1118611Snjl/******************************************************************************
2118611Snjl *
3118611Snjl * Module Name: asllength - Tree walk to determine package and opcode lengths
4118611Snjl *
5118611Snjl *****************************************************************************/
6118611Snjl
7217365Sjkim/*
8281075Sdim * Copyright (C) 2000 - 2015, Intel Corp.
9118611Snjl * All rights reserved.
10118611Snjl *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25118611Snjl *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29118611Snjl *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43118611Snjl
44151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45118611Snjl#include "aslcompiler.y.h"
46193529Sjkim#include <contrib/dev/acpica/include/amlcode.h>
47118611Snjl
48118611Snjl
49118611Snjl#define _COMPONENT          ACPI_COMPILER
50118611Snjl        ACPI_MODULE_NAME    ("asllength")
51118611Snjl
52151937Sjkim/* Local prototypes */
53118611Snjl
54151937Sjkimstatic UINT8
55151937SjkimCgGetPackageLenByteCount (
56151937Sjkim    ACPI_PARSE_OBJECT       *Op,
57151937Sjkim    UINT32                  PackageLength);
58151937Sjkim
59151937Sjkimstatic void
60151937SjkimCgGenerateAmlOpcodeLength (
61151937Sjkim    ACPI_PARSE_OBJECT       *Op);
62151937Sjkim
63151937Sjkim
64151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS
65151937Sjkimvoid
66151937SjkimLnAdjustLengthToRoot (
67151937Sjkim    ACPI_PARSE_OBJECT       *Op,
68151937Sjkim    UINT32                  LengthDelta);
69151937Sjkim#endif
70151937Sjkim
71151937Sjkim
72118611Snjl/*******************************************************************************
73118611Snjl *
74118611Snjl * FUNCTION:    LnInitLengthsWalk
75118611Snjl *
76118611Snjl * PARAMETERS:  ASL_WALK_CALLBACK
77118611Snjl *
78118611Snjl * RETURN:      Status
79118611Snjl *
80118611Snjl * DESCRIPTION: Walk callback to initialize (and re-initialize) the node
81241973Sjkim *              subtree length(s) to zero. The Subtree lengths are bubbled
82118611Snjl *              up to the root node in order to get a total AML length.
83118611Snjl *
84118611Snjl ******************************************************************************/
85118611Snjl
86118611SnjlACPI_STATUS
87118611SnjlLnInitLengthsWalk (
88118611Snjl    ACPI_PARSE_OBJECT       *Op,
89118611Snjl    UINT32                  Level,
90118611Snjl    void                    *Context)
91118611Snjl{
92118611Snjl
93118611Snjl    Op->Asl.AmlSubtreeLength = 0;
94118611Snjl    return (AE_OK);
95118611Snjl}
96118611Snjl
97118611Snjl
98118611Snjl/*******************************************************************************
99118611Snjl *
100118611Snjl * FUNCTION:    LnPackageLengthWalk
101118611Snjl *
102118611Snjl * PARAMETERS:  ASL_WALK_CALLBACK
103118611Snjl *
104118611Snjl * RETURN:      Status
105118611Snjl *
106118611Snjl * DESCRIPTION: Walk callback to calculate the total AML length.
107118611Snjl *              1) Calculate the AML lengths (opcode, package length, etc.) for
108118611Snjl *                 THIS node.
109118611Snjl *              2) Bubbble up all of these lengths to the parent node by summing
110118611Snjl *                 them all into the parent subtree length.
111118611Snjl *
112118611Snjl * Note:  The SubtreeLength represents the total AML length of all child nodes
113241973Sjkim *        in all subtrees under a given node. Therefore, once this walk is
114118611Snjl *        complete, the Root Node subtree length is the AML length of the entire
115118611Snjl *        tree (and thus, the entire ACPI table)
116118611Snjl *
117118611Snjl ******************************************************************************/
118118611Snjl
119118611SnjlACPI_STATUS
120118611SnjlLnPackageLengthWalk (
121118611Snjl    ACPI_PARSE_OBJECT       *Op,
122118611Snjl    UINT32                  Level,
123118611Snjl    void                    *Context)
124118611Snjl{
125118611Snjl
126118611Snjl    /* Generate the AML lengths for this node */
127118611Snjl
128118611Snjl    CgGenerateAmlLengths (Op);
129118611Snjl
130118611Snjl    /* Bubble up all lengths (this node and all below it) to the parent */
131118611Snjl
132118611Snjl    if ((Op->Asl.Parent) &&
133118611Snjl        (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
134118611Snjl    {
135118611Snjl        Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength +
136118611Snjl                                           Op->Asl.AmlOpcodeLength +
137118611Snjl                                           Op->Asl.AmlPkgLenBytes +
138118611Snjl                                           Op->Asl.AmlSubtreeLength);
139118611Snjl    }
140118611Snjl    return (AE_OK);
141118611Snjl}
142118611Snjl
143118611Snjl
144118611Snjl/*******************************************************************************
145118611Snjl *
146118611Snjl * FUNCTION:    CgGetPackageLenByteCount
147118611Snjl *
148151937Sjkim * PARAMETERS:  Op              - Parse node
149118611Snjl *              PackageLength   - Length to be encoded
150118611Snjl *
151118611Snjl * RETURN:      Required length of the package length encoding
152118611Snjl *
153118611Snjl * DESCRIPTION: Calculate the number of bytes required to encode the given
154118611Snjl *              package length.
155118611Snjl *
156118611Snjl ******************************************************************************/
157118611Snjl
158151937Sjkimstatic UINT8
159118611SnjlCgGetPackageLenByteCount (
160118611Snjl    ACPI_PARSE_OBJECT       *Op,
161118611Snjl    UINT32                  PackageLength)
162118611Snjl{
163118611Snjl
164118611Snjl    /*
165118611Snjl     * Determine the number of bytes required to encode the package length
166118611Snjl     * Note: the package length includes the number of bytes used to encode
167118611Snjl     * the package length, so we must account for this also.
168118611Snjl     */
169118611Snjl    if (PackageLength <= (0x0000003F - 1))
170118611Snjl    {
171118611Snjl        return (1);
172118611Snjl    }
173118611Snjl    else if (PackageLength <= (0x00000FFF - 2))
174118611Snjl    {
175118611Snjl        return (2);
176118611Snjl    }
177118611Snjl    else if (PackageLength <= (0x000FFFFF - 3))
178118611Snjl    {
179118611Snjl        return (3);
180118611Snjl    }
181118611Snjl    else if (PackageLength <= (0x0FFFFFFF - 4))
182118611Snjl    {
183118611Snjl        return (4);
184118611Snjl    }
185118611Snjl    else
186118611Snjl    {
187118611Snjl        /* Fatal error - the package length is too large to encode */
188118611Snjl
189118611Snjl        AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL);
190118611Snjl    }
191118611Snjl
192118611Snjl    return (0);
193118611Snjl}
194118611Snjl
195118611Snjl
196118611Snjl/*******************************************************************************
197118611Snjl *
198118611Snjl * FUNCTION:    CgGenerateAmlOpcodeLength
199118611Snjl *
200151937Sjkim * PARAMETERS:  Op          - Parse node whose AML opcode lengths will be
201118611Snjl *                            calculated
202118611Snjl *
203118611Snjl * RETURN:      None.
204118611Snjl *
205118611Snjl * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
206118611Snjl *              fields for this node.
207118611Snjl *
208118611Snjl ******************************************************************************/
209118611Snjl
210151937Sjkimstatic void
211118611SnjlCgGenerateAmlOpcodeLength (
212118611Snjl    ACPI_PARSE_OBJECT       *Op)
213118611Snjl{
214118611Snjl
215118611Snjl    /* Check for two-byte opcode */
216118611Snjl
217118611Snjl    if (Op->Asl.AmlOpcode > 0x00FF)
218118611Snjl    {
219118611Snjl        Op->Asl.AmlOpcodeLength = 2;
220118611Snjl    }
221118611Snjl    else
222118611Snjl    {
223118611Snjl        Op->Asl.AmlOpcodeLength = 1;
224118611Snjl    }
225118611Snjl
226118611Snjl    /* Does this opcode have an associated "PackageLength" field? */
227118611Snjl
228118611Snjl    Op->Asl.AmlPkgLenBytes = 0;
229118611Snjl    if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
230118611Snjl    {
231151937Sjkim        Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (
232151937Sjkim                                    Op, Op->Asl.AmlSubtreeLength);
233118611Snjl    }
234118611Snjl
235118611Snjl    /* Data opcode lengths are easy */
236118611Snjl
237118611Snjl    switch (Op->Asl.AmlOpcode)
238118611Snjl    {
239118611Snjl    case AML_BYTE_OP:
240118611Snjl
241118611Snjl        Op->Asl.AmlLength = 1;
242118611Snjl        break;
243118611Snjl
244118611Snjl    case AML_WORD_OP:
245118611Snjl
246118611Snjl        Op->Asl.AmlLength = 2;
247118611Snjl        break;
248118611Snjl
249118611Snjl    case AML_DWORD_OP:
250118611Snjl
251118611Snjl        Op->Asl.AmlLength = 4;
252118611Snjl        break;
253118611Snjl
254118611Snjl    case AML_QWORD_OP:
255118611Snjl
256118611Snjl        Op->Asl.AmlLength = 8;
257118611Snjl        break;
258118611Snjl
259118611Snjl    default:
260250838Sjkim
261118611Snjl        /* All data opcodes must be above */
262118611Snjl        break;
263118611Snjl    }
264118611Snjl}
265118611Snjl
266118611Snjl
267118611Snjl/*******************************************************************************
268118611Snjl *
269118611Snjl * FUNCTION:    CgGenerateAmlLengths
270118611Snjl *
271118611Snjl * PARAMETERS:  Op        - Parse node
272118611Snjl *
273118611Snjl * RETURN:      None.
274118611Snjl *
275118611Snjl * DESCRIPTION: Generate internal length fields based on the AML opcode or
276118611Snjl *              parse opcode.
277118611Snjl *
278118611Snjl ******************************************************************************/
279118611Snjl
280118611Snjlvoid
281118611SnjlCgGenerateAmlLengths (
282118611Snjl    ACPI_PARSE_OBJECT       *Op)
283118611Snjl{
284118611Snjl    char                    *Buffer;
285118611Snjl    ACPI_STATUS             Status;
286118611Snjl
287118611Snjl
288118611Snjl    switch (Op->Asl.AmlOpcode)
289118611Snjl    {
290118611Snjl    case AML_RAW_DATA_BYTE:
291118611Snjl
292118611Snjl        Op->Asl.AmlOpcodeLength = 0;
293118611Snjl        Op->Asl.AmlLength = 1;
294118611Snjl        return;
295118611Snjl
296118611Snjl    case AML_RAW_DATA_WORD:
297118611Snjl
298118611Snjl        Op->Asl.AmlOpcodeLength = 0;
299118611Snjl        Op->Asl.AmlLength = 2;
300118611Snjl        return;
301118611Snjl
302118611Snjl    case AML_RAW_DATA_DWORD:
303118611Snjl
304118611Snjl        Op->Asl.AmlOpcodeLength = 0;
305118611Snjl        Op->Asl.AmlLength = 4;
306118611Snjl        return;
307118611Snjl
308118611Snjl    case AML_RAW_DATA_QWORD:
309118611Snjl
310118611Snjl        Op->Asl.AmlOpcodeLength = 0;
311118611Snjl        Op->Asl.AmlLength = 8;
312118611Snjl        return;
313118611Snjl
314118611Snjl    case AML_RAW_DATA_BUFFER:
315118611Snjl
316118611Snjl        /* Aml length is/was set by creator */
317118611Snjl
318118611Snjl        Op->Asl.AmlOpcodeLength = 0;
319118611Snjl        return;
320118611Snjl
321118611Snjl    case AML_RAW_DATA_CHAIN:
322118611Snjl
323118611Snjl        /* Aml length is/was set by creator */
324118611Snjl
325118611Snjl        Op->Asl.AmlOpcodeLength = 0;
326118611Snjl        return;
327118611Snjl
328118611Snjl    default:
329250838Sjkim
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
429241973Sjkim *              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
457