aslopcodes.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: aslopcode - AML opcode generation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/include/amlcode.h>
47
48#define _COMPONENT          ACPI_COMPILER
49        ACPI_MODULE_NAME    ("aslopcodes")
50
51
52/* Local prototypes */
53
54static void
55OpcDoAccessAs (
56    ACPI_PARSE_OBJECT       *Op);
57
58static void
59OpcDoConnection (
60    ACPI_PARSE_OBJECT       *Op);
61
62static void
63OpcDoUnicode (
64    ACPI_PARSE_OBJECT       *Op);
65
66static void
67OpcDoEisaId (
68    ACPI_PARSE_OBJECT       *Op);
69
70static void
71OpcDoPld (
72    ACPI_PARSE_OBJECT       *Op);
73
74static void
75OpcDoUuId (
76    ACPI_PARSE_OBJECT       *Op);
77
78static UINT8 *
79OpcEncodePldBuffer (
80    ACPI_PLD_INFO           *PldInfo);
81
82
83/* ToPld strings */
84
85static char *AslPldPanelList[] =
86{
87    "TOP",
88    "BOTTOM",
89    "LEFT",
90    "RIGHT",
91    "FRONT",
92    "BACK",
93    "UNKNOWN",
94    NULL
95};
96
97static char *AslPldVerticalPositionList[] =
98{
99    "UPPER",
100    "CENTER",
101    "LOWER",
102    NULL
103};
104
105static char *AslPldHorizontalPositionList[] =
106{
107    "LEFT",
108    "CENTER",
109    "RIGHT",
110    NULL
111};
112
113static char *AslPldShapeList[] =
114{
115    "ROUND",
116    "OVAL",
117    "SQUARE",
118    "VERTICALRECTANGLE",
119    "HORIZONTALRECTANGLE",
120    "VERTICALTRAPEZOID",
121    "HORIZONTALTRAPEZOID",
122    "UNKNOWN",
123    "CHAMFERED",
124    NULL
125};
126
127
128/*******************************************************************************
129 *
130 * FUNCTION:    OpcAmlOpcodeUpdateWalk
131 *
132 * PARAMETERS:  ASL_WALK_CALLBACK
133 *
134 * RETURN:      Status
135 *
136 * DESCRIPTION: Opcode update walk, ascending callback
137 *
138 ******************************************************************************/
139
140ACPI_STATUS
141OpcAmlOpcodeUpdateWalk (
142    ACPI_PARSE_OBJECT       *Op,
143    UINT32                  Level,
144    void                    *Context)
145{
146
147    /*
148     * Handle the Package() case where the actual opcode cannot be determined
149     * until the PackageLength operand has been folded and minimized.
150     * (PackageOp versus VarPackageOp)
151     *
152     * This is (as of ACPI 3.0) the only case where the AML opcode can change
153     * based upon the value of a parameter.
154     *
155     * The parser always inserts a VarPackage opcode, which can possibly be
156     * optimized to a Package opcode.
157     */
158    if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
159    {
160        OpnDoPackage (Op);
161    }
162
163    return (AE_OK);
164}
165
166
167/*******************************************************************************
168 *
169 * FUNCTION:    OpcAmlOpcodeWalk
170 *
171 * PARAMETERS:  ASL_WALK_CALLBACK
172 *
173 * RETURN:      Status
174 *
175 * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
176 *              operands.
177 *
178 ******************************************************************************/
179
180ACPI_STATUS
181OpcAmlOpcodeWalk (
182    ACPI_PARSE_OBJECT       *Op,
183    UINT32                  Level,
184    void                    *Context)
185{
186
187    TotalParseNodes++;
188
189    OpcGenerateAmlOpcode (Op);
190    OpnGenerateAmlOperands (Op);
191    return (AE_OK);
192}
193
194
195/*******************************************************************************
196 *
197 * FUNCTION:    OpcGetIntegerWidth
198 *
199 * PARAMETERS:  Op          - DEFINITION BLOCK op
200 *
201 * RETURN:      none
202 *
203 * DESCRIPTION: Extract integer width from the table revision
204 *
205 ******************************************************************************/
206
207void
208OpcGetIntegerWidth (
209    ACPI_PARSE_OBJECT       *Op)
210{
211    ACPI_PARSE_OBJECT       *Child;
212
213
214    if (!Op)
215    {
216        return;
217    }
218
219    if (Gbl_RevisionOverride)
220    {
221        AcpiUtSetIntegerWidth (Gbl_RevisionOverride);
222    }
223    else
224    {
225        Child = Op->Asl.Child;
226        Child = Child->Asl.Next;
227        Child = Child->Asl.Next;
228
229        /* Use the revision to set the integer width */
230
231        AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
232    }
233}
234
235
236/*******************************************************************************
237 *
238 * FUNCTION:    OpcSetOptimalIntegerSize
239 *
240 * PARAMETERS:  Op        - A parse tree node
241 *
242 * RETURN:      Integer width, in bytes. Also sets the node AML opcode to the
243 *              optimal integer AML prefix opcode.
244 *
245 * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading
246 *              zeros can be truncated to squeeze the integer into the
247 *              minimal number of AML bytes.
248 *
249 ******************************************************************************/
250
251UINT32
252OpcSetOptimalIntegerSize (
253    ACPI_PARSE_OBJECT       *Op)
254{
255
256#if 0
257    /*
258     * TBD: - we don't want to optimize integers in the block header, but the
259     * code below does not work correctly.
260     */
261    if (Op->Asl.Parent &&
262        Op->Asl.Parent->Asl.Parent &&
263       (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK))
264    {
265        return (0);
266    }
267#endif
268
269    /*
270     * Check for the special AML integers first - Zero, One, Ones.
271     * These are single-byte opcodes that are the smallest possible
272     * representation of an integer.
273     *
274     * This optimization is optional.
275     */
276    if (Gbl_IntegerOptimizationFlag)
277    {
278        switch (Op->Asl.Value.Integer)
279        {
280        case 0:
281
282            Op->Asl.AmlOpcode = AML_ZERO_OP;
283            AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
284                Op, "Zero");
285            return (1);
286
287        case 1:
288
289            Op->Asl.AmlOpcode = AML_ONE_OP;
290            AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
291                Op, "One");
292            return (1);
293
294        case ACPI_UINT32_MAX:
295
296            /* Check for table integer width (32 or 64) */
297
298            if (AcpiGbl_IntegerByteWidth == 4)
299            {
300                Op->Asl.AmlOpcode = AML_ONES_OP;
301                AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
302                    Op, "Ones");
303                return (1);
304            }
305            break;
306
307        case ACPI_UINT64_MAX:
308
309            /* Check for table integer width (32 or 64) */
310
311            if (AcpiGbl_IntegerByteWidth == 8)
312            {
313                Op->Asl.AmlOpcode = AML_ONES_OP;
314                AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
315                    Op, "Ones");
316                return (1);
317            }
318            break;
319
320        default:
321
322            break;
323        }
324    }
325
326    /* Find the best fit using the various AML integer prefixes */
327
328    if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
329    {
330        Op->Asl.AmlOpcode = AML_BYTE_OP;
331        return (1);
332    }
333    if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
334    {
335        Op->Asl.AmlOpcode = AML_WORD_OP;
336        return (2);
337    }
338    if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
339    {
340        Op->Asl.AmlOpcode = AML_DWORD_OP;
341        return (4);
342    }
343    else
344    {
345        if (AcpiGbl_IntegerByteWidth == 4)
346        {
347            AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
348                Op, NULL);
349
350            if (!Gbl_IgnoreErrors)
351            {
352                /* Truncate the integer to 32-bit */
353                Op->Asl.AmlOpcode = AML_DWORD_OP;
354                return (4);
355            }
356        }
357
358        Op->Asl.AmlOpcode = AML_QWORD_OP;
359        return (8);
360    }
361}
362
363
364/*******************************************************************************
365 *
366 * FUNCTION:    OpcDoAccessAs
367 *
368 * PARAMETERS:  Op        - Parse node
369 *
370 * RETURN:      None
371 *
372 * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
373 *
374 ******************************************************************************/
375
376static void
377OpcDoAccessAs (
378    ACPI_PARSE_OBJECT       *Op)
379{
380    ACPI_PARSE_OBJECT       *TypeOp;
381    ACPI_PARSE_OBJECT       *AttribOp;
382    ACPI_PARSE_OBJECT       *LengthOp;
383    UINT8                   Attribute;
384
385
386    Op->Asl.AmlOpcodeLength = 1;
387    TypeOp = Op->Asl.Child;
388
389    /* First child is the access type */
390
391    TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
392    TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
393
394    /* Second child is the optional access attribute */
395
396    AttribOp = TypeOp->Asl.Next;
397    if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
398    {
399        AttribOp->Asl.Value.Integer = 0;
400    }
401    AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
402    AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
403
404    /* Only a few AccessAttributes support AccessLength */
405
406    Attribute = (UINT8) AttribOp->Asl.Value.Integer;
407    if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
408        (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
409        (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
410    {
411        return;
412    }
413
414    Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
415
416    /*
417     * Child of Attributes is the AccessLength (required for Multibyte,
418     * RawBytes, RawProcess.)
419     */
420    LengthOp = AttribOp->Asl.Child;
421    if (!LengthOp)
422    {
423        return;
424    }
425
426    /* TBD: probably can remove */
427
428    if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
429    {
430        LengthOp->Asl.Value.Integer = 16;
431    }
432
433    LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
434    LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
435}
436
437
438/*******************************************************************************
439 *
440 * FUNCTION:    OpcDoConnection
441 *
442 * PARAMETERS:  Op        - Parse node
443 *
444 * RETURN:      None
445 *
446 * DESCRIPTION: Implement the Connection ASL keyword.
447 *
448 ******************************************************************************/
449
450static void
451OpcDoConnection (
452    ACPI_PARSE_OBJECT       *Op)
453{
454    ASL_RESOURCE_NODE       *Rnode;
455    ACPI_PARSE_OBJECT       *BufferOp;
456    ACPI_PARSE_OBJECT       *BufferLengthOp;
457    ACPI_PARSE_OBJECT       *BufferDataOp;
458    ASL_RESOURCE_INFO       Info;
459    UINT8                   State;
460
461
462    Op->Asl.AmlOpcodeLength = 1;
463
464    if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
465    {
466        return;
467    }
468
469    BufferOp = Op->Asl.Child;
470    BufferLengthOp = BufferOp->Asl.Child;
471    BufferDataOp = BufferLengthOp->Asl.Next;
472
473    Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
474    Info.CurrentByteOffset = 0;
475    State = ACPI_RSTATE_NORMAL;
476    Rnode = RsDoOneResourceDescriptor (&Info, &State);
477    if (!Rnode)
478    {
479        return; /* error */
480    }
481
482    /*
483     * Transform the nodes into the following
484     *
485     * Op           -> AML_BUFFER_OP
486     * First Child  -> BufferLength
487     * Second Child -> Descriptor Buffer (raw byte data)
488     */
489    BufferOp->Asl.ParseOpcode         = PARSEOP_BUFFER;
490    BufferOp->Asl.AmlOpcode           = AML_BUFFER_OP;
491    BufferOp->Asl.CompileFlags        = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
492    UtSetParseOpName (BufferOp);
493
494    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
495    BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
496    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
497    UtSetParseOpName (BufferLengthOp);
498
499    BufferDataOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
500    BufferDataOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
501    BufferDataOp->Asl.AmlOpcodeLength     = 0;
502    BufferDataOp->Asl.AmlLength           = Rnode->BufferLength;
503    BufferDataOp->Asl.Value.Buffer        = (UINT8 *) Rnode;
504    UtSetParseOpName (BufferDataOp);
505}
506
507
508/*******************************************************************************
509 *
510 * FUNCTION:    OpcDoUnicode
511 *
512 * PARAMETERS:  Op        - Parse node
513 *
514 * RETURN:      None
515 *
516 * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
517 *              to a unicode buffer. There is no Unicode AML opcode.
518 *
519 * Note:  The Unicode string is 16 bits per character, no leading signature,
520 *        with a 16-bit terminating NULL.
521 *
522 ******************************************************************************/
523
524static void
525OpcDoUnicode (
526    ACPI_PARSE_OBJECT       *Op)
527{
528    ACPI_PARSE_OBJECT       *InitializerOp;
529    UINT32                  Length;
530    UINT32                  Count;
531    UINT32                  i;
532    UINT8                   *AsciiString;
533    UINT16                  *UnicodeString;
534    ACPI_PARSE_OBJECT       *BufferLengthOp;
535
536
537    /* Change op into a buffer object */
538
539    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
540    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
541    UtSetParseOpName (Op);
542
543    /* Buffer Length is first, followed by the string */
544
545    BufferLengthOp = Op->Asl.Child;
546    InitializerOp = BufferLengthOp->Asl.Next;
547
548    AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
549
550    /* Create a new buffer for the Unicode string */
551
552    Count = strlen (InitializerOp->Asl.Value.String) + 1;
553    Length = Count * sizeof (UINT16);
554    UnicodeString = UtLocalCalloc (Length);
555
556    /* Convert to Unicode string (including null terminator) */
557
558    for (i = 0; i < Count; i++)
559    {
560        UnicodeString[i] = (UINT16) AsciiString[i];
561    }
562
563    /*
564     * Just set the buffer size node to be the buffer length, regardless
565     * of whether it was previously an integer or a default_arg placeholder
566     */
567    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
568    BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
569    BufferLengthOp->Asl.Value.Integer = Length;
570    UtSetParseOpName (BufferLengthOp);
571
572    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
573
574    /* The Unicode string is a raw data buffer */
575
576    InitializerOp->Asl.Value.Buffer   = (UINT8 *) UnicodeString;
577    InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
578    InitializerOp->Asl.AmlLength      = Length;
579    InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
580    InitializerOp->Asl.Child          = NULL;
581    UtSetParseOpName (InitializerOp);
582}
583
584
585/*******************************************************************************
586 *
587 * FUNCTION:    OpcDoEisaId
588 *
589 * PARAMETERS:  Op        - Parse node
590 *
591 * RETURN:      None
592 *
593 * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
594 *              Pnp BIOS Specification for details. Here is an excerpt:
595 *
596 *              A seven character ASCII representation of the product
597 *              identifier compressed into a 32-bit identifier. The seven
598 *              character ID consists of a three character manufacturer code,
599 *              a three character hexadecimal product identifier, and a one
600 *              character hexadecimal revision number. The manufacturer code
601 *              is a 3 uppercase character code that is compressed into 3 5-bit
602 *              values as follows:
603 *                  1) Find hex ASCII value for each letter
604 *                  2) Subtract 40h from each ASCII value
605 *                  3) Retain 5 least significant bits for each letter by
606 *                     discarding upper 3 bits because they are always 0.
607 *                  4) Compressed code = concatenate 0 and the 3 5-bit values
608 *
609 *              The format of the compressed product identifier is as follows:
610 *              Byte 0: Bit 7       - Reserved (0)
611 *                      Bits 6-2:   - 1st character of compressed mfg code
612 *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
613 *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
614 *                      Bits 4-0    - 3rd character of mfg code
615 *              Byte 2: Bits 7-4    - 1st hex digit of product number
616 *                      Bits 3-0    - 2nd hex digit of product number
617 *              Byte 3: Bits 7-4    - 3st hex digit of product number
618 *                      Bits 3-0    - Hex digit of the revision number
619 *
620 ******************************************************************************/
621
622static void
623OpcDoEisaId (
624    ACPI_PARSE_OBJECT       *Op)
625{
626    UINT32                  EisaId = 0;
627    UINT32                  BigEndianId;
628    char                    *InString;
629    ACPI_STATUS             Status = AE_OK;
630    UINT32                  i;
631
632
633    InString = (char *) Op->Asl.Value.String;
634
635    /*
636     * The EISAID string must be exactly 7 characters and of the form
637     * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
638     */
639    if (ACPI_STRLEN (InString) != 7)
640    {
641        Status = AE_BAD_PARAMETER;
642    }
643    else
644    {
645        /* Check all 7 characters for correct format */
646
647        for (i = 0; i < 7; i++)
648        {
649            /* First 3 characters must be uppercase letters */
650
651            if (i < 3)
652            {
653                if (!isupper ((int) InString[i]))
654                {
655                    Status = AE_BAD_PARAMETER;
656                }
657            }
658
659            /* Last 4 characters must be hex digits */
660
661            else if (!isxdigit ((int) InString[i]))
662            {
663                Status = AE_BAD_PARAMETER;
664            }
665        }
666    }
667
668    if (ACPI_FAILURE (Status))
669    {
670        AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
671    }
672    else
673    {
674        /* Create ID big-endian first (bits are contiguous) */
675
676        BigEndianId =
677            (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
678            (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
679            (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
680
681            (AcpiUtAsciiCharToHex (InString[3])) << 12 |
682            (AcpiUtAsciiCharToHex (InString[4])) << 8  |
683            (AcpiUtAsciiCharToHex (InString[5])) << 4  |
684             AcpiUtAsciiCharToHex (InString[6]);
685
686        /* Swap to little-endian to get final ID (see function header) */
687
688        EisaId = AcpiUtDwordByteSwap (BigEndianId);
689    }
690
691    /*
692     * Morph the Op into an integer, regardless of whether there
693     * was an error in the EISAID string
694     */
695    Op->Asl.Value.Integer = EisaId;
696
697    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
698    Op->Asl.ParseOpcode = PARSEOP_INTEGER;
699    (void) OpcSetOptimalIntegerSize (Op);
700
701    /* Op is now an integer */
702
703    UtSetParseOpName (Op);
704}
705
706
707/*******************************************************************************
708 *
709 * FUNCTION:    OpcEncodePldBuffer
710 *
711 * PARAMETERS:  PldInfo             - _PLD buffer struct (Using local struct)
712 *
713 * RETURN:      Encode _PLD buffer suitable for return value from _PLD
714 *
715 * DESCRIPTION: Bit-packs a _PLD buffer struct.
716 *
717 ******************************************************************************/
718
719static UINT8 *
720OpcEncodePldBuffer (
721    ACPI_PLD_INFO           *PldInfo)
722{
723    UINT32                  *Buffer;
724    UINT32                  Dword;
725
726
727    Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE);
728    if (!Buffer)
729    {
730        return (NULL);
731    }
732
733    /* First 32 bits */
734
735    Dword = 0;
736    ACPI_PLD_SET_REVISION       (&Dword, PldInfo->Revision);
737    ACPI_PLD_SET_IGNORE_COLOR   (&Dword, PldInfo->IgnoreColor);
738    ACPI_PLD_SET_RED            (&Dword, PldInfo->Red);
739    ACPI_PLD_SET_GREEN          (&Dword, PldInfo->Green);
740    ACPI_PLD_SET_BLUE           (&Dword, PldInfo->Blue);
741    ACPI_MOVE_32_TO_32          (&Buffer[0], &Dword);
742
743    /* Second 32 bits */
744
745    Dword = 0;
746    ACPI_PLD_SET_WIDTH          (&Dword, PldInfo->Width);
747    ACPI_PLD_SET_HEIGHT         (&Dword, PldInfo->Height);
748    ACPI_MOVE_32_TO_32          (&Buffer[1], &Dword);
749
750    /* Third 32 bits */
751
752    Dword = 0;
753    ACPI_PLD_SET_USER_VISIBLE   (&Dword, PldInfo->UserVisible);
754    ACPI_PLD_SET_DOCK           (&Dword, PldInfo->Dock);
755    ACPI_PLD_SET_LID            (&Dword, PldInfo->Lid);
756    ACPI_PLD_SET_PANEL          (&Dword, PldInfo->Panel);
757    ACPI_PLD_SET_VERTICAL       (&Dword, PldInfo->VerticalPosition);
758    ACPI_PLD_SET_HORIZONTAL     (&Dword, PldInfo->HorizontalPosition);
759    ACPI_PLD_SET_SHAPE          (&Dword, PldInfo->Shape);
760    ACPI_PLD_SET_ORIENTATION    (&Dword, PldInfo->GroupOrientation);
761    ACPI_PLD_SET_TOKEN          (&Dword, PldInfo->GroupToken);
762    ACPI_PLD_SET_POSITION       (&Dword, PldInfo->GroupPosition);
763    ACPI_PLD_SET_BAY            (&Dword, PldInfo->Bay);
764    ACPI_MOVE_32_TO_32          (&Buffer[2], &Dword);
765
766    /* Fourth 32 bits */
767
768    Dword = 0;
769    ACPI_PLD_SET_EJECTABLE      (&Dword, PldInfo->Ejectable);
770    ACPI_PLD_SET_OSPM_EJECT     (&Dword, PldInfo->OspmEjectRequired);
771    ACPI_PLD_SET_CABINET        (&Dword, PldInfo->CabinetNumber);
772    ACPI_PLD_SET_CARD_CAGE      (&Dword, PldInfo->CardCageNumber);
773    ACPI_PLD_SET_REFERENCE      (&Dword, PldInfo->Reference);
774    ACPI_PLD_SET_ROTATION       (&Dword, PldInfo->Rotation);
775    ACPI_PLD_SET_ORDER          (&Dword, PldInfo->Order);
776    ACPI_MOVE_32_TO_32          (&Buffer[3], &Dword);
777
778    if (PldInfo->Revision >= 2)
779    {
780        /* Fifth 32 bits */
781
782        Dword = 0;
783        ACPI_PLD_SET_VERT_OFFSET    (&Dword, PldInfo->VerticalOffset);
784        ACPI_PLD_SET_HORIZ_OFFSET   (&Dword, PldInfo->HorizontalOffset);
785        ACPI_MOVE_32_TO_32          (&Buffer[4], &Dword);
786    }
787
788    return (ACPI_CAST_PTR (UINT8, Buffer));
789}
790
791
792/*******************************************************************************
793 *
794 * FUNCTION:    OpcStrupr (strupr)
795 *
796 * PARAMETERS:  SrcString           - The source string to convert
797 *
798 * RETURN:      None
799 *
800 * DESCRIPTION: Convert string to uppercase
801 *
802 * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
803 *
804 ******************************************************************************/
805
806static void
807OpcStrupr (
808    char                    *SrcString)
809{
810    char                    *String;
811
812
813    if (!SrcString)
814    {
815        return;
816    }
817
818    /* Walk entire string, uppercasing the letters */
819
820    for (String = SrcString; *String; String++)
821    {
822        *String = (char) toupper ((int) *String);
823    }
824
825    return;
826}
827
828
829/*******************************************************************************
830 *
831 * FUNCTION:    OpcFindName
832 *
833 * PARAMETERS:  List                - Array of char strings to be searched
834 *              Name                - Char string to string for
835 *              Index               - Index value to set if found
836 *
837 * RETURN:      TRUE if any names matched, FALSE otherwise
838 *
839 * DESCRIPTION: Match PLD name to value in lookup table. Sets Value to
840 *              equivalent parameter value.
841 *
842 ******************************************************************************/
843
844static BOOLEAN
845OpcFindName (
846    char                    **List,
847    char                    *Name,
848    UINT64                  *Index)
849{
850    char                     *Str;
851    UINT32                   i;
852
853
854    OpcStrupr (Name);
855
856    for (i = 0, Str = List[0]; Str; i++, Str = List[i])
857    {
858        if (!(ACPI_STRNCMP (Str, Name, ACPI_STRLEN (Name))))
859        {
860            *Index = i;
861            return (TRUE);
862        }
863    }
864
865    return (FALSE);
866}
867
868
869/*******************************************************************************
870 *
871 * FUNCTION:    OpcDoPld
872 *
873 * PARAMETERS:  Op                  - Parse node
874 *
875 * RETURN:      None
876 *
877 * DESCRIPTION: Convert ToPLD macro to 20-byte buffer
878 *
879 ******************************************************************************/
880
881static void
882OpcDoPld (
883    ACPI_PARSE_OBJECT       *Op)
884{
885    UINT8                   *Buffer;
886    ACPI_PARSE_OBJECT       *Node;
887    ACPI_PLD_INFO           PldInfo;
888    ACPI_PARSE_OBJECT       *NewOp;
889
890
891    if (!Op)
892    {
893        AslError(ASL_ERROR, ASL_MSG_NOT_EXIST, Op, NULL);
894        return;
895    }
896
897    if (Op->Asl.ParseOpcode != PARSEOP_TOPLD)
898    {
899        AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Op, NULL);
900        return;
901    }
902
903    Buffer = UtLocalCalloc (ACPI_PLD_BUFFER_SIZE);
904    if (!Buffer)
905    {
906        AslError(ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION, Op, NULL);
907        return;
908    }
909
910    ACPI_MEMSET (&PldInfo, 0, sizeof (ACPI_PLD_INFO));
911
912    Node = Op->Asl.Child;
913    while (Node)
914    {
915        switch (Node->Asl.ParseOpcode)
916        {
917        case PARSEOP_PLD_REVISION:
918
919            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
920            {
921                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
922                break;
923            }
924
925            if (Node->Asl.Child->Asl.Value.Integer > 127)
926            {
927                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
928                break;
929            }
930
931            PldInfo.Revision = (UINT8) Node->Asl.Child->Asl.Value.Integer;
932            break;
933
934        case PARSEOP_PLD_IGNORECOLOR:
935
936            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
937            {
938                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
939                break;
940            }
941
942            if (Node->Asl.Child->Asl.Value.Integer > 1)
943            {
944                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
945                break;
946            }
947
948            PldInfo.IgnoreColor = (UINT8) Node->Asl.Child->Asl.Value.Integer;
949            break;
950
951        case PARSEOP_PLD_RED:
952        case PARSEOP_PLD_GREEN:
953        case PARSEOP_PLD_BLUE:
954
955            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
956            {
957                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
958                break;
959            }
960
961            if (Node->Asl.Child->Asl.Value.Integer > 255)
962            {
963                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
964                break;
965            }
966
967            if (Node->Asl.ParseOpcode == PARSEOP_PLD_RED)
968            {
969                PldInfo.Red = (UINT8) Node->Asl.Child->Asl.Value.Integer;
970            }
971            else if (Node->Asl.ParseOpcode == PARSEOP_PLD_GREEN)
972            {
973                PldInfo.Green = (UINT8) Node->Asl.Child->Asl.Value.Integer;
974            }
975            else /* PARSEOP_PLD_BLUE */
976            {
977                PldInfo.Blue = (UINT8) Node->Asl.Child->Asl.Value.Integer;
978            }
979            break;
980
981        case PARSEOP_PLD_WIDTH:
982        case PARSEOP_PLD_HEIGHT:
983
984            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
985            {
986                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
987                break;
988            }
989
990            if (Node->Asl.Child->Asl.Value.Integer > 65535)
991            {
992                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
993                break;
994            }
995
996            if (Node->Asl.ParseOpcode == PARSEOP_PLD_WIDTH)
997            {
998                PldInfo.Width = (UINT16) Node->Asl.Child->Asl.Value.Integer;
999            }
1000            else /* PARSEOP_PLD_HEIGHT */
1001            {
1002                PldInfo.Height = (UINT16) Node->Asl.Child->Asl.Value.Integer;
1003            }
1004
1005            break;
1006
1007        case PARSEOP_PLD_USERVISIBLE:
1008        case PARSEOP_PLD_DOCK:
1009        case PARSEOP_PLD_LID:
1010
1011            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1012            {
1013                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1014                break;
1015            }
1016
1017            if (Node->Asl.Child->Asl.Value.Integer > 1)
1018            {
1019                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1020                break;
1021            }
1022
1023            if (Node->Asl.ParseOpcode == PARSEOP_PLD_USERVISIBLE)
1024            {
1025                PldInfo.UserVisible = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1026            }
1027            else if (Node->Asl.ParseOpcode == PARSEOP_PLD_DOCK)
1028            {
1029                PldInfo.Dock = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1030            }
1031            else
1032            {
1033                PldInfo.Lid = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1034            }
1035
1036            break;
1037
1038        case PARSEOP_PLD_PANEL:
1039
1040            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1041            {
1042                if (Node->Asl.Child->Asl.Value.Integer > 6)
1043                {
1044                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1045                    break;
1046                }
1047            }
1048            else /* PARSEOP_STRING */
1049            {
1050                if (!OpcFindName(AslPldPanelList,
1051                    Node->Asl.Child->Asl.Value.String,
1052                    &Node->Asl.Child->Asl.Value.Integer))
1053                {
1054                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1055                    break;
1056                }
1057            }
1058
1059            PldInfo.Panel = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1060            break;
1061
1062        case PARSEOP_PLD_VERTICALPOSITION:
1063
1064            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1065            {
1066                if (Node->Asl.Child->Asl.Value.Integer > 2)
1067                {
1068                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1069                    break;
1070                }
1071            }
1072            else /* PARSEOP_STRING */
1073            {
1074                if (!OpcFindName(AslPldVerticalPositionList,
1075                    Node->Asl.Child->Asl.Value.String,
1076                    &Node->Asl.Child->Asl.Value.Integer))
1077                {
1078                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1079                    break;
1080                }
1081            }
1082
1083            PldInfo.VerticalPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1084            break;
1085
1086        case PARSEOP_PLD_HORIZONTALPOSITION:
1087
1088            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1089            {
1090                if (Node->Asl.Child->Asl.Value.Integer > 2)
1091                {
1092                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1093                    break;
1094                }
1095            }
1096            else /* PARSEOP_STRING */
1097            {
1098                if (!OpcFindName(AslPldHorizontalPositionList,
1099                    Node->Asl.Child->Asl.Value.String,
1100                    &Node->Asl.Child->Asl.Value.Integer))
1101                {
1102                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1103                    break;
1104                }
1105            }
1106
1107            PldInfo.HorizontalPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1108            break;
1109
1110        case PARSEOP_PLD_SHAPE:
1111
1112            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1113            {
1114                if (Node->Asl.Child->Asl.Value.Integer > 8)
1115                {
1116                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1117                    break;
1118                }
1119            }
1120            else /* PARSEOP_STRING */
1121            {
1122                if (!OpcFindName(AslPldShapeList,
1123                    Node->Asl.Child->Asl.Value.String,
1124                    &Node->Asl.Child->Asl.Value.Integer))
1125                {
1126                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1127                    break;
1128                }
1129            }
1130
1131            PldInfo.Shape = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1132            break;
1133
1134        case PARSEOP_PLD_GROUPORIENTATION:
1135
1136            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1137            {
1138                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1139                break;
1140            }
1141
1142            if (Node->Asl.Child->Asl.Value.Integer > 1)
1143            {
1144                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1145                break;
1146            }
1147
1148            PldInfo.GroupOrientation = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1149            break;
1150
1151        case PARSEOP_PLD_GROUPTOKEN:
1152        case PARSEOP_PLD_GROUPPOSITION:
1153
1154            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1155            {
1156                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1157                break;
1158            }
1159
1160            if (Node->Asl.Child->Asl.Value.Integer > 255)
1161            {
1162                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1163                break;
1164            }
1165
1166
1167            if (Node->Asl.ParseOpcode == PARSEOP_PLD_GROUPTOKEN)
1168            {
1169                PldInfo.GroupToken = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1170            }
1171            else /* PARSEOP_PLD_GROUPPOSITION */
1172            {
1173                PldInfo.GroupPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1174            }
1175
1176            break;
1177
1178        case PARSEOP_PLD_BAY:
1179        case PARSEOP_PLD_EJECTABLE:
1180        case PARSEOP_PLD_EJECTREQUIRED:
1181
1182            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1183            {
1184                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1185                break;
1186            }
1187
1188            if (Node->Asl.Child->Asl.Value.Integer > 1)
1189            {
1190                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1191                break;
1192            }
1193
1194            if (Node->Asl.ParseOpcode == PARSEOP_PLD_BAY)
1195            {
1196                PldInfo.Bay = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1197            }
1198            else if (Node->Asl.ParseOpcode == PARSEOP_PLD_EJECTABLE)
1199            {
1200                PldInfo.Ejectable = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1201            }
1202            else /* PARSEOP_PLD_EJECTREQUIRED */
1203            {
1204                PldInfo.OspmEjectRequired = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1205            }
1206
1207            break;
1208
1209        case PARSEOP_PLD_CABINETNUMBER:
1210        case PARSEOP_PLD_CARDCAGENUMBER:
1211
1212            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1213            {
1214                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1215                break;
1216            }
1217
1218            if (Node->Asl.Child->Asl.Value.Integer > 255)
1219            {
1220                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1221                break;
1222            }
1223
1224            if (Node->Asl.ParseOpcode == PARSEOP_PLD_CABINETNUMBER)
1225            {
1226                PldInfo.CabinetNumber = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1227            }
1228            else /* PARSEOP_PLD_CARDCAGENUMBER */
1229            {
1230                PldInfo.CardCageNumber = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1231            }
1232
1233            break;
1234
1235        case PARSEOP_PLD_REFERENCE:
1236
1237            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1238            {
1239                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1240                break;
1241            }
1242
1243            if (Node->Asl.Child->Asl.Value.Integer > 1)
1244            {
1245                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1246                break;
1247            }
1248
1249            PldInfo.Reference = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1250            break;
1251
1252        case PARSEOP_PLD_ROTATION:
1253
1254            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1255            {
1256                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1257                break;
1258            }
1259
1260            if (Node->Asl.Child->Asl.Value.Integer > 7)
1261            {
1262                switch (Node->Asl.Child->Asl.Value.Integer)
1263                {
1264                case 45:
1265
1266                    Node->Asl.Child->Asl.Value.Integer = 1;
1267                    break;
1268
1269                case 90:
1270
1271                    Node->Asl.Child->Asl.Value.Integer = 2;
1272                    break;
1273
1274                case 135:
1275
1276                    Node->Asl.Child->Asl.Value.Integer = 3;
1277                    break;
1278
1279                case 180:
1280
1281                    Node->Asl.Child->Asl.Value.Integer = 4;
1282                    break;
1283
1284                case 225:
1285
1286                    Node->Asl.Child->Asl.Value.Integer = 5;
1287                    break;
1288
1289                case 270:
1290
1291                    Node->Asl.Child->Asl.Value.Integer = 6;
1292                    break;
1293
1294                case 315:
1295
1296                    Node->Asl.Child->Asl.Value.Integer = 7;
1297                    break;
1298
1299                default:
1300
1301                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1302                    break;
1303                }
1304            }
1305
1306            PldInfo.Rotation = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1307            break;
1308
1309        case PARSEOP_PLD_ORDER:
1310
1311            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1312            {
1313                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1314                break;
1315            }
1316
1317            if (Node->Asl.Child->Asl.Value.Integer > 31)
1318            {
1319                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1320                break;
1321            }
1322
1323            PldInfo.Order = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1324            break;
1325
1326        case PARSEOP_PLD_VERTICALOFFSET:
1327        case PARSEOP_PLD_HORIZONTALOFFSET:
1328
1329            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1330            {
1331                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1332                break;
1333            }
1334
1335            if (Node->Asl.Child->Asl.Value.Integer > 65535)
1336            {
1337                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1338                break;
1339            }
1340
1341            if (Node->Asl.ParseOpcode == PARSEOP_PLD_VERTICALOFFSET)
1342            {
1343                PldInfo.VerticalOffset = (UINT16) Node->Asl.Child->Asl.Value.Integer;
1344            }
1345            else /* PARSEOP_PLD_HORIZONTALOFFSET */
1346            {
1347                PldInfo.HorizontalOffset = (UINT16) Node->Asl.Child->Asl.Value.Integer;
1348            }
1349
1350            break;
1351
1352        default:
1353
1354            AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1355            break;
1356        }
1357
1358        Node = Node->Asl.Next;
1359    }
1360
1361    Buffer = OpcEncodePldBuffer(&PldInfo);
1362
1363    /* Change Op to a Buffer */
1364
1365    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
1366    Op->Common.AmlOpcode = AML_BUFFER_OP;
1367
1368    /* Disable further optimization */
1369
1370    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
1371    UtSetParseOpName (Op);
1372
1373    /* Child node is the buffer length */
1374
1375    NewOp = TrAllocateNode (PARSEOP_INTEGER);
1376
1377    NewOp->Asl.AmlOpcode     = AML_BYTE_OP;
1378    NewOp->Asl.Value.Integer = 20;
1379    NewOp->Asl.Parent        = Op;
1380
1381    Op->Asl.Child = NewOp;
1382    Op = NewOp;
1383
1384    /* Peer to the child is the raw buffer data */
1385
1386    NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
1387    NewOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
1388    NewOp->Asl.AmlLength     = 20;
1389    NewOp->Asl.Value.String  = ACPI_CAST_PTR (char, Buffer);
1390    NewOp->Asl.Parent        = Op->Asl.Parent;
1391
1392    Op->Asl.Next = NewOp;
1393}
1394
1395
1396/*******************************************************************************
1397 *
1398 * FUNCTION:    OpcDoUuId
1399 *
1400 * PARAMETERS:  Op                  - Parse node
1401 *
1402 * RETURN:      None
1403 *
1404 * DESCRIPTION: Convert UUID string to 16-byte buffer
1405 *
1406 ******************************************************************************/
1407
1408static void
1409OpcDoUuId (
1410    ACPI_PARSE_OBJECT       *Op)
1411{
1412    char                    *InString;
1413    UINT8                   *Buffer;
1414    ACPI_STATUS             Status = AE_OK;
1415    ACPI_PARSE_OBJECT       *NewOp;
1416
1417
1418    InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
1419    Buffer = UtLocalCalloc (16);
1420
1421    Status = AuValidateUuid (InString);
1422    if (ACPI_FAILURE (Status))
1423    {
1424        AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
1425    }
1426    else
1427    {
1428        AcpiUtConvertStringToUuid (InString, Buffer);
1429    }
1430
1431    /* Change Op to a Buffer */
1432
1433    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
1434    Op->Common.AmlOpcode = AML_BUFFER_OP;
1435
1436    /* Disable further optimization */
1437
1438    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
1439    UtSetParseOpName (Op);
1440
1441    /* Child node is the buffer length */
1442
1443    NewOp = TrAllocateNode (PARSEOP_INTEGER);
1444
1445    NewOp->Asl.AmlOpcode     = AML_BYTE_OP;
1446    NewOp->Asl.Value.Integer = 16;
1447    NewOp->Asl.Parent        = Op;
1448
1449    Op->Asl.Child = NewOp;
1450    Op = NewOp;
1451
1452    /* Peer to the child is the raw buffer data */
1453
1454    NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
1455    NewOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
1456    NewOp->Asl.AmlLength     = 16;
1457    NewOp->Asl.Value.String  = ACPI_CAST_PTR (char, Buffer);
1458    NewOp->Asl.Parent        = Op->Asl.Parent;
1459
1460    Op->Asl.Next = NewOp;
1461}
1462
1463
1464/*******************************************************************************
1465 *
1466 * FUNCTION:    OpcGenerateAmlOpcode
1467 *
1468 * PARAMETERS:  Op                  - Parse node
1469 *
1470 * RETURN:      None
1471 *
1472 * DESCRIPTION: Generate the AML opcode associated with the node and its
1473 *              parse (lex/flex) keyword opcode. Essentially implements
1474 *              a mapping between the parse opcodes and the actual AML opcodes.
1475 *
1476 ******************************************************************************/
1477
1478void
1479OpcGenerateAmlOpcode (
1480    ACPI_PARSE_OBJECT       *Op)
1481{
1482    UINT16                  Index;
1483
1484
1485    Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
1486
1487    Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
1488    Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
1489    Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
1490
1491    if (!Op->Asl.Value.Integer)
1492    {
1493        Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
1494    }
1495
1496    /* Special handling for some opcodes */
1497
1498    switch (Op->Asl.ParseOpcode)
1499    {
1500    case PARSEOP_INTEGER:
1501        /*
1502         * Set the opcode based on the size of the integer
1503         */
1504        (void) OpcSetOptimalIntegerSize (Op);
1505        break;
1506
1507    case PARSEOP_OFFSET:
1508
1509        Op->Asl.AmlOpcodeLength = 1;
1510        break;
1511
1512    case PARSEOP_ACCESSAS:
1513
1514        OpcDoAccessAs (Op);
1515        break;
1516
1517    case PARSEOP_CONNECTION:
1518
1519        OpcDoConnection (Op);
1520        break;
1521
1522    case PARSEOP_EISAID:
1523
1524        OpcDoEisaId (Op);
1525        break;
1526
1527    case PARSEOP_PRINTF:
1528
1529        OpcDoPrintf (Op);
1530        break;
1531
1532    case PARSEOP_FPRINTF:
1533
1534        OpcDoFprintf (Op);
1535        break;
1536
1537    case PARSEOP_TOPLD:
1538
1539        OpcDoPld (Op);
1540        break;
1541
1542    case PARSEOP_TOUUID:
1543
1544        OpcDoUuId (Op);
1545        break;
1546
1547    case PARSEOP_UNICODE:
1548
1549        OpcDoUnicode (Op);
1550        break;
1551
1552    case PARSEOP_INCLUDE:
1553
1554        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1555        Gbl_HasIncludeFiles = TRUE;
1556        break;
1557
1558    case PARSEOP_EXTERNAL:
1559
1560        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1561        Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1562        break;
1563
1564    case PARSEOP_TIMER:
1565
1566        if (AcpiGbl_IntegerBitWidth == 32)
1567        {
1568            AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
1569        }
1570        break;
1571
1572    default:
1573
1574        /* Nothing to do for other opcodes */
1575
1576        break;
1577    }
1578
1579    return;
1580}
1581