asllength.c revision 217365
1118611Snjl
2118611Snjl/******************************************************************************
3118611Snjl *
4118611Snjl * Module Name: asllength - Tree walk to determine package and opcode lengths
5118611Snjl *
6118611Snjl *****************************************************************************/
7118611Snjl
8217365Sjkim/*
9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
10118611Snjl * All rights reserved.
11118611Snjl *
12217365Sjkim * Redistribution and use in source and binary forms, with or without
13217365Sjkim * modification, are permitted provided that the following conditions
14217365Sjkim * are met:
15217365Sjkim * 1. Redistributions of source code must retain the above copyright
16217365Sjkim *    notice, this list of conditions, and the following disclaimer,
17217365Sjkim *    without modification.
18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21217365Sjkim *    including a substantially similar Disclaimer requirement for further
22217365Sjkim *    binary redistribution.
23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24217365Sjkim *    of any contributors may be used to endorse or promote products derived
25217365Sjkim *    from this software without specific prior written permission.
26118611Snjl *
27217365Sjkim * Alternatively, this software may be distributed under the terms of the
28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29217365Sjkim * Software Foundation.
30118611Snjl *
31217365Sjkim * NO WARRANTY
32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
43217365Sjkim */
44118611Snjl
45118611Snjl
46151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
47118611Snjl#include "aslcompiler.y.h"
48193529Sjkim#include <contrib/dev/acpica/include/amlcode.h>
49118611Snjl
50118611Snjl
51118611Snjl#define _COMPONENT          ACPI_COMPILER
52118611Snjl        ACPI_MODULE_NAME    ("asllength")
53118611Snjl
54151937Sjkim/* Local prototypes */
55118611Snjl
56151937Sjkimstatic UINT8
57151937SjkimCgGetPackageLenByteCount (
58151937Sjkim    ACPI_PARSE_OBJECT       *Op,
59151937Sjkim    UINT32                  PackageLength);
60151937Sjkim
61151937Sjkimstatic void
62151937SjkimCgGenerateAmlOpcodeLength (
63151937Sjkim    ACPI_PARSE_OBJECT       *Op);
64151937Sjkim
65151937Sjkim
66151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS
67151937Sjkimvoid
68151937SjkimLnAdjustLengthToRoot (
69151937Sjkim    ACPI_PARSE_OBJECT       *Op,
70151937Sjkim    UINT32                  LengthDelta);
71151937Sjkim#endif
72151937Sjkim
73151937Sjkim
74118611Snjl/*******************************************************************************
75118611Snjl *
76118611Snjl * FUNCTION:    LnInitLengthsWalk
77118611Snjl *
78118611Snjl * PARAMETERS:  ASL_WALK_CALLBACK
79118611Snjl *
80118611Snjl * RETURN:      Status
81118611Snjl *
82118611Snjl * DESCRIPTION: Walk callback to initialize (and re-initialize) the node
83118611Snjl *              subtree length(s) to zero.  The Subtree lengths are bubbled
84118611Snjl *              up to the root node in order to get a total AML length.
85118611Snjl *
86118611Snjl ******************************************************************************/
87118611Snjl
88118611SnjlACPI_STATUS
89118611SnjlLnInitLengthsWalk (
90118611Snjl    ACPI_PARSE_OBJECT       *Op,
91118611Snjl    UINT32                  Level,
92118611Snjl    void                    *Context)
93118611Snjl{
94118611Snjl
95118611Snjl    Op->Asl.AmlSubtreeLength = 0;
96118611Snjl    return (AE_OK);
97118611Snjl}
98118611Snjl
99118611Snjl
100118611Snjl/*******************************************************************************
101118611Snjl *
102118611Snjl * FUNCTION:    LnPackageLengthWalk
103118611Snjl *
104118611Snjl * PARAMETERS:  ASL_WALK_CALLBACK
105118611Snjl *
106118611Snjl * RETURN:      Status
107118611Snjl *
108118611Snjl * DESCRIPTION: Walk callback to calculate the total AML length.
109118611Snjl *              1) Calculate the AML lengths (opcode, package length, etc.) for
110118611Snjl *                 THIS node.
111118611Snjl *              2) Bubbble up all of these lengths to the parent node by summing
112118611Snjl *                 them all into the parent subtree length.
113118611Snjl *
114118611Snjl * Note:  The SubtreeLength represents the total AML length of all child nodes
115118611Snjl *        in all subtrees under a given node.  Therefore, once this walk is
116118611Snjl *        complete, the Root Node subtree length is the AML length of the entire
117118611Snjl *        tree (and thus, the entire ACPI table)
118118611Snjl *
119118611Snjl ******************************************************************************/
120118611Snjl
121118611SnjlACPI_STATUS
122118611SnjlLnPackageLengthWalk (
123118611Snjl    ACPI_PARSE_OBJECT       *Op,
124118611Snjl    UINT32                  Level,
125118611Snjl    void                    *Context)
126118611Snjl{
127118611Snjl
128118611Snjl    /* Generate the AML lengths for this node */
129118611Snjl
130118611Snjl    CgGenerateAmlLengths (Op);
131118611Snjl
132118611Snjl    /* Bubble up all lengths (this node and all below it) to the parent */
133118611Snjl
134118611Snjl    if ((Op->Asl.Parent) &&
135118611Snjl        (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
136118611Snjl    {
137118611Snjl        Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength +
138118611Snjl                                           Op->Asl.AmlOpcodeLength +
139118611Snjl                                           Op->Asl.AmlPkgLenBytes +
140118611Snjl                                           Op->Asl.AmlSubtreeLength);
141118611Snjl    }
142118611Snjl    return (AE_OK);
143118611Snjl}
144118611Snjl
145118611Snjl
146118611Snjl/*******************************************************************************
147118611Snjl *
148118611Snjl * FUNCTION:    CgGetPackageLenByteCount
149118611Snjl *
150151937Sjkim * PARAMETERS:  Op              - Parse node
151118611Snjl *              PackageLength   - Length to be encoded
152118611Snjl *
153118611Snjl * RETURN:      Required length of the package length encoding
154118611Snjl *
155118611Snjl * DESCRIPTION: Calculate the number of bytes required to encode the given
156118611Snjl *              package length.
157118611Snjl *
158118611Snjl ******************************************************************************/
159118611Snjl
160151937Sjkimstatic UINT8
161118611SnjlCgGetPackageLenByteCount (
162118611Snjl    ACPI_PARSE_OBJECT       *Op,
163118611Snjl    UINT32                  PackageLength)
164118611Snjl{
165118611Snjl
166118611Snjl    /*
167118611Snjl     * Determine the number of bytes required to encode the package length
168118611Snjl     * Note: the package length includes the number of bytes used to encode
169118611Snjl     * the package length, so we must account for this also.
170118611Snjl     */
171118611Snjl    if (PackageLength <= (0x0000003F - 1))
172118611Snjl    {
173118611Snjl        return (1);
174118611Snjl    }
175118611Snjl    else if (PackageLength <= (0x00000FFF - 2))
176118611Snjl    {
177118611Snjl        return (2);
178118611Snjl    }
179118611Snjl    else if (PackageLength <= (0x000FFFFF - 3))
180118611Snjl    {
181118611Snjl        return (3);
182118611Snjl    }
183118611Snjl    else if (PackageLength <= (0x0FFFFFFF - 4))
184118611Snjl    {
185118611Snjl        return (4);
186118611Snjl    }
187118611Snjl    else
188118611Snjl    {
189118611Snjl        /* Fatal error - the package length is too large to encode */
190118611Snjl
191118611Snjl        AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL);
192118611Snjl    }
193118611Snjl
194118611Snjl    return (0);
195118611Snjl}
196118611Snjl
197118611Snjl
198118611Snjl/*******************************************************************************
199118611Snjl *
200118611Snjl * FUNCTION:    CgGenerateAmlOpcodeLength
201118611Snjl *
202151937Sjkim * PARAMETERS:  Op          - Parse node whose AML opcode lengths will be
203118611Snjl *                            calculated
204118611Snjl *
205118611Snjl * RETURN:      None.
206118611Snjl *
207118611Snjl * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
208118611Snjl *              fields for this node.
209118611Snjl *
210118611Snjl ******************************************************************************/
211118611Snjl
212151937Sjkimstatic void
213118611SnjlCgGenerateAmlOpcodeLength (
214118611Snjl    ACPI_PARSE_OBJECT       *Op)
215118611Snjl{
216118611Snjl
217118611Snjl    /* Check for two-byte opcode */
218118611Snjl
219118611Snjl    if (Op->Asl.AmlOpcode > 0x00FF)
220118611Snjl    {
221118611Snjl        Op->Asl.AmlOpcodeLength = 2;
222118611Snjl    }
223118611Snjl    else
224118611Snjl    {
225118611Snjl        Op->Asl.AmlOpcodeLength = 1;
226118611Snjl    }
227118611Snjl
228118611Snjl    /* Does this opcode have an associated "PackageLength" field? */
229118611Snjl
230118611Snjl    Op->Asl.AmlPkgLenBytes = 0;
231118611Snjl    if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
232118611Snjl    {
233151937Sjkim        Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (
234151937Sjkim                                    Op, Op->Asl.AmlSubtreeLength);
235118611Snjl    }
236118611Snjl
237118611Snjl    /* Data opcode lengths are easy */
238118611Snjl
239118611Snjl    switch (Op->Asl.AmlOpcode)
240118611Snjl    {
241118611Snjl    case AML_BYTE_OP:
242118611Snjl
243118611Snjl        Op->Asl.AmlLength = 1;
244118611Snjl        break;
245118611Snjl
246118611Snjl    case AML_WORD_OP:
247118611Snjl
248118611Snjl        Op->Asl.AmlLength = 2;
249118611Snjl        break;
250118611Snjl
251118611Snjl    case AML_DWORD_OP:
252118611Snjl
253118611Snjl        Op->Asl.AmlLength = 4;
254118611Snjl        break;
255118611Snjl
256118611Snjl    case AML_QWORD_OP:
257118611Snjl
258118611Snjl        Op->Asl.AmlLength = 8;
259118611Snjl        break;
260118611Snjl
261118611Snjl    default:
262118611Snjl        /* All data opcodes must be above */
263118611Snjl        break;
264118611Snjl    }
265118611Snjl}
266118611Snjl
267118611Snjl
268118611Snjl/*******************************************************************************
269118611Snjl *
270118611Snjl * FUNCTION:    CgGenerateAmlLengths
271118611Snjl *
272118611Snjl * PARAMETERS:  Op        - Parse node
273118611Snjl *
274118611Snjl * RETURN:      None.
275118611Snjl *
276118611Snjl * DESCRIPTION: Generate internal length fields based on the AML opcode or
277118611Snjl *              parse opcode.
278118611Snjl *
279118611Snjl ******************************************************************************/
280118611Snjl
281118611Snjlvoid
282118611SnjlCgGenerateAmlLengths (
283118611Snjl    ACPI_PARSE_OBJECT       *Op)
284118611Snjl{
285118611Snjl    char                    *Buffer;
286118611Snjl    ACPI_STATUS             Status;
287118611Snjl
288118611Snjl
289118611Snjl    switch (Op->Asl.AmlOpcode)
290118611Snjl    {
291118611Snjl    case AML_RAW_DATA_BYTE:
292118611Snjl
293118611Snjl        Op->Asl.AmlOpcodeLength = 0;
294118611Snjl        Op->Asl.AmlLength = 1;
295118611Snjl        return;
296118611Snjl
297118611Snjl    case AML_RAW_DATA_WORD:
298118611Snjl
299118611Snjl        Op->Asl.AmlOpcodeLength = 0;
300118611Snjl        Op->Asl.AmlLength = 2;
301118611Snjl        return;
302118611Snjl
303118611Snjl    case AML_RAW_DATA_DWORD:
304118611Snjl
305118611Snjl        Op->Asl.AmlOpcodeLength = 0;
306118611Snjl        Op->Asl.AmlLength = 4;
307118611Snjl        return;
308118611Snjl
309118611Snjl    case AML_RAW_DATA_QWORD:
310118611Snjl
311118611Snjl        Op->Asl.AmlOpcodeLength = 0;
312118611Snjl        Op->Asl.AmlLength = 8;
313118611Snjl        return;
314118611Snjl
315118611Snjl    case AML_RAW_DATA_BUFFER:
316118611Snjl
317118611Snjl        /* Aml length is/was set by creator */
318118611Snjl
319118611Snjl        Op->Asl.AmlOpcodeLength = 0;
320118611Snjl        return;
321118611Snjl
322118611Snjl    case AML_RAW_DATA_CHAIN:
323118611Snjl
324118611Snjl        /* Aml length is/was set by creator */
325118611Snjl
326118611Snjl        Op->Asl.AmlOpcodeLength = 0;
327118611Snjl        return;
328118611Snjl
329118611Snjl    default:
330118611Snjl        break;
331118611Snjl    }
332118611Snjl
333118611Snjl    switch (Op->Asl.ParseOpcode)
334118611Snjl    {
335118611Snjl    case PARSEOP_DEFINITIONBLOCK:
336118611Snjl
337151937Sjkim        Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) +
338151937Sjkim                            Op->Asl.AmlSubtreeLength;
339118611Snjl        break;
340118611Snjl
341118611Snjl    case PARSEOP_NAMESEG:
342118611Snjl
343118611Snjl        Op->Asl.AmlOpcodeLength = 0;
344118611Snjl        Op->Asl.AmlLength = 4;
345118611Snjl        Op->Asl.ExternalName = Op->Asl.Value.String;
346118611Snjl        break;
347118611Snjl
348118611Snjl    case PARSEOP_NAMESTRING:
349118611Snjl    case PARSEOP_METHODCALL:
350118611Snjl
351118611Snjl        if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED)
352118611Snjl        {
353118611Snjl            break;
354118611Snjl        }
355118611Snjl
356118611Snjl        Op->Asl.AmlOpcodeLength = 0;
357118611Snjl        Status = UtInternalizeName (Op->Asl.Value.String, &Buffer);
358118611Snjl        if (ACPI_FAILURE (Status))
359118611Snjl        {
360118611Snjl            DbgPrint (ASL_DEBUG_OUTPUT,
361118611Snjl                "Failure from internalize name %X\n", Status);
362118611Snjl            break;
363118611Snjl        }
364118611Snjl
365118611Snjl        Op->Asl.ExternalName = Op->Asl.Value.String;
366118611Snjl        Op->Asl.Value.String = Buffer;
367118611Snjl        Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED;
368118611Snjl
369118611Snjl        Op->Asl.AmlLength = strlen (Buffer);
370118611Snjl
371118611Snjl        /*
372118611Snjl         * Check for single backslash reference to root,
373118611Snjl         * make it a null terminated string in the AML
374118611Snjl         */
375118611Snjl        if (Op->Asl.AmlLength == 1)
376118611Snjl        {
377118611Snjl            Op->Asl.AmlLength = 2;
378118611Snjl        }
379118611Snjl        break;
380118611Snjl
381118611Snjl    case PARSEOP_STRING_LITERAL:
382118611Snjl
383118611Snjl        Op->Asl.AmlOpcodeLength = 1;
384151937Sjkim
385151937Sjkim        /* Get null terminator */
386151937Sjkim
387151937Sjkim        Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1;
388118611Snjl        break;
389118611Snjl
390118611Snjl    case PARSEOP_PACKAGE_LENGTH:
391118611Snjl
392118611Snjl        Op->Asl.AmlOpcodeLength = 0;
393151937Sjkim        Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op,
394151937Sjkim                                    (UINT32) Op->Asl.Value.Integer);
395118611Snjl        break;
396118611Snjl
397118611Snjl    case PARSEOP_RAW_DATA:
398118611Snjl
399118611Snjl        Op->Asl.AmlOpcodeLength = 0;
400118611Snjl        break;
401118611Snjl
402118611Snjl    case PARSEOP_DEFAULT_ARG:
403118611Snjl    case PARSEOP_EXTERNAL:
404118611Snjl    case PARSEOP_INCLUDE:
405118611Snjl    case PARSEOP_INCLUDE_END:
406118611Snjl
407118611Snjl        /* Ignore the "default arg" nodes, they are extraneous at this point */
408118611Snjl
409118611Snjl        break;
410118611Snjl
411118611Snjl    default:
412118611Snjl
413118611Snjl        CgGenerateAmlOpcodeLength (Op);
414118611Snjl        break;
415118611Snjl    }
416118611Snjl}
417118611Snjl
418118611Snjl
419151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS
420151937Sjkim/*******************************************************************************
421151937Sjkim *
422151937Sjkim * FUNCTION:    LnAdjustLengthToRoot
423151937Sjkim *
424151937Sjkim * PARAMETERS:  Op      - Node whose Length was changed
425151937Sjkim *
426151937Sjkim * RETURN:      None.
427151937Sjkim *
428151937Sjkim * DESCRIPTION: Change the Subtree length of the given node, and bubble the
429151937Sjkim *              change all the way up to the root node.  This allows for
430151937Sjkim *              last second changes to a package length (for example, if the
431151937Sjkim *              package length encoding gets shorter or longer.)
432151937Sjkim *
433151937Sjkim ******************************************************************************/
434151937Sjkim
435151937Sjkimvoid
436151937SjkimLnAdjustLengthToRoot (
437151937Sjkim    ACPI_PARSE_OBJECT       *SubtreeOp,
438151937Sjkim    UINT32                  LengthDelta)
439151937Sjkim{
440151937Sjkim    ACPI_PARSE_OBJECT       *Op;
441151937Sjkim
442151937Sjkim
443151937Sjkim    /* Adjust all subtree lengths up to the root */
444151937Sjkim
445151937Sjkim    Op = SubtreeOp->Asl.Parent;
446151937Sjkim    while (Op)
447151937Sjkim    {
448151937Sjkim        Op->Asl.AmlSubtreeLength -= LengthDelta;
449151937Sjkim        Op = Op->Asl.Parent;
450151937Sjkim    }
451151937Sjkim
452151937Sjkim    /* Adjust the global table length */
453151937Sjkim
454151937Sjkim    Gbl_TableLength -= LengthDelta;
455151937Sjkim}
456151937Sjkim#endif
457151937Sjkim
458151937Sjkim
459