1118611Snjl/******************************************************************************
2118611Snjl *
3118611Snjl * Module Name: aslopcode - AML opcode generation
4118611Snjl *
5118611Snjl *****************************************************************************/
6118611Snjl
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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#define _COMPONENT          ACPI_COMPILER
49118611Snjl        ACPI_MODULE_NAME    ("aslopcodes")
50118611Snjl
51118611Snjl
52151937Sjkim/* Local prototypes */
53151937Sjkim
54151937Sjkimstatic void
55151937SjkimOpcDoAccessAs (
56151937Sjkim    ACPI_PARSE_OBJECT       *Op);
57151937Sjkim
58151937Sjkimstatic void
59228110SjkimOpcDoConnection (
60228110Sjkim    ACPI_PARSE_OBJECT       *Op);
61228110Sjkim
62228110Sjkimstatic void
63151937SjkimOpcDoUnicode (
64151937Sjkim    ACPI_PARSE_OBJECT       *Op);
65151937Sjkim
66151937Sjkimstatic void
67151937SjkimOpcDoEisaId (
68151937Sjkim    ACPI_PARSE_OBJECT       *Op);
69151937Sjkim
70151937Sjkimstatic void
71151937SjkimOpcDoUuId (
72151937Sjkim    ACPI_PARSE_OBJECT       *Op);
73151937Sjkim
74151937Sjkim
75118611Snjl/*******************************************************************************
76118611Snjl *
77151937Sjkim * FUNCTION:    OpcAmlOpcodeUpdateWalk
78151937Sjkim *
79151937Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
80151937Sjkim *
81151937Sjkim * RETURN:      Status
82151937Sjkim *
83151937Sjkim * DESCRIPTION: Opcode update walk, ascending callback
84151937Sjkim *
85151937Sjkim ******************************************************************************/
86151937Sjkim
87151937SjkimACPI_STATUS
88151937SjkimOpcAmlOpcodeUpdateWalk (
89151937Sjkim    ACPI_PARSE_OBJECT       *Op,
90151937Sjkim    UINT32                  Level,
91151937Sjkim    void                    *Context)
92151937Sjkim{
93151937Sjkim
94151937Sjkim    /*
95151937Sjkim     * Handle the Package() case where the actual opcode cannot be determined
96151937Sjkim     * until the PackageLength operand has been folded and minimized.
97151937Sjkim     * (PackageOp versus VarPackageOp)
98151937Sjkim     *
99151937Sjkim     * This is (as of ACPI 3.0) the only case where the AML opcode can change
100151937Sjkim     * based upon the value of a parameter.
101151937Sjkim     *
102151937Sjkim     * The parser always inserts a VarPackage opcode, which can possibly be
103151937Sjkim     * optimized to a Package opcode.
104151937Sjkim     */
105151937Sjkim    if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
106151937Sjkim    {
107151937Sjkim        OpnDoPackage (Op);
108151937Sjkim    }
109151937Sjkim
110151937Sjkim    return (AE_OK);
111151937Sjkim}
112151937Sjkim
113151937Sjkim
114151937Sjkim/*******************************************************************************
115151937Sjkim *
116118611Snjl * FUNCTION:    OpcAmlOpcodeWalk
117118611Snjl *
118118611Snjl * PARAMETERS:  ASL_WALK_CALLBACK
119118611Snjl *
120118611Snjl * RETURN:      Status
121118611Snjl *
122118611Snjl * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
123118611Snjl *              operands.
124118611Snjl *
125118611Snjl ******************************************************************************/
126118611Snjl
127118611SnjlACPI_STATUS
128118611SnjlOpcAmlOpcodeWalk (
129118611Snjl    ACPI_PARSE_OBJECT       *Op,
130118611Snjl    UINT32                  Level,
131118611Snjl    void                    *Context)
132118611Snjl{
133118611Snjl
134118611Snjl    TotalParseNodes++;
135118611Snjl
136118611Snjl    OpcGenerateAmlOpcode (Op);
137118611Snjl    OpnGenerateAmlOperands (Op);
138118611Snjl    return (AE_OK);
139118611Snjl}
140118611Snjl
141118611Snjl
142118611Snjl/*******************************************************************************
143118611Snjl *
144118611Snjl * FUNCTION:    OpcGetIntegerWidth
145118611Snjl *
146118611Snjl * PARAMETERS:  Op          - DEFINITION BLOCK op
147118611Snjl *
148118611Snjl * RETURN:      none
149118611Snjl *
150118611Snjl * DESCRIPTION: Extract integer width from the table revision
151118611Snjl *
152118611Snjl ******************************************************************************/
153118611Snjl
154118611Snjlvoid
155118611SnjlOpcGetIntegerWidth (
156118611Snjl    ACPI_PARSE_OBJECT       *Op)
157118611Snjl{
158118611Snjl    ACPI_PARSE_OBJECT       *Child;
159118611Snjl
160151937Sjkim
161118611Snjl    if (!Op)
162118611Snjl    {
163118611Snjl        return;
164118611Snjl    }
165118611Snjl
166151937Sjkim    if (Gbl_RevisionOverride)
167151937Sjkim    {
168151937Sjkim        AcpiUtSetIntegerWidth (Gbl_RevisionOverride);
169151937Sjkim    }
170151937Sjkim    else
171151937Sjkim    {
172151937Sjkim        Child = Op->Asl.Child;
173151937Sjkim        Child = Child->Asl.Next;
174151937Sjkim        Child = Child->Asl.Next;
175118611Snjl
176151937Sjkim        /* Use the revision to set the integer width */
177118611Snjl
178151937Sjkim        AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
179151937Sjkim    }
180118611Snjl}
181118611Snjl
182118611Snjl
183118611Snjl/*******************************************************************************
184118611Snjl *
185118611Snjl * FUNCTION:    OpcSetOptimalIntegerSize
186118611Snjl *
187118611Snjl * PARAMETERS:  Op        - A parse tree node
188118611Snjl *
189241973Sjkim * RETURN:      Integer width, in bytes. Also sets the node AML opcode to the
190118611Snjl *              optimal integer AML prefix opcode.
191118611Snjl *
192241973Sjkim * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading
193118611Snjl *              zeros can be truncated to squeeze the integer into the
194118611Snjl *              minimal number of AML bytes.
195118611Snjl *
196118611Snjl ******************************************************************************/
197118611Snjl
198118611SnjlUINT32
199118611SnjlOpcSetOptimalIntegerSize (
200118611Snjl    ACPI_PARSE_OBJECT       *Op)
201118611Snjl{
202118611Snjl
203151937Sjkim#if 0
204151937Sjkim    /*
205151937Sjkim     * TBD: - we don't want to optimize integers in the block header, but the
206151937Sjkim     * code below does not work correctly.
207151937Sjkim     */
208138287Smarks    if (Op->Asl.Parent &&
209138287Smarks        Op->Asl.Parent->Asl.Parent &&
210306536Sjkim       (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK))
211138287Smarks    {
212241973Sjkim        return (0);
213138287Smarks    }
214151937Sjkim#endif
215138287Smarks
216118611Snjl    /*
217118611Snjl     * Check for the special AML integers first - Zero, One, Ones.
218118611Snjl     * These are single-byte opcodes that are the smallest possible
219118611Snjl     * representation of an integer.
220118611Snjl     *
221118611Snjl     * This optimization is optional.
222118611Snjl     */
223118611Snjl    if (Gbl_IntegerOptimizationFlag)
224118611Snjl    {
225118611Snjl        switch (Op->Asl.Value.Integer)
226118611Snjl        {
227118611Snjl        case 0:
228118611Snjl
229118611Snjl            Op->Asl.AmlOpcode = AML_ZERO_OP;
230151937Sjkim            AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
231151937Sjkim                Op, "Zero");
232241973Sjkim            return (1);
233118611Snjl
234118611Snjl        case 1:
235118611Snjl
236118611Snjl            Op->Asl.AmlOpcode = AML_ONE_OP;
237151937Sjkim            AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
238151937Sjkim                Op, "One");
239241973Sjkim            return (1);
240118611Snjl
241118611Snjl        case ACPI_UINT32_MAX:
242118611Snjl
243118611Snjl            /* Check for table integer width (32 or 64) */
244118611Snjl
245118611Snjl            if (AcpiGbl_IntegerByteWidth == 4)
246118611Snjl            {
247118611Snjl                Op->Asl.AmlOpcode = AML_ONES_OP;
248151937Sjkim                AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
249151937Sjkim                    Op, "Ones");
250241973Sjkim                return (1);
251118611Snjl            }
252118611Snjl            break;
253118611Snjl
254202771Sjkim        case ACPI_UINT64_MAX:
255118611Snjl
256118611Snjl            /* Check for table integer width (32 or 64) */
257118611Snjl
258118611Snjl            if (AcpiGbl_IntegerByteWidth == 8)
259118611Snjl            {
260118611Snjl                Op->Asl.AmlOpcode = AML_ONES_OP;
261151937Sjkim                AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
262151937Sjkim                    Op, "Ones");
263241973Sjkim                return (1);
264118611Snjl            }
265118611Snjl            break;
266118611Snjl
267118611Snjl        default:
268250838Sjkim
269118611Snjl            break;
270118611Snjl        }
271118611Snjl    }
272118611Snjl
273118611Snjl    /* Find the best fit using the various AML integer prefixes */
274118611Snjl
275118611Snjl    if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
276118611Snjl    {
277118611Snjl        Op->Asl.AmlOpcode = AML_BYTE_OP;
278241973Sjkim        return (1);
279118611Snjl    }
280306536Sjkim
281118611Snjl    if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
282118611Snjl    {
283118611Snjl        Op->Asl.AmlOpcode = AML_WORD_OP;
284241973Sjkim        return (2);
285118611Snjl    }
286306536Sjkim
287118611Snjl    if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
288118611Snjl    {
289118611Snjl        Op->Asl.AmlOpcode = AML_DWORD_OP;
290241973Sjkim        return (4);
291118611Snjl    }
292118611Snjl    else
293118611Snjl    {
294151937Sjkim        if (AcpiGbl_IntegerByteWidth == 4)
295151937Sjkim        {
296151937Sjkim            AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
297151937Sjkim                Op, NULL);
298151937Sjkim
299151937Sjkim            if (!Gbl_IgnoreErrors)
300151937Sjkim            {
301151937Sjkim                /* Truncate the integer to 32-bit */
302151937Sjkim                Op->Asl.AmlOpcode = AML_DWORD_OP;
303241973Sjkim                return (4);
304151937Sjkim            }
305151937Sjkim        }
306151937Sjkim
307118611Snjl        Op->Asl.AmlOpcode = AML_QWORD_OP;
308241973Sjkim        return (8);
309118611Snjl    }
310118611Snjl}
311118611Snjl
312118611Snjl
313118611Snjl/*******************************************************************************
314118611Snjl *
315118611Snjl * FUNCTION:    OpcDoAccessAs
316118611Snjl *
317118611Snjl * PARAMETERS:  Op        - Parse node
318118611Snjl *
319118611Snjl * RETURN:      None
320118611Snjl *
321118611Snjl * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
322118611Snjl *
323118611Snjl ******************************************************************************/
324118611Snjl
325151937Sjkimstatic void
326118611SnjlOpcDoAccessAs (
327151937Sjkim    ACPI_PARSE_OBJECT       *Op)
328118611Snjl{
329228110Sjkim    ACPI_PARSE_OBJECT       *TypeOp;
330228110Sjkim    ACPI_PARSE_OBJECT       *AttribOp;
331228110Sjkim    ACPI_PARSE_OBJECT       *LengthOp;
332228110Sjkim    UINT8                   Attribute;
333118611Snjl
334118611Snjl
335118611Snjl    Op->Asl.AmlOpcodeLength = 1;
336228110Sjkim    TypeOp = Op->Asl.Child;
337118611Snjl
338118611Snjl    /* First child is the access type */
339118611Snjl
340228110Sjkim    TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
341228110Sjkim    TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
342118611Snjl
343118611Snjl    /* Second child is the optional access attribute */
344118611Snjl
345228110Sjkim    AttribOp = TypeOp->Asl.Next;
346228110Sjkim    if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
347118611Snjl    {
348228110Sjkim        AttribOp->Asl.Value.Integer = 0;
349118611Snjl    }
350306536Sjkim
351228110Sjkim    AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
352228110Sjkim    AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
353228110Sjkim
354228110Sjkim    /* Only a few AccessAttributes support AccessLength */
355228110Sjkim
356228110Sjkim    Attribute = (UINT8) AttribOp->Asl.Value.Integer;
357228110Sjkim    if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
358228110Sjkim        (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
359228110Sjkim        (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
360228110Sjkim    {
361228110Sjkim        return;
362228110Sjkim    }
363228110Sjkim
364228110Sjkim    Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
365228110Sjkim
366228110Sjkim    /*
367228110Sjkim     * Child of Attributes is the AccessLength (required for Multibyte,
368228110Sjkim     * RawBytes, RawProcess.)
369228110Sjkim     */
370228110Sjkim    LengthOp = AttribOp->Asl.Child;
371228110Sjkim    if (!LengthOp)
372228110Sjkim    {
373228110Sjkim        return;
374228110Sjkim    }
375228110Sjkim
376228110Sjkim    /* TBD: probably can remove */
377228110Sjkim
378228110Sjkim    if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
379228110Sjkim    {
380228110Sjkim        LengthOp->Asl.Value.Integer = 16;
381228110Sjkim    }
382228110Sjkim
383228110Sjkim    LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
384228110Sjkim    LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
385118611Snjl}
386118611Snjl
387118611Snjl
388118611Snjl/*******************************************************************************
389118611Snjl *
390228110Sjkim * FUNCTION:    OpcDoConnection
391228110Sjkim *
392228110Sjkim * PARAMETERS:  Op        - Parse node
393228110Sjkim *
394228110Sjkim * RETURN:      None
395228110Sjkim *
396228110Sjkim * DESCRIPTION: Implement the Connection ASL keyword.
397228110Sjkim *
398228110Sjkim ******************************************************************************/
399228110Sjkim
400228110Sjkimstatic void
401228110SjkimOpcDoConnection (
402228110Sjkim    ACPI_PARSE_OBJECT       *Op)
403228110Sjkim{
404228110Sjkim    ASL_RESOURCE_NODE       *Rnode;
405228110Sjkim    ACPI_PARSE_OBJECT       *BufferOp;
406228110Sjkim    ACPI_PARSE_OBJECT       *BufferLengthOp;
407228110Sjkim    ACPI_PARSE_OBJECT       *BufferDataOp;
408281075Sdim    ASL_RESOURCE_INFO       Info;
409228110Sjkim    UINT8                   State;
410228110Sjkim
411228110Sjkim
412228110Sjkim    Op->Asl.AmlOpcodeLength = 1;
413228110Sjkim
414228110Sjkim    if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
415228110Sjkim    {
416228110Sjkim        return;
417228110Sjkim    }
418228110Sjkim
419228110Sjkim    BufferOp = Op->Asl.Child;
420228110Sjkim    BufferLengthOp = BufferOp->Asl.Child;
421228110Sjkim    BufferDataOp = BufferLengthOp->Asl.Next;
422228110Sjkim
423281075Sdim    Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
424281075Sdim    Info.CurrentByteOffset = 0;
425228110Sjkim    State = ACPI_RSTATE_NORMAL;
426281075Sdim    Rnode = RsDoOneResourceDescriptor (&Info, &State);
427228110Sjkim    if (!Rnode)
428228110Sjkim    {
429228110Sjkim        return; /* error */
430228110Sjkim    }
431228110Sjkim
432228110Sjkim    /*
433228110Sjkim     * Transform the nodes into the following
434228110Sjkim     *
435228110Sjkim     * Op           -> AML_BUFFER_OP
436228110Sjkim     * First Child  -> BufferLength
437228110Sjkim     * Second Child -> Descriptor Buffer (raw byte data)
438228110Sjkim     */
439306536Sjkim    BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
440306536Sjkim    BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
441306536Sjkim    BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
442228110Sjkim    UtSetParseOpName (BufferOp);
443228110Sjkim
444306536Sjkim    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
445228110Sjkim    BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
446228110Sjkim    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
447228110Sjkim    UtSetParseOpName (BufferLengthOp);
448228110Sjkim
449306536Sjkim    BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
450306536Sjkim    BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
451306536Sjkim    BufferDataOp->Asl.AmlOpcodeLength = 0;
452306536Sjkim    BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
453306536Sjkim    BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
454228110Sjkim    UtSetParseOpName (BufferDataOp);
455228110Sjkim}
456228110Sjkim
457228110Sjkim
458228110Sjkim/*******************************************************************************
459228110Sjkim *
460118611Snjl * FUNCTION:    OpcDoUnicode
461118611Snjl *
462118611Snjl * PARAMETERS:  Op        - Parse node
463118611Snjl *
464118611Snjl * RETURN:      None
465118611Snjl *
466118611Snjl * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
467241973Sjkim *              to a unicode buffer. There is no Unicode AML opcode.
468118611Snjl *
469118611Snjl * Note:  The Unicode string is 16 bits per character, no leading signature,
470118611Snjl *        with a 16-bit terminating NULL.
471118611Snjl *
472118611Snjl ******************************************************************************/
473118611Snjl
474151937Sjkimstatic void
475118611SnjlOpcDoUnicode (
476151937Sjkim    ACPI_PARSE_OBJECT       *Op)
477118611Snjl{
478151937Sjkim    ACPI_PARSE_OBJECT       *InitializerOp;
479151937Sjkim    UINT32                  Length;
480151937Sjkim    UINT32                  Count;
481151937Sjkim    UINT32                  i;
482151937Sjkim    UINT8                   *AsciiString;
483151937Sjkim    UINT16                  *UnicodeString;
484151937Sjkim    ACPI_PARSE_OBJECT       *BufferLengthOp;
485118611Snjl
486118611Snjl
487118611Snjl    /* Change op into a buffer object */
488118611Snjl
489118611Snjl    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
490118611Snjl    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
491118611Snjl    UtSetParseOpName (Op);
492118611Snjl
493118611Snjl    /* Buffer Length is first, followed by the string */
494118611Snjl
495118611Snjl    BufferLengthOp = Op->Asl.Child;
496118611Snjl    InitializerOp = BufferLengthOp->Asl.Next;
497118611Snjl
498118611Snjl    AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
499118611Snjl
500118611Snjl    /* Create a new buffer for the Unicode string */
501118611Snjl
502118611Snjl    Count = strlen (InitializerOp->Asl.Value.String) + 1;
503118611Snjl    Length = Count * sizeof (UINT16);
504118611Snjl    UnicodeString = UtLocalCalloc (Length);
505118611Snjl
506118611Snjl    /* Convert to Unicode string (including null terminator) */
507118611Snjl
508118611Snjl    for (i = 0; i < Count; i++)
509118611Snjl    {
510118611Snjl        UnicodeString[i] = (UINT16) AsciiString[i];
511118611Snjl    }
512118611Snjl
513118611Snjl    /*
514118611Snjl     * Just set the buffer size node to be the buffer length, regardless
515118611Snjl     * of whether it was previously an integer or a default_arg placeholder
516118611Snjl     */
517306536Sjkim    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
518306536Sjkim    BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
519118611Snjl    BufferLengthOp->Asl.Value.Integer = Length;
520118611Snjl    UtSetParseOpName (BufferLengthOp);
521118611Snjl
522118611Snjl    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
523118611Snjl
524118611Snjl    /* The Unicode string is a raw data buffer */
525118611Snjl
526306536Sjkim    InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
527306536Sjkim    InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
528306536Sjkim    InitializerOp->Asl.AmlLength = Length;
529306536Sjkim    InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
530306536Sjkim    InitializerOp->Asl.Child = NULL;
531118611Snjl    UtSetParseOpName (InitializerOp);
532118611Snjl}
533118611Snjl
534118611Snjl
535118611Snjl/*******************************************************************************
536118611Snjl *
537118611Snjl * FUNCTION:    OpcDoEisaId
538118611Snjl *
539118611Snjl * PARAMETERS:  Op        - Parse node
540118611Snjl *
541118611Snjl * RETURN:      None
542118611Snjl *
543241973Sjkim * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
544241973Sjkim *              Pnp BIOS Specification for details. Here is an excerpt:
545118611Snjl *
546118611Snjl *              A seven character ASCII representation of the product
547241973Sjkim *              identifier compressed into a 32-bit identifier. The seven
548118611Snjl *              character ID consists of a three character manufacturer code,
549118611Snjl *              a three character hexadecimal product identifier, and a one
550241973Sjkim *              character hexadecimal revision number. The manufacturer code
551118611Snjl *              is a 3 uppercase character code that is compressed into 3 5-bit
552118611Snjl *              values as follows:
553118611Snjl *                  1) Find hex ASCII value for each letter
554118611Snjl *                  2) Subtract 40h from each ASCII value
555241973Sjkim *                  3) Retain 5 least significant bits for each letter by
556118611Snjl *                     discarding upper 3 bits because they are always 0.
557118611Snjl *                  4) Compressed code = concatenate 0 and the 3 5-bit values
558118611Snjl *
559118611Snjl *              The format of the compressed product identifier is as follows:
560118611Snjl *              Byte 0: Bit 7       - Reserved (0)
561118611Snjl *                      Bits 6-2:   - 1st character of compressed mfg code
562118611Snjl *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
563118611Snjl *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
564118611Snjl *                      Bits 4-0    - 3rd character of mfg code
565118611Snjl *              Byte 2: Bits 7-4    - 1st hex digit of product number
566118611Snjl *                      Bits 3-0    - 2nd hex digit of product number
567118611Snjl *              Byte 3: Bits 7-4    - 3st hex digit of product number
568118611Snjl *                      Bits 3-0    - Hex digit of the revision number
569118611Snjl *
570118611Snjl ******************************************************************************/
571118611Snjl
572151937Sjkimstatic void
573118611SnjlOpcDoEisaId (
574118611Snjl    ACPI_PARSE_OBJECT       *Op)
575118611Snjl{
576118611Snjl    UINT32                  EisaId = 0;
577118611Snjl    UINT32                  BigEndianId;
578118611Snjl    char                    *InString;
579118611Snjl    ACPI_STATUS             Status = AE_OK;
580193529Sjkim    UINT32                  i;
581118611Snjl
582118611Snjl
583118611Snjl    InString = (char *) Op->Asl.Value.String;
584118611Snjl
585118611Snjl    /*
586118611Snjl     * The EISAID string must be exactly 7 characters and of the form
587151937Sjkim     * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
588118611Snjl     */
589306536Sjkim    if (strlen (InString) != 7)
590118611Snjl    {
591118611Snjl        Status = AE_BAD_PARAMETER;
592118611Snjl    }
593118611Snjl    else
594118611Snjl    {
595118611Snjl        /* Check all 7 characters for correct format */
596118611Snjl
597118611Snjl        for (i = 0; i < 7; i++)
598118611Snjl        {
599138287Smarks            /* First 3 characters must be uppercase letters */
600118611Snjl
601118611Snjl            if (i < 3)
602118611Snjl            {
603202771Sjkim                if (!isupper ((int) InString[i]))
604118611Snjl                {
605118611Snjl                    Status = AE_BAD_PARAMETER;
606118611Snjl                }
607118611Snjl            }
608118611Snjl
609118611Snjl            /* Last 4 characters must be hex digits */
610118611Snjl
611202771Sjkim            else if (!isxdigit ((int) InString[i]))
612118611Snjl            {
613118611Snjl                Status = AE_BAD_PARAMETER;
614118611Snjl            }
615118611Snjl        }
616118611Snjl    }
617118611Snjl
618118611Snjl    if (ACPI_FAILURE (Status))
619118611Snjl    {
620118611Snjl        AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
621118611Snjl    }
622118611Snjl    else
623118611Snjl    {
624118611Snjl        /* Create ID big-endian first (bits are contiguous) */
625118611Snjl
626167802Sjkim        BigEndianId =
627212761Sjkim            (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
628212761Sjkim            (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
629212761Sjkim            (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
630118611Snjl
631281075Sdim            (AcpiUtAsciiCharToHex (InString[3])) << 12 |
632281075Sdim            (AcpiUtAsciiCharToHex (InString[4])) << 8  |
633281075Sdim            (AcpiUtAsciiCharToHex (InString[5])) << 4  |
634281075Sdim             AcpiUtAsciiCharToHex (InString[6]);
635118611Snjl
636118611Snjl        /* Swap to little-endian to get final ID (see function header) */
637118611Snjl
638118611Snjl        EisaId = AcpiUtDwordByteSwap (BigEndianId);
639118611Snjl    }
640118611Snjl
641118611Snjl    /*
642118611Snjl     * Morph the Op into an integer, regardless of whether there
643118611Snjl     * was an error in the EISAID string
644118611Snjl     */
645118611Snjl    Op->Asl.Value.Integer = EisaId;
646118611Snjl
647118611Snjl    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
648118611Snjl    Op->Asl.ParseOpcode = PARSEOP_INTEGER;
649118611Snjl    (void) OpcSetOptimalIntegerSize (Op);
650118611Snjl
651118611Snjl    /* Op is now an integer */
652118611Snjl
653118611Snjl    UtSetParseOpName (Op);
654118611Snjl}
655118611Snjl
656118611Snjl
657118611Snjl/*******************************************************************************
658118611Snjl *
659228110Sjkim * FUNCTION:    OpcDoUuId
660138287Smarks *
661281075Sdim * PARAMETERS:  Op                  - Parse node
662138287Smarks *
663138287Smarks * RETURN:      None
664138287Smarks *
665151937Sjkim * DESCRIPTION: Convert UUID string to 16-byte buffer
666138287Smarks *
667138287Smarks ******************************************************************************/
668138287Smarks
669151937Sjkimstatic void
670138287SmarksOpcDoUuId (
671138287Smarks    ACPI_PARSE_OBJECT       *Op)
672138287Smarks{
673138287Smarks    char                    *InString;
674281075Sdim    UINT8                   *Buffer;
675138287Smarks    ACPI_STATUS             Status = AE_OK;
676138287Smarks    ACPI_PARSE_OBJECT       *NewOp;
677138287Smarks
678138287Smarks
679281075Sdim    InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
680138287Smarks    Buffer = UtLocalCalloc (16);
681138287Smarks
682217365Sjkim    Status = AuValidateUuid (InString);
683138287Smarks    if (ACPI_FAILURE (Status))
684138287Smarks    {
685138287Smarks        AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
686138287Smarks    }
687217365Sjkim    else
688138287Smarks    {
689281075Sdim        AcpiUtConvertStringToUuid (InString, Buffer);
690138287Smarks    }
691138287Smarks
692138287Smarks    /* Change Op to a Buffer */
693138287Smarks
694138287Smarks    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
695138287Smarks    Op->Common.AmlOpcode = AML_BUFFER_OP;
696151937Sjkim
697151937Sjkim    /* Disable further optimization */
698151937Sjkim
699151937Sjkim    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
700138287Smarks    UtSetParseOpName (Op);
701138287Smarks
702138287Smarks    /* Child node is the buffer length */
703138287Smarks
704138287Smarks    NewOp = TrAllocateNode (PARSEOP_INTEGER);
705138287Smarks
706306536Sjkim    NewOp->Asl.AmlOpcode = AML_BYTE_OP;
707138287Smarks    NewOp->Asl.Value.Integer = 16;
708306536Sjkim    NewOp->Asl.Parent = Op;
709138287Smarks
710138287Smarks    Op->Asl.Child = NewOp;
711138287Smarks    Op = NewOp;
712138287Smarks
713138287Smarks    /* Peer to the child is the raw buffer data */
714138287Smarks
715138287Smarks    NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
716306536Sjkim    NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
717306536Sjkim    NewOp->Asl.AmlLength = 16;
718306536Sjkim    NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
719306536Sjkim    NewOp->Asl.Parent = Op->Asl.Parent;
720138287Smarks
721138287Smarks    Op->Asl.Next = NewOp;
722138287Smarks}
723138287Smarks
724138287Smarks
725138287Smarks/*******************************************************************************
726138287Smarks *
727118611Snjl * FUNCTION:    OpcGenerateAmlOpcode
728118611Snjl *
729281075Sdim * PARAMETERS:  Op                  - Parse node
730118611Snjl *
731118611Snjl * RETURN:      None
732118611Snjl *
733118611Snjl * DESCRIPTION: Generate the AML opcode associated with the node and its
734241973Sjkim *              parse (lex/flex) keyword opcode. Essentially implements
735118611Snjl *              a mapping between the parse opcodes and the actual AML opcodes.
736118611Snjl *
737118611Snjl ******************************************************************************/
738118611Snjl
739118611Snjlvoid
740118611SnjlOpcGenerateAmlOpcode (
741118611Snjl    ACPI_PARSE_OBJECT       *Op)
742118611Snjl{
743118611Snjl    UINT16                  Index;
744118611Snjl
745118611Snjl
746118611Snjl    Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
747118611Snjl
748118611Snjl    Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
749118611Snjl    Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
750118611Snjl    Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
751118611Snjl
752118611Snjl    if (!Op->Asl.Value.Integer)
753118611Snjl    {
754118611Snjl        Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
755118611Snjl    }
756118611Snjl
757118611Snjl    /* Special handling for some opcodes */
758118611Snjl
759118611Snjl    switch (Op->Asl.ParseOpcode)
760118611Snjl    {
761118611Snjl    case PARSEOP_INTEGER:
762118611Snjl        /*
763118611Snjl         * Set the opcode based on the size of the integer
764118611Snjl         */
765118611Snjl        (void) OpcSetOptimalIntegerSize (Op);
766118611Snjl        break;
767118611Snjl
768118611Snjl    case PARSEOP_OFFSET:
769118611Snjl
770118611Snjl        Op->Asl.AmlOpcodeLength = 1;
771118611Snjl        break;
772118611Snjl
773118611Snjl    case PARSEOP_ACCESSAS:
774118611Snjl
775118611Snjl        OpcDoAccessAs (Op);
776118611Snjl        break;
777118611Snjl
778228110Sjkim    case PARSEOP_CONNECTION:
779228110Sjkim
780228110Sjkim        OpcDoConnection (Op);
781228110Sjkim        break;
782228110Sjkim
783118611Snjl    case PARSEOP_EISAID:
784118611Snjl
785118611Snjl        OpcDoEisaId (Op);
786118611Snjl        break;
787118611Snjl
788281075Sdim    case PARSEOP_PRINTF:
789281075Sdim
790281075Sdim        OpcDoPrintf (Op);
791281075Sdim        break;
792281075Sdim
793281075Sdim    case PARSEOP_FPRINTF:
794281075Sdim
795281075Sdim        OpcDoFprintf (Op);
796281075Sdim        break;
797281075Sdim
798281075Sdim    case PARSEOP_TOPLD:
799281075Sdim
800281075Sdim        OpcDoPld (Op);
801281075Sdim        break;
802281075Sdim
803138287Smarks    case PARSEOP_TOUUID:
804138287Smarks
805138287Smarks        OpcDoUuId (Op);
806138287Smarks        break;
807138287Smarks
808118611Snjl    case PARSEOP_UNICODE:
809118611Snjl
810118611Snjl        OpcDoUnicode (Op);
811118611Snjl        break;
812118611Snjl
813118611Snjl    case PARSEOP_INCLUDE:
814118611Snjl
815118611Snjl        Gbl_HasIncludeFiles = TRUE;
816118611Snjl        break;
817118611Snjl
818118611Snjl    case PARSEOP_EXTERNAL:
819118611Snjl
820306536Sjkim        if (Gbl_DoExternals == FALSE)
821306536Sjkim        {
822306536Sjkim            Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
823306536Sjkim            Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
824306536Sjkim        }
825118611Snjl        break;
826118611Snjl
827245582Sjkim    case PARSEOP_TIMER:
828245582Sjkim
829245582Sjkim        if (AcpiGbl_IntegerBitWidth == 32)
830245582Sjkim        {
831245582Sjkim            AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
832245582Sjkim        }
833245582Sjkim        break;
834245582Sjkim
835118611Snjl    default:
836250838Sjkim
837118611Snjl        /* Nothing to do for other opcodes */
838250838Sjkim
839118611Snjl        break;
840118611Snjl    }
841118611Snjl
842118611Snjl    return;
843118611Snjl}
844