aslopcodes.c revision 306536
1256949Sganbold/******************************************************************************
2256949Sganbold *
3256949Sganbold * Module Name: aslopcode - AML opcode generation
4256949Sganbold *
5256949Sganbold *****************************************************************************/
6256949Sganbold
7256949Sganbold/*
8256949Sganbold * Copyright (C) 2000 - 2016, Intel Corp.
9256949Sganbold * All rights reserved.
10256949Sganbold *
11256949Sganbold * Redistribution and use in source and binary forms, with or without
12256949Sganbold * modification, are permitted provided that the following conditions
13256949Sganbold * are met:
14256949Sganbold * 1. Redistributions of source code must retain the above copyright
15256949Sganbold *    notice, this list of conditions, and the following disclaimer,
16256949Sganbold *    without modification.
17256949Sganbold * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18256949Sganbold *    substantially similar to the "NO WARRANTY" disclaimer below
19256949Sganbold *    ("Disclaimer") and any redistribution must be conditioned upon
20256949Sganbold *    including a substantially similar Disclaimer requirement for further
21256949Sganbold *    binary redistribution.
22256949Sganbold * 3. Neither the names of the above-listed copyright holders nor the names
23256949Sganbold *    of any contributors may be used to endorse or promote products derived
24256949Sganbold *    from this software without specific prior written permission.
25256949Sganbold *
26256949Sganbold * Alternatively, this software may be distributed under the terms of the
27256949Sganbold * GNU General Public License ("GPL") version 2 as published by the Free
28256949Sganbold * Software Foundation.
29256949Sganbold *
30256949Sganbold * NO WARRANTY
31256949Sganbold * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32256949Sganbold * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33256949Sganbold * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34256949Sganbold * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35256949Sganbold * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36256949Sganbold * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37256949Sganbold * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38256949Sganbold * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39256949Sganbold * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40256949Sganbold * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41256949Sganbold * POSSIBILITY OF SUCH DAMAGES.
42256949Sganbold */
43256949Sganbold
44256949Sganbold#include <contrib/dev/acpica/compiler/aslcompiler.h>
45256949Sganbold#include "aslcompiler.y.h"
46256949Sganbold#include <contrib/dev/acpica/include/amlcode.h>
47256949Sganbold
48256949Sganbold#define _COMPONENT          ACPI_COMPILER
49256949Sganbold        ACPI_MODULE_NAME    ("aslopcodes")
50256949Sganbold
51256949Sganbold
52256949Sganbold/* Local prototypes */
53256949Sganbold
54256949Sganboldstatic void
55256949SganboldOpcDoAccessAs (
56256949Sganbold    ACPI_PARSE_OBJECT       *Op);
57256949Sganbold
58256949Sganboldstatic void
59256949SganboldOpcDoConnection (
60256949Sganbold    ACPI_PARSE_OBJECT       *Op);
61256949Sganbold
62256949Sganboldstatic void
63256949SganboldOpcDoUnicode (
64256949Sganbold    ACPI_PARSE_OBJECT       *Op);
65256949Sganbold
66256949Sganboldstatic void
67256949SganboldOpcDoEisaId (
68256949Sganbold    ACPI_PARSE_OBJECT       *Op);
69256949Sganbold
70256949Sganboldstatic void
71256949SganboldOpcDoUuId (
72256949Sganbold    ACPI_PARSE_OBJECT       *Op);
73256949Sganbold
74256949Sganbold
75256949Sganbold/*******************************************************************************
76256949Sganbold *
77256949Sganbold * FUNCTION:    OpcAmlOpcodeUpdateWalk
78256949Sganbold *
79256949Sganbold * PARAMETERS:  ASL_WALK_CALLBACK
80256949Sganbold *
81256949Sganbold * RETURN:      Status
82256949Sganbold *
83256949Sganbold * DESCRIPTION: Opcode update walk, ascending callback
84256949Sganbold *
85256949Sganbold ******************************************************************************/
86256949Sganbold
87256949SganboldACPI_STATUS
88256949SganboldOpcAmlOpcodeUpdateWalk (
89256949Sganbold    ACPI_PARSE_OBJECT       *Op,
90256949Sganbold    UINT32                  Level,
91256949Sganbold    void                    *Context)
92256949Sganbold{
93256949Sganbold
94256949Sganbold    /*
95256949Sganbold     * Handle the Package() case where the actual opcode cannot be determined
96256949Sganbold     * until the PackageLength operand has been folded and minimized.
97256949Sganbold     * (PackageOp versus VarPackageOp)
98256949Sganbold     *
99256949Sganbold     * This is (as of ACPI 3.0) the only case where the AML opcode can change
100256949Sganbold     * based upon the value of a parameter.
101256949Sganbold     *
102256949Sganbold     * The parser always inserts a VarPackage opcode, which can possibly be
103256949Sganbold     * optimized to a Package opcode.
104256949Sganbold     */
105256949Sganbold    if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
106256949Sganbold    {
107256949Sganbold        OpnDoPackage (Op);
108256949Sganbold    }
109256949Sganbold
110256949Sganbold    return (AE_OK);
111256949Sganbold}
112256949Sganbold
113256949Sganbold
114/*******************************************************************************
115 *
116 * FUNCTION:    OpcAmlOpcodeWalk
117 *
118 * PARAMETERS:  ASL_WALK_CALLBACK
119 *
120 * RETURN:      Status
121 *
122 * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
123 *              operands.
124 *
125 ******************************************************************************/
126
127ACPI_STATUS
128OpcAmlOpcodeWalk (
129    ACPI_PARSE_OBJECT       *Op,
130    UINT32                  Level,
131    void                    *Context)
132{
133
134    TotalParseNodes++;
135
136    OpcGenerateAmlOpcode (Op);
137    OpnGenerateAmlOperands (Op);
138    return (AE_OK);
139}
140
141
142/*******************************************************************************
143 *
144 * FUNCTION:    OpcGetIntegerWidth
145 *
146 * PARAMETERS:  Op          - DEFINITION BLOCK op
147 *
148 * RETURN:      none
149 *
150 * DESCRIPTION: Extract integer width from the table revision
151 *
152 ******************************************************************************/
153
154void
155OpcGetIntegerWidth (
156    ACPI_PARSE_OBJECT       *Op)
157{
158    ACPI_PARSE_OBJECT       *Child;
159
160
161    if (!Op)
162    {
163        return;
164    }
165
166    if (Gbl_RevisionOverride)
167    {
168        AcpiUtSetIntegerWidth (Gbl_RevisionOverride);
169    }
170    else
171    {
172        Child = Op->Asl.Child;
173        Child = Child->Asl.Next;
174        Child = Child->Asl.Next;
175
176        /* Use the revision to set the integer width */
177
178        AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
179    }
180}
181
182
183/*******************************************************************************
184 *
185 * FUNCTION:    OpcSetOptimalIntegerSize
186 *
187 * PARAMETERS:  Op        - A parse tree node
188 *
189 * RETURN:      Integer width, in bytes. Also sets the node AML opcode to the
190 *              optimal integer AML prefix opcode.
191 *
192 * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading
193 *              zeros can be truncated to squeeze the integer into the
194 *              minimal number of AML bytes.
195 *
196 ******************************************************************************/
197
198UINT32
199OpcSetOptimalIntegerSize (
200    ACPI_PARSE_OBJECT       *Op)
201{
202
203#if 0
204    /*
205     * TBD: - we don't want to optimize integers in the block header, but the
206     * code below does not work correctly.
207     */
208    if (Op->Asl.Parent &&
209        Op->Asl.Parent->Asl.Parent &&
210       (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK))
211    {
212        return (0);
213    }
214#endif
215
216    /*
217     * Check for the special AML integers first - Zero, One, Ones.
218     * These are single-byte opcodes that are the smallest possible
219     * representation of an integer.
220     *
221     * This optimization is optional.
222     */
223    if (Gbl_IntegerOptimizationFlag)
224    {
225        switch (Op->Asl.Value.Integer)
226        {
227        case 0:
228
229            Op->Asl.AmlOpcode = AML_ZERO_OP;
230            AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
231                Op, "Zero");
232            return (1);
233
234        case 1:
235
236            Op->Asl.AmlOpcode = AML_ONE_OP;
237            AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
238                Op, "One");
239            return (1);
240
241        case ACPI_UINT32_MAX:
242
243            /* Check for table integer width (32 or 64) */
244
245            if (AcpiGbl_IntegerByteWidth == 4)
246            {
247                Op->Asl.AmlOpcode = AML_ONES_OP;
248                AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
249                    Op, "Ones");
250                return (1);
251            }
252            break;
253
254        case ACPI_UINT64_MAX:
255
256            /* Check for table integer width (32 or 64) */
257
258            if (AcpiGbl_IntegerByteWidth == 8)
259            {
260                Op->Asl.AmlOpcode = AML_ONES_OP;
261                AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
262                    Op, "Ones");
263                return (1);
264            }
265            break;
266
267        default:
268
269            break;
270        }
271    }
272
273    /* Find the best fit using the various AML integer prefixes */
274
275    if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
276    {
277        Op->Asl.AmlOpcode = AML_BYTE_OP;
278        return (1);
279    }
280
281    if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
282    {
283        Op->Asl.AmlOpcode = AML_WORD_OP;
284        return (2);
285    }
286
287    if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
288    {
289        Op->Asl.AmlOpcode = AML_DWORD_OP;
290        return (4);
291    }
292    else
293    {
294        if (AcpiGbl_IntegerByteWidth == 4)
295        {
296            AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
297                Op, NULL);
298
299            if (!Gbl_IgnoreErrors)
300            {
301                /* Truncate the integer to 32-bit */
302                Op->Asl.AmlOpcode = AML_DWORD_OP;
303                return (4);
304            }
305        }
306
307        Op->Asl.AmlOpcode = AML_QWORD_OP;
308        return (8);
309    }
310}
311
312
313/*******************************************************************************
314 *
315 * FUNCTION:    OpcDoAccessAs
316 *
317 * PARAMETERS:  Op        - Parse node
318 *
319 * RETURN:      None
320 *
321 * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
322 *
323 ******************************************************************************/
324
325static void
326OpcDoAccessAs (
327    ACPI_PARSE_OBJECT       *Op)
328{
329    ACPI_PARSE_OBJECT       *TypeOp;
330    ACPI_PARSE_OBJECT       *AttribOp;
331    ACPI_PARSE_OBJECT       *LengthOp;
332    UINT8                   Attribute;
333
334
335    Op->Asl.AmlOpcodeLength = 1;
336    TypeOp = Op->Asl.Child;
337
338    /* First child is the access type */
339
340    TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
341    TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
342
343    /* Second child is the optional access attribute */
344
345    AttribOp = TypeOp->Asl.Next;
346    if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
347    {
348        AttribOp->Asl.Value.Integer = 0;
349    }
350
351    AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
352    AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
353
354    /* Only a few AccessAttributes support AccessLength */
355
356    Attribute = (UINT8) AttribOp->Asl.Value.Integer;
357    if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
358        (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
359        (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
360    {
361        return;
362    }
363
364    Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
365
366    /*
367     * Child of Attributes is the AccessLength (required for Multibyte,
368     * RawBytes, RawProcess.)
369     */
370    LengthOp = AttribOp->Asl.Child;
371    if (!LengthOp)
372    {
373        return;
374    }
375
376    /* TBD: probably can remove */
377
378    if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
379    {
380        LengthOp->Asl.Value.Integer = 16;
381    }
382
383    LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
384    LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
385}
386
387
388/*******************************************************************************
389 *
390 * FUNCTION:    OpcDoConnection
391 *
392 * PARAMETERS:  Op        - Parse node
393 *
394 * RETURN:      None
395 *
396 * DESCRIPTION: Implement the Connection ASL keyword.
397 *
398 ******************************************************************************/
399
400static void
401OpcDoConnection (
402    ACPI_PARSE_OBJECT       *Op)
403{
404    ASL_RESOURCE_NODE       *Rnode;
405    ACPI_PARSE_OBJECT       *BufferOp;
406    ACPI_PARSE_OBJECT       *BufferLengthOp;
407    ACPI_PARSE_OBJECT       *BufferDataOp;
408    ASL_RESOURCE_INFO       Info;
409    UINT8                   State;
410
411
412    Op->Asl.AmlOpcodeLength = 1;
413
414    if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
415    {
416        return;
417    }
418
419    BufferOp = Op->Asl.Child;
420    BufferLengthOp = BufferOp->Asl.Child;
421    BufferDataOp = BufferLengthOp->Asl.Next;
422
423    Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
424    Info.CurrentByteOffset = 0;
425    State = ACPI_RSTATE_NORMAL;
426    Rnode = RsDoOneResourceDescriptor (&Info, &State);
427    if (!Rnode)
428    {
429        return; /* error */
430    }
431
432    /*
433     * Transform the nodes into the following
434     *
435     * Op           -> AML_BUFFER_OP
436     * First Child  -> BufferLength
437     * Second Child -> Descriptor Buffer (raw byte data)
438     */
439    BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
440    BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
441    BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
442    UtSetParseOpName (BufferOp);
443
444    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
445    BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
446    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
447    UtSetParseOpName (BufferLengthOp);
448
449    BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
450    BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
451    BufferDataOp->Asl.AmlOpcodeLength = 0;
452    BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
453    BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
454    UtSetParseOpName (BufferDataOp);
455}
456
457
458/*******************************************************************************
459 *
460 * FUNCTION:    OpcDoUnicode
461 *
462 * PARAMETERS:  Op        - Parse node
463 *
464 * RETURN:      None
465 *
466 * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
467 *              to a unicode buffer. There is no Unicode AML opcode.
468 *
469 * Note:  The Unicode string is 16 bits per character, no leading signature,
470 *        with a 16-bit terminating NULL.
471 *
472 ******************************************************************************/
473
474static void
475OpcDoUnicode (
476    ACPI_PARSE_OBJECT       *Op)
477{
478    ACPI_PARSE_OBJECT       *InitializerOp;
479    UINT32                  Length;
480    UINT32                  Count;
481    UINT32                  i;
482    UINT8                   *AsciiString;
483    UINT16                  *UnicodeString;
484    ACPI_PARSE_OBJECT       *BufferLengthOp;
485
486
487    /* Change op into a buffer object */
488
489    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
490    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
491    UtSetParseOpName (Op);
492
493    /* Buffer Length is first, followed by the string */
494
495    BufferLengthOp = Op->Asl.Child;
496    InitializerOp = BufferLengthOp->Asl.Next;
497
498    AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
499
500    /* Create a new buffer for the Unicode string */
501
502    Count = strlen (InitializerOp->Asl.Value.String) + 1;
503    Length = Count * sizeof (UINT16);
504    UnicodeString = UtLocalCalloc (Length);
505
506    /* Convert to Unicode string (including null terminator) */
507
508    for (i = 0; i < Count; i++)
509    {
510        UnicodeString[i] = (UINT16) AsciiString[i];
511    }
512
513    /*
514     * Just set the buffer size node to be the buffer length, regardless
515     * of whether it was previously an integer or a default_arg placeholder
516     */
517    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
518    BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
519    BufferLengthOp->Asl.Value.Integer = Length;
520    UtSetParseOpName (BufferLengthOp);
521
522    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
523
524    /* The Unicode string is a raw data buffer */
525
526    InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
527    InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
528    InitializerOp->Asl.AmlLength = Length;
529    InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
530    InitializerOp->Asl.Child = NULL;
531    UtSetParseOpName (InitializerOp);
532}
533
534
535/*******************************************************************************
536 *
537 * FUNCTION:    OpcDoEisaId
538 *
539 * PARAMETERS:  Op        - Parse node
540 *
541 * RETURN:      None
542 *
543 * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
544 *              Pnp BIOS Specification for details. Here is an excerpt:
545 *
546 *              A seven character ASCII representation of the product
547 *              identifier compressed into a 32-bit identifier. The seven
548 *              character ID consists of a three character manufacturer code,
549 *              a three character hexadecimal product identifier, and a one
550 *              character hexadecimal revision number. The manufacturer code
551 *              is a 3 uppercase character code that is compressed into 3 5-bit
552 *              values as follows:
553 *                  1) Find hex ASCII value for each letter
554 *                  2) Subtract 40h from each ASCII value
555 *                  3) Retain 5 least significant bits for each letter by
556 *                     discarding upper 3 bits because they are always 0.
557 *                  4) Compressed code = concatenate 0 and the 3 5-bit values
558 *
559 *              The format of the compressed product identifier is as follows:
560 *              Byte 0: Bit 7       - Reserved (0)
561 *                      Bits 6-2:   - 1st character of compressed mfg code
562 *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
563 *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
564 *                      Bits 4-0    - 3rd character of mfg code
565 *              Byte 2: Bits 7-4    - 1st hex digit of product number
566 *                      Bits 3-0    - 2nd hex digit of product number
567 *              Byte 3: Bits 7-4    - 3st hex digit of product number
568 *                      Bits 3-0    - Hex digit of the revision number
569 *
570 ******************************************************************************/
571
572static void
573OpcDoEisaId (
574    ACPI_PARSE_OBJECT       *Op)
575{
576    UINT32                  EisaId = 0;
577    UINT32                  BigEndianId;
578    char                    *InString;
579    ACPI_STATUS             Status = AE_OK;
580    UINT32                  i;
581
582
583    InString = (char *) Op->Asl.Value.String;
584
585    /*
586     * The EISAID string must be exactly 7 characters and of the form
587     * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
588     */
589    if (strlen (InString) != 7)
590    {
591        Status = AE_BAD_PARAMETER;
592    }
593    else
594    {
595        /* Check all 7 characters for correct format */
596
597        for (i = 0; i < 7; i++)
598        {
599            /* First 3 characters must be uppercase letters */
600
601            if (i < 3)
602            {
603                if (!isupper ((int) InString[i]))
604                {
605                    Status = AE_BAD_PARAMETER;
606                }
607            }
608
609            /* Last 4 characters must be hex digits */
610
611            else if (!isxdigit ((int) InString[i]))
612            {
613                Status = AE_BAD_PARAMETER;
614            }
615        }
616    }
617
618    if (ACPI_FAILURE (Status))
619    {
620        AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
621    }
622    else
623    {
624        /* Create ID big-endian first (bits are contiguous) */
625
626        BigEndianId =
627            (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
628            (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
629            (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
630
631            (AcpiUtAsciiCharToHex (InString[3])) << 12 |
632            (AcpiUtAsciiCharToHex (InString[4])) << 8  |
633            (AcpiUtAsciiCharToHex (InString[5])) << 4  |
634             AcpiUtAsciiCharToHex (InString[6]);
635
636        /* Swap to little-endian to get final ID (see function header) */
637
638        EisaId = AcpiUtDwordByteSwap (BigEndianId);
639    }
640
641    /*
642     * Morph the Op into an integer, regardless of whether there
643     * was an error in the EISAID string
644     */
645    Op->Asl.Value.Integer = EisaId;
646
647    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
648    Op->Asl.ParseOpcode = PARSEOP_INTEGER;
649    (void) OpcSetOptimalIntegerSize (Op);
650
651    /* Op is now an integer */
652
653    UtSetParseOpName (Op);
654}
655
656
657/*******************************************************************************
658 *
659 * FUNCTION:    OpcDoUuId
660 *
661 * PARAMETERS:  Op                  - Parse node
662 *
663 * RETURN:      None
664 *
665 * DESCRIPTION: Convert UUID string to 16-byte buffer
666 *
667 ******************************************************************************/
668
669static void
670OpcDoUuId (
671    ACPI_PARSE_OBJECT       *Op)
672{
673    char                    *InString;
674    UINT8                   *Buffer;
675    ACPI_STATUS             Status = AE_OK;
676    ACPI_PARSE_OBJECT       *NewOp;
677
678
679    InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
680    Buffer = UtLocalCalloc (16);
681
682    Status = AuValidateUuid (InString);
683    if (ACPI_FAILURE (Status))
684    {
685        AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
686    }
687    else
688    {
689        AcpiUtConvertStringToUuid (InString, Buffer);
690    }
691
692    /* Change Op to a Buffer */
693
694    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
695    Op->Common.AmlOpcode = AML_BUFFER_OP;
696
697    /* Disable further optimization */
698
699    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
700    UtSetParseOpName (Op);
701
702    /* Child node is the buffer length */
703
704    NewOp = TrAllocateNode (PARSEOP_INTEGER);
705
706    NewOp->Asl.AmlOpcode = AML_BYTE_OP;
707    NewOp->Asl.Value.Integer = 16;
708    NewOp->Asl.Parent = Op;
709
710    Op->Asl.Child = NewOp;
711    Op = NewOp;
712
713    /* Peer to the child is the raw buffer data */
714
715    NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
716    NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
717    NewOp->Asl.AmlLength = 16;
718    NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
719    NewOp->Asl.Parent = Op->Asl.Parent;
720
721    Op->Asl.Next = NewOp;
722}
723
724
725/*******************************************************************************
726 *
727 * FUNCTION:    OpcGenerateAmlOpcode
728 *
729 * PARAMETERS:  Op                  - Parse node
730 *
731 * RETURN:      None
732 *
733 * DESCRIPTION: Generate the AML opcode associated with the node and its
734 *              parse (lex/flex) keyword opcode. Essentially implements
735 *              a mapping between the parse opcodes and the actual AML opcodes.
736 *
737 ******************************************************************************/
738
739void
740OpcGenerateAmlOpcode (
741    ACPI_PARSE_OBJECT       *Op)
742{
743    UINT16                  Index;
744
745
746    Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
747
748    Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
749    Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
750    Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
751
752    if (!Op->Asl.Value.Integer)
753    {
754        Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
755    }
756
757    /* Special handling for some opcodes */
758
759    switch (Op->Asl.ParseOpcode)
760    {
761    case PARSEOP_INTEGER:
762        /*
763         * Set the opcode based on the size of the integer
764         */
765        (void) OpcSetOptimalIntegerSize (Op);
766        break;
767
768    case PARSEOP_OFFSET:
769
770        Op->Asl.AmlOpcodeLength = 1;
771        break;
772
773    case PARSEOP_ACCESSAS:
774
775        OpcDoAccessAs (Op);
776        break;
777
778    case PARSEOP_CONNECTION:
779
780        OpcDoConnection (Op);
781        break;
782
783    case PARSEOP_EISAID:
784
785        OpcDoEisaId (Op);
786        break;
787
788    case PARSEOP_PRINTF:
789
790        OpcDoPrintf (Op);
791        break;
792
793    case PARSEOP_FPRINTF:
794
795        OpcDoFprintf (Op);
796        break;
797
798    case PARSEOP_TOPLD:
799
800        OpcDoPld (Op);
801        break;
802
803    case PARSEOP_TOUUID:
804
805        OpcDoUuId (Op);
806        break;
807
808    case PARSEOP_UNICODE:
809
810        OpcDoUnicode (Op);
811        break;
812
813    case PARSEOP_INCLUDE:
814
815        Gbl_HasIncludeFiles = TRUE;
816        break;
817
818    case PARSEOP_EXTERNAL:
819
820        if (Gbl_DoExternals == FALSE)
821        {
822            Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
823            Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
824        }
825        break;
826
827    case PARSEOP_TIMER:
828
829        if (AcpiGbl_IntegerBitWidth == 32)
830        {
831            AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
832        }
833        break;
834
835    default:
836
837        /* Nothing to do for other opcodes */
838
839        break;
840    }
841
842    return;
843}
844