1 /******************************************************************************
2  *
3  * Module Name: aslopcode - AML opcode generation
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47 
48 #define _COMPONENT          ACPI_COMPILER
49         ACPI_MODULE_NAME    ("aslopcodes")
50 
51 
52 /* Local prototypes */
53 
54 static void
55 OpcDoAccessAs (
56     ACPI_PARSE_OBJECT       *Op);
57 
58 static void
59 OpcDoConnection (
60     ACPI_PARSE_OBJECT       *Op);
61 
62 static void
63 OpcDoUnicode (
64     ACPI_PARSE_OBJECT       *Op);
65 
66 static void
67 OpcDoEisaId (
68     ACPI_PARSE_OBJECT       *Op);
69 
70 static void
71 OpcDoPld (
72     ACPI_PARSE_OBJECT       *Op);
73 
74 static void
75 OpcDoUuId (
76     ACPI_PARSE_OBJECT       *Op);
77 
78 static UINT8 *
79 OpcEncodePldBuffer (
80     ACPI_PLD_INFO           *PldInfo);
81 
82 
83 /* ToPld strings */
84 
85 static char *AslPldPanelList[] =
86 {
87     "TOP",
88     "BOTTOM",
89     "LEFT",
90     "RIGHT",
91     "FRONT",
92     "BACK",
93     "UNKNOWN",
94     NULL
95 };
96 
97 static char *AslPldVerticalPositionList[] =
98 {
99     "UPPER",
100     "CENTER",
101     "LOWER",
102     NULL
103 };
104 
105 static char *AslPldHorizontalPositionList[] =
106 {
107     "LEFT",
108     "CENTER",
109     "RIGHT",
110     NULL
111 };
112 
113 static 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 
140 ACPI_STATUS
141 OpcAmlOpcodeUpdateWalk (
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 
180 ACPI_STATUS
181 OpcAmlOpcodeWalk (
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 
207 void
208 OpcGetIntegerWidth (
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 
251 UINT32
252 OpcSetOptimalIntegerSize (
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_DEFINITION_BLOCK))
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 
334     if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
335     {
336         Op->Asl.AmlOpcode = AML_WORD_OP;
337         return (2);
338     }
339 
340     if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
341     {
342         Op->Asl.AmlOpcode = AML_DWORD_OP;
343         return (4);
344     }
345     else
346     {
347         if (AcpiGbl_IntegerByteWidth == 4)
348         {
349             AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
350                 Op, NULL);
351 
352             if (!Gbl_IgnoreErrors)
353             {
354                 /* Truncate the integer to 32-bit */
355                 Op->Asl.AmlOpcode = AML_DWORD_OP;
356                 return (4);
357             }
358         }
359 
360         Op->Asl.AmlOpcode = AML_QWORD_OP;
361         return (8);
362     }
363 }
364 
365 
366 /*******************************************************************************
367  *
368  * FUNCTION:    OpcDoAccessAs
369  *
370  * PARAMETERS:  Op        - Parse node
371  *
372  * RETURN:      None
373  *
374  * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
375  *
376  ******************************************************************************/
377 
378 static void
379 OpcDoAccessAs (
380     ACPI_PARSE_OBJECT       *Op)
381 {
382     ACPI_PARSE_OBJECT       *TypeOp;
383     ACPI_PARSE_OBJECT       *AttribOp;
384     ACPI_PARSE_OBJECT       *LengthOp;
385     UINT8                   Attribute;
386 
387 
388     Op->Asl.AmlOpcodeLength = 1;
389     TypeOp = Op->Asl.Child;
390 
391     /* First child is the access type */
392 
393     TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
394     TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
395 
396     /* Second child is the optional access attribute */
397 
398     AttribOp = TypeOp->Asl.Next;
399     if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
400     {
401         AttribOp->Asl.Value.Integer = 0;
402     }
403 
404     AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
405     AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
406 
407     /* Only a few AccessAttributes support AccessLength */
408 
409     Attribute = (UINT8) AttribOp->Asl.Value.Integer;
410     if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
411         (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
412         (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
413     {
414         return;
415     }
416 
417     Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
418 
419     /*
420      * Child of Attributes is the AccessLength (required for Multibyte,
421      * RawBytes, RawProcess.)
422      */
423     LengthOp = AttribOp->Asl.Child;
424     if (!LengthOp)
425     {
426         return;
427     }
428 
429     /* TBD: probably can remove */
430 
431     if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
432     {
433         LengthOp->Asl.Value.Integer = 16;
434     }
435 
436     LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
437     LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
438 }
439 
440 
441 /*******************************************************************************
442  *
443  * FUNCTION:    OpcDoConnection
444  *
445  * PARAMETERS:  Op        - Parse node
446  *
447  * RETURN:      None
448  *
449  * DESCRIPTION: Implement the Connection ASL keyword.
450  *
451  ******************************************************************************/
452 
453 static void
454 OpcDoConnection (
455     ACPI_PARSE_OBJECT       *Op)
456 {
457     ASL_RESOURCE_NODE       *Rnode;
458     ACPI_PARSE_OBJECT       *BufferOp;
459     ACPI_PARSE_OBJECT       *BufferLengthOp;
460     ACPI_PARSE_OBJECT       *BufferDataOp;
461     ASL_RESOURCE_INFO       Info;
462     UINT8                   State;
463 
464 
465     Op->Asl.AmlOpcodeLength = 1;
466 
467     if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
468     {
469         return;
470     }
471 
472     BufferOp = Op->Asl.Child;
473     BufferLengthOp = BufferOp->Asl.Child;
474     BufferDataOp = BufferLengthOp->Asl.Next;
475 
476     Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
477     Info.CurrentByteOffset = 0;
478     State = ACPI_RSTATE_NORMAL;
479     Rnode = RsDoOneResourceDescriptor (&Info, &State);
480     if (!Rnode)
481     {
482         return; /* error */
483     }
484 
485     /*
486      * Transform the nodes into the following
487      *
488      * Op           -> AML_BUFFER_OP
489      * First Child  -> BufferLength
490      * Second Child -> Descriptor Buffer (raw byte data)
491      */
492     BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
493     BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
494     BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
495     UtSetParseOpName (BufferOp);
496 
497     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
498     BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
499     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
500     UtSetParseOpName (BufferLengthOp);
501 
502     BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
503     BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
504     BufferDataOp->Asl.AmlOpcodeLength = 0;
505     BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
506     BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
507     UtSetParseOpName (BufferDataOp);
508 }
509 
510 
511 /*******************************************************************************
512  *
513  * FUNCTION:    OpcDoUnicode
514  *
515  * PARAMETERS:  Op        - Parse node
516  *
517  * RETURN:      None
518  *
519  * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
520  *              to a unicode buffer. There is no Unicode AML opcode.
521  *
522  * Note:  The Unicode string is 16 bits per character, no leading signature,
523  *        with a 16-bit terminating NULL.
524  *
525  ******************************************************************************/
526 
527 static void
528 OpcDoUnicode (
529     ACPI_PARSE_OBJECT       *Op)
530 {
531     ACPI_PARSE_OBJECT       *InitializerOp;
532     UINT32                  Length;
533     UINT32                  Count;
534     UINT32                  i;
535     UINT8                   *AsciiString;
536     UINT16                  *UnicodeString;
537     ACPI_PARSE_OBJECT       *BufferLengthOp;
538 
539 
540     /* Change op into a buffer object */
541 
542     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
543     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
544     UtSetParseOpName (Op);
545 
546     /* Buffer Length is first, followed by the string */
547 
548     BufferLengthOp = Op->Asl.Child;
549     InitializerOp = BufferLengthOp->Asl.Next;
550 
551     AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
552 
553     /* Create a new buffer for the Unicode string */
554 
555     Count = strlen (InitializerOp->Asl.Value.String) + 1;
556     Length = Count * sizeof (UINT16);
557     UnicodeString = UtLocalCalloc (Length);
558 
559     /* Convert to Unicode string (including null terminator) */
560 
561     for (i = 0; i < Count; i++)
562     {
563         UnicodeString[i] = (UINT16) AsciiString[i];
564     }
565 
566     /*
567      * Just set the buffer size node to be the buffer length, regardless
568      * of whether it was previously an integer or a default_arg placeholder
569      */
570     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
571     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
572     BufferLengthOp->Asl.Value.Integer = Length;
573     UtSetParseOpName (BufferLengthOp);
574 
575     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
576 
577     /* The Unicode string is a raw data buffer */
578 
579     InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
580     InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
581     InitializerOp->Asl.AmlLength = Length;
582     InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
583     InitializerOp->Asl.Child = NULL;
584     UtSetParseOpName (InitializerOp);
585 }
586 
587 
588 /*******************************************************************************
589  *
590  * FUNCTION:    OpcDoEisaId
591  *
592  * PARAMETERS:  Op        - Parse node
593  *
594  * RETURN:      None
595  *
596  * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
597  *              Pnp BIOS Specification for details. Here is an excerpt:
598  *
599  *              A seven character ASCII representation of the product
600  *              identifier compressed into a 32-bit identifier. The seven
601  *              character ID consists of a three character manufacturer code,
602  *              a three character hexadecimal product identifier, and a one
603  *              character hexadecimal revision number. The manufacturer code
604  *              is a 3 uppercase character code that is compressed into 3 5-bit
605  *              values as follows:
606  *                  1) Find hex ASCII value for each letter
607  *                  2) Subtract 40h from each ASCII value
608  *                  3) Retain 5 least significant bits for each letter by
609  *                     discarding upper 3 bits because they are always 0.
610  *                  4) Compressed code = concatenate 0 and the 3 5-bit values
611  *
612  *              The format of the compressed product identifier is as follows:
613  *              Byte 0: Bit 7       - Reserved (0)
614  *                      Bits 6-2:   - 1st character of compressed mfg code
615  *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
616  *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
617  *                      Bits 4-0    - 3rd character of mfg code
618  *              Byte 2: Bits 7-4    - 1st hex digit of product number
619  *                      Bits 3-0    - 2nd hex digit of product number
620  *              Byte 3: Bits 7-4    - 3st hex digit of product number
621  *                      Bits 3-0    - Hex digit of the revision number
622  *
623  ******************************************************************************/
624 
625 static void
626 OpcDoEisaId (
627     ACPI_PARSE_OBJECT       *Op)
628 {
629     UINT32                  EisaId = 0;
630     UINT32                  BigEndianId;
631     char                    *InString;
632     ACPI_STATUS             Status = AE_OK;
633     UINT32                  i;
634 
635 
636     InString = (char *) Op->Asl.Value.String;
637 
638     /*
639      * The EISAID string must be exactly 7 characters and of the form
640      * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
641      */
642     if (strlen (InString) != 7)
643     {
644         Status = AE_BAD_PARAMETER;
645     }
646     else
647     {
648         /* Check all 7 characters for correct format */
649 
650         for (i = 0; i < 7; i++)
651         {
652             /* First 3 characters must be uppercase letters */
653 
654             if (i < 3)
655             {
656                 if (!isupper ((int) InString[i]))
657                 {
658                     Status = AE_BAD_PARAMETER;
659                 }
660             }
661 
662             /* Last 4 characters must be hex digits */
663 
664             else if (!isxdigit ((int) InString[i]))
665             {
666                 Status = AE_BAD_PARAMETER;
667             }
668         }
669     }
670 
671     if (ACPI_FAILURE (Status))
672     {
673         AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
674     }
675     else
676     {
677         /* Create ID big-endian first (bits are contiguous) */
678 
679         BigEndianId =
680             (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
681             (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
682             (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
683 
684             (AcpiUtAsciiCharToHex (InString[3])) << 12 |
685             (AcpiUtAsciiCharToHex (InString[4])) << 8  |
686             (AcpiUtAsciiCharToHex (InString[5])) << 4  |
687              AcpiUtAsciiCharToHex (InString[6]);
688 
689         /* Swap to little-endian to get final ID (see function header) */
690 
691         EisaId = AcpiUtDwordByteSwap (BigEndianId);
692     }
693 
694     /*
695      * Morph the Op into an integer, regardless of whether there
696      * was an error in the EISAID string
697      */
698     Op->Asl.Value.Integer = EisaId;
699 
700     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
701     Op->Asl.ParseOpcode = PARSEOP_INTEGER;
702     (void) OpcSetOptimalIntegerSize (Op);
703 
704     /* Op is now an integer */
705 
706     UtSetParseOpName (Op);
707 }
708 
709 
710 /*******************************************************************************
711  *
712  * FUNCTION:    OpcEncodePldBuffer
713  *
714  * PARAMETERS:  PldInfo             - _PLD buffer struct (Using local struct)
715  *
716  * RETURN:      Encode _PLD buffer suitable for return value from _PLD
717  *
718  * DESCRIPTION: Bit-packs a _PLD buffer struct.
719  *
720  ******************************************************************************/
721 
722 static UINT8 *
723 OpcEncodePldBuffer (
724     ACPI_PLD_INFO           *PldInfo)
725 {
726     UINT32                  *Buffer;
727     UINT32                  Dword;
728 
729 
730     Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE);
731     if (!Buffer)
732     {
733         return (NULL);
734     }
735 
736     /* First 32 bits */
737 
738     Dword = 0;
739     ACPI_PLD_SET_REVISION       (&Dword, PldInfo->Revision);
740     ACPI_PLD_SET_IGNORE_COLOR   (&Dword, PldInfo->IgnoreColor);
741     ACPI_PLD_SET_RED            (&Dword, PldInfo->Red);
742     ACPI_PLD_SET_GREEN          (&Dword, PldInfo->Green);
743     ACPI_PLD_SET_BLUE           (&Dword, PldInfo->Blue);
744     ACPI_MOVE_32_TO_32          (&Buffer[0], &Dword);
745 
746     /* Second 32 bits */
747 
748     Dword = 0;
749     ACPI_PLD_SET_WIDTH          (&Dword, PldInfo->Width);
750     ACPI_PLD_SET_HEIGHT         (&Dword, PldInfo->Height);
751     ACPI_MOVE_32_TO_32          (&Buffer[1], &Dword);
752 
753     /* Third 32 bits */
754 
755     Dword = 0;
756     ACPI_PLD_SET_USER_VISIBLE   (&Dword, PldInfo->UserVisible);
757     ACPI_PLD_SET_DOCK           (&Dword, PldInfo->Dock);
758     ACPI_PLD_SET_LID            (&Dword, PldInfo->Lid);
759     ACPI_PLD_SET_PANEL          (&Dword, PldInfo->Panel);
760     ACPI_PLD_SET_VERTICAL       (&Dword, PldInfo->VerticalPosition);
761     ACPI_PLD_SET_HORIZONTAL     (&Dword, PldInfo->HorizontalPosition);
762     ACPI_PLD_SET_SHAPE          (&Dword, PldInfo->Shape);
763     ACPI_PLD_SET_ORIENTATION    (&Dword, PldInfo->GroupOrientation);
764     ACPI_PLD_SET_TOKEN          (&Dword, PldInfo->GroupToken);
765     ACPI_PLD_SET_POSITION       (&Dword, PldInfo->GroupPosition);
766     ACPI_PLD_SET_BAY            (&Dword, PldInfo->Bay);
767     ACPI_MOVE_32_TO_32          (&Buffer[2], &Dword);
768 
769     /* Fourth 32 bits */
770 
771     Dword = 0;
772     ACPI_PLD_SET_EJECTABLE      (&Dword, PldInfo->Ejectable);
773     ACPI_PLD_SET_OSPM_EJECT     (&Dword, PldInfo->OspmEjectRequired);
774     ACPI_PLD_SET_CABINET        (&Dword, PldInfo->CabinetNumber);
775     ACPI_PLD_SET_CARD_CAGE      (&Dword, PldInfo->CardCageNumber);
776     ACPI_PLD_SET_REFERENCE      (&Dword, PldInfo->Reference);
777     ACPI_PLD_SET_ROTATION       (&Dword, PldInfo->Rotation);
778     ACPI_PLD_SET_ORDER          (&Dword, PldInfo->Order);
779     ACPI_MOVE_32_TO_32          (&Buffer[3], &Dword);
780 
781     if (PldInfo->Revision >= 2)
782     {
783         /* Fifth 32 bits */
784 
785         Dword = 0;
786         ACPI_PLD_SET_VERT_OFFSET    (&Dword, PldInfo->VerticalOffset);
787         ACPI_PLD_SET_HORIZ_OFFSET   (&Dword, PldInfo->HorizontalOffset);
788         ACPI_MOVE_32_TO_32          (&Buffer[4], &Dword);
789     }
790 
791     return (ACPI_CAST_PTR (UINT8, Buffer));
792 }
793 
794 
795 /*******************************************************************************
796  *
797  * FUNCTION:    OpcFindName
798  *
799  * PARAMETERS:  List                - Array of char strings to be searched
800  *              Name                - Char string to string for
801  *              Index               - Index value to set if found
802  *
803  * RETURN:      TRUE if any names matched, FALSE otherwise
804  *
805  * DESCRIPTION: Match PLD name to value in lookup table. Sets Value to
806  *              equivalent parameter value.
807  *
808  ******************************************************************************/
809 
810 static BOOLEAN
811 OpcFindName (
812     char                    **List,
813     char                    *Name,
814     UINT64                  *Index)
815 {
816     char                     *Str;
817     UINT32                   i;
818 
819 
820     AcpiUtStrupr (Name);
821 
822     for (i = 0, Str = List[0]; Str; i++, Str = List[i])
823     {
824         if (!(strncmp (Str, Name, strlen (Name))))
825         {
826             *Index = i;
827             return (TRUE);
828         }
829     }
830 
831     return (FALSE);
832 }
833 
834 
835 /*******************************************************************************
836  *
837  * FUNCTION:    OpcDoPld
838  *
839  * PARAMETERS:  Op                  - Parse node
840  *
841  * RETURN:      None
842  *
843  * DESCRIPTION: Convert ToPLD macro to 20-byte buffer
844  *
845  ******************************************************************************/
846 
847 static void
848 OpcDoPld (
849     ACPI_PARSE_OBJECT       *Op)
850 {
851     UINT8                   *Buffer;
852     ACPI_PARSE_OBJECT       *Node;
853     ACPI_PLD_INFO           PldInfo;
854     ACPI_PARSE_OBJECT       *NewOp;
855 
856 
857     if (!Op)
858     {
859         AslError(ASL_ERROR, ASL_MSG_NOT_EXIST, Op, NULL);
860         return;
861     }
862 
863     if (Op->Asl.ParseOpcode != PARSEOP_TOPLD)
864     {
865         AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Op, NULL);
866         return;
867     }
868 
869     memset (&PldInfo, 0, sizeof (ACPI_PLD_INFO));
870 
871     Node = Op->Asl.Child;
872     while (Node)
873     {
874         switch (Node->Asl.ParseOpcode)
875         {
876         case PARSEOP_PLD_REVISION:
877 
878             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
879             {
880                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
881                 break;
882             }
883 
884             if (Node->Asl.Child->Asl.Value.Integer > 127)
885             {
886                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
887                 break;
888             }
889 
890             PldInfo.Revision = (UINT8) Node->Asl.Child->Asl.Value.Integer;
891             break;
892 
893         case PARSEOP_PLD_IGNORECOLOR:
894 
895             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
896             {
897                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
898                 break;
899             }
900 
901             if (Node->Asl.Child->Asl.Value.Integer > 1)
902             {
903                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
904                 break;
905             }
906 
907             PldInfo.IgnoreColor = (UINT8) Node->Asl.Child->Asl.Value.Integer;
908             break;
909 
910         case PARSEOP_PLD_RED:
911         case PARSEOP_PLD_GREEN:
912         case PARSEOP_PLD_BLUE:
913 
914             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
915             {
916                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
917                 break;
918             }
919 
920             if (Node->Asl.Child->Asl.Value.Integer > 255)
921             {
922                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
923                 break;
924             }
925 
926             if (Node->Asl.ParseOpcode == PARSEOP_PLD_RED)
927             {
928                 PldInfo.Red = (UINT8) Node->Asl.Child->Asl.Value.Integer;
929             }
930             else if (Node->Asl.ParseOpcode == PARSEOP_PLD_GREEN)
931             {
932                 PldInfo.Green = (UINT8) Node->Asl.Child->Asl.Value.Integer;
933             }
934             else /* PARSEOP_PLD_BLUE */
935             {
936                 PldInfo.Blue = (UINT8) Node->Asl.Child->Asl.Value.Integer;
937             }
938             break;
939 
940         case PARSEOP_PLD_WIDTH:
941         case PARSEOP_PLD_HEIGHT:
942 
943             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
944             {
945                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
946                 break;
947             }
948 
949             if (Node->Asl.Child->Asl.Value.Integer > 65535)
950             {
951                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
952                 break;
953             }
954 
955             if (Node->Asl.ParseOpcode == PARSEOP_PLD_WIDTH)
956             {
957                 PldInfo.Width = (UINT16) Node->Asl.Child->Asl.Value.Integer;
958             }
959             else /* PARSEOP_PLD_HEIGHT */
960             {
961                 PldInfo.Height = (UINT16) Node->Asl.Child->Asl.Value.Integer;
962             }
963 
964             break;
965 
966         case PARSEOP_PLD_USERVISIBLE:
967         case PARSEOP_PLD_DOCK:
968         case PARSEOP_PLD_LID:
969 
970             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
971             {
972                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
973                 break;
974             }
975 
976             if (Node->Asl.Child->Asl.Value.Integer > 1)
977             {
978                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
979                 break;
980             }
981 
982             if (Node->Asl.ParseOpcode == PARSEOP_PLD_USERVISIBLE)
983             {
984                 PldInfo.UserVisible = (UINT8) Node->Asl.Child->Asl.Value.Integer;
985             }
986             else if (Node->Asl.ParseOpcode == PARSEOP_PLD_DOCK)
987             {
988                 PldInfo.Dock = (UINT8) Node->Asl.Child->Asl.Value.Integer;
989             }
990             else
991             {
992                 PldInfo.Lid = (UINT8) Node->Asl.Child->Asl.Value.Integer;
993             }
994 
995             break;
996 
997         case PARSEOP_PLD_PANEL:
998 
999             if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1000             {
1001                 if (Node->Asl.Child->Asl.Value.Integer > 6)
1002                 {
1003                     AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1004                     break;
1005                 }
1006             }
1007             else /* PARSEOP_STRING */
1008             {
1009                 if (!OpcFindName(AslPldPanelList,
1010                     Node->Asl.Child->Asl.Value.String,
1011                     &Node->Asl.Child->Asl.Value.Integer))
1012                 {
1013                     AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1014                     break;
1015                 }
1016             }
1017 
1018             PldInfo.Panel = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1019             break;
1020 
1021         case PARSEOP_PLD_VERTICALPOSITION:
1022 
1023             if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1024             {
1025                 if (Node->Asl.Child->Asl.Value.Integer > 2)
1026                 {
1027                     AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1028                     break;
1029                 }
1030             }
1031             else /* PARSEOP_STRING */
1032             {
1033                 if (!OpcFindName(AslPldVerticalPositionList,
1034                     Node->Asl.Child->Asl.Value.String,
1035                     &Node->Asl.Child->Asl.Value.Integer))
1036                 {
1037                     AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1038                     break;
1039                 }
1040             }
1041 
1042             PldInfo.VerticalPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1043             break;
1044 
1045         case PARSEOP_PLD_HORIZONTALPOSITION:
1046 
1047             if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1048             {
1049                 if (Node->Asl.Child->Asl.Value.Integer > 2)
1050                 {
1051                     AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1052                     break;
1053                 }
1054             }
1055             else /* PARSEOP_STRING */
1056             {
1057                 if (!OpcFindName(AslPldHorizontalPositionList,
1058                     Node->Asl.Child->Asl.Value.String,
1059                     &Node->Asl.Child->Asl.Value.Integer))
1060                 {
1061                     AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1062                     break;
1063                 }
1064             }
1065 
1066             PldInfo.HorizontalPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1067             break;
1068 
1069         case PARSEOP_PLD_SHAPE:
1070 
1071             if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
1072             {
1073                 if (Node->Asl.Child->Asl.Value.Integer > 8)
1074                 {
1075                     AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1076                     break;
1077                 }
1078             }
1079             else /* PARSEOP_STRING */
1080             {
1081                 if (!OpcFindName(AslPldShapeList,
1082                     Node->Asl.Child->Asl.Value.String,
1083                     &Node->Asl.Child->Asl.Value.Integer))
1084                 {
1085                     AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
1086                     break;
1087                 }
1088             }
1089 
1090             PldInfo.Shape = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1091             break;
1092 
1093         case PARSEOP_PLD_GROUPORIENTATION:
1094 
1095             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1096             {
1097                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1098                 break;
1099             }
1100 
1101             if (Node->Asl.Child->Asl.Value.Integer > 1)
1102             {
1103                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1104                 break;
1105             }
1106 
1107             PldInfo.GroupOrientation = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1108             break;
1109 
1110         case PARSEOP_PLD_GROUPTOKEN:
1111         case PARSEOP_PLD_GROUPPOSITION:
1112 
1113             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1114             {
1115                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1116                 break;
1117             }
1118 
1119             if (Node->Asl.Child->Asl.Value.Integer > 255)
1120             {
1121                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1122                 break;
1123             }
1124 
1125 
1126             if (Node->Asl.ParseOpcode == PARSEOP_PLD_GROUPTOKEN)
1127             {
1128                 PldInfo.GroupToken = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1129             }
1130             else /* PARSEOP_PLD_GROUPPOSITION */
1131             {
1132                 PldInfo.GroupPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1133             }
1134 
1135             break;
1136 
1137         case PARSEOP_PLD_BAY:
1138         case PARSEOP_PLD_EJECTABLE:
1139         case PARSEOP_PLD_EJECTREQUIRED:
1140 
1141             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1142             {
1143                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1144                 break;
1145             }
1146 
1147             if (Node->Asl.Child->Asl.Value.Integer > 1)
1148             {
1149                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1150                 break;
1151             }
1152 
1153             if (Node->Asl.ParseOpcode == PARSEOP_PLD_BAY)
1154             {
1155                 PldInfo.Bay = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1156             }
1157             else if (Node->Asl.ParseOpcode == PARSEOP_PLD_EJECTABLE)
1158             {
1159                 PldInfo.Ejectable = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1160             }
1161             else /* PARSEOP_PLD_EJECTREQUIRED */
1162             {
1163                 PldInfo.OspmEjectRequired = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1164             }
1165 
1166             break;
1167 
1168         case PARSEOP_PLD_CABINETNUMBER:
1169         case PARSEOP_PLD_CARDCAGENUMBER:
1170 
1171             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1172             {
1173                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1174                 break;
1175             }
1176 
1177             if (Node->Asl.Child->Asl.Value.Integer > 255)
1178             {
1179                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1180                 break;
1181             }
1182 
1183             if (Node->Asl.ParseOpcode == PARSEOP_PLD_CABINETNUMBER)
1184             {
1185                 PldInfo.CabinetNumber = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1186             }
1187             else /* PARSEOP_PLD_CARDCAGENUMBER */
1188             {
1189                 PldInfo.CardCageNumber = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1190             }
1191 
1192             break;
1193 
1194         case PARSEOP_PLD_REFERENCE:
1195 
1196             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1197             {
1198                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1199                 break;
1200             }
1201 
1202             if (Node->Asl.Child->Asl.Value.Integer > 1)
1203             {
1204                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1205                 break;
1206             }
1207 
1208             PldInfo.Reference = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1209             break;
1210 
1211         case PARSEOP_PLD_ROTATION:
1212 
1213             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1214             {
1215                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1216                 break;
1217             }
1218 
1219             if (Node->Asl.Child->Asl.Value.Integer > 7)
1220             {
1221                 switch (Node->Asl.Child->Asl.Value.Integer)
1222                 {
1223                 case 45:
1224 
1225                     Node->Asl.Child->Asl.Value.Integer = 1;
1226                     break;
1227 
1228                 case 90:
1229 
1230                     Node->Asl.Child->Asl.Value.Integer = 2;
1231                     break;
1232 
1233                 case 135:
1234 
1235                     Node->Asl.Child->Asl.Value.Integer = 3;
1236                     break;
1237 
1238                 case 180:
1239 
1240                     Node->Asl.Child->Asl.Value.Integer = 4;
1241                     break;
1242 
1243                 case 225:
1244 
1245                     Node->Asl.Child->Asl.Value.Integer = 5;
1246                     break;
1247 
1248                 case 270:
1249 
1250                     Node->Asl.Child->Asl.Value.Integer = 6;
1251                     break;
1252 
1253                 case 315:
1254 
1255                     Node->Asl.Child->Asl.Value.Integer = 7;
1256                     break;
1257 
1258                 default:
1259 
1260                     AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1261                     break;
1262                 }
1263             }
1264 
1265             PldInfo.Rotation = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1266             break;
1267 
1268         case PARSEOP_PLD_ORDER:
1269 
1270             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1271             {
1272                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1273                 break;
1274             }
1275 
1276             if (Node->Asl.Child->Asl.Value.Integer > 31)
1277             {
1278                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1279                 break;
1280             }
1281 
1282             PldInfo.Order = (UINT8) Node->Asl.Child->Asl.Value.Integer;
1283             break;
1284 
1285         case PARSEOP_PLD_VERTICALOFFSET:
1286         case PARSEOP_PLD_HORIZONTALOFFSET:
1287 
1288             if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
1289             {
1290                 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1291                 break;
1292             }
1293 
1294             if (Node->Asl.Child->Asl.Value.Integer > 65535)
1295             {
1296                 AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
1297                 break;
1298             }
1299 
1300             if (Node->Asl.ParseOpcode == PARSEOP_PLD_VERTICALOFFSET)
1301             {
1302                 PldInfo.VerticalOffset = (UINT16) Node->Asl.Child->Asl.Value.Integer;
1303             }
1304             else /* PARSEOP_PLD_HORIZONTALOFFSET */
1305             {
1306                 PldInfo.HorizontalOffset = (UINT16) Node->Asl.Child->Asl.Value.Integer;
1307             }
1308 
1309             break;
1310 
1311         default:
1312 
1313             AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
1314             break;
1315         }
1316 
1317         Node = Node->Asl.Next;
1318     }
1319 
1320     Buffer = OpcEncodePldBuffer(&PldInfo);
1321 
1322     /* Change Op to a Buffer */
1323 
1324     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
1325     Op->Common.AmlOpcode = AML_BUFFER_OP;
1326 
1327     /* Disable further optimization */
1328 
1329     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
1330     UtSetParseOpName (Op);
1331 
1332     /* Child node is the buffer length */
1333 
1334     NewOp = TrAllocateNode (PARSEOP_INTEGER);
1335 
1336     NewOp->Asl.AmlOpcode = AML_BYTE_OP;
1337     NewOp->Asl.Value.Integer = 20;
1338     NewOp->Asl.Parent = Op;
1339 
1340     Op->Asl.Child = NewOp;
1341     Op = NewOp;
1342 
1343     /* Peer to the child is the raw buffer data */
1344 
1345     NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
1346     NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
1347     NewOp->Asl.AmlLength = 20;
1348     NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
1349     NewOp->Asl.Parent = Op->Asl.Parent;
1350 
1351     Op->Asl.Next = NewOp;
1352 }
1353 
1354 
1355 /*******************************************************************************
1356  *
1357  * FUNCTION:    OpcDoUuId
1358  *
1359  * PARAMETERS:  Op                  - Parse node
1360  *
1361  * RETURN:      None
1362  *
1363  * DESCRIPTION: Convert UUID string to 16-byte buffer
1364  *
1365  ******************************************************************************/
1366 
1367 static void
1368 OpcDoUuId (
1369     ACPI_PARSE_OBJECT       *Op)
1370 {
1371     char                    *InString;
1372     UINT8                   *Buffer;
1373     ACPI_STATUS             Status = AE_OK;
1374     ACPI_PARSE_OBJECT       *NewOp;
1375 
1376 
1377     InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
1378     Buffer = UtLocalCalloc (16);
1379 
1380     Status = AuValidateUuid (InString);
1381     if (ACPI_FAILURE (Status))
1382     {
1383         AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
1384     }
1385     else
1386     {
1387         AcpiUtConvertStringToUuid (InString, Buffer);
1388     }
1389 
1390     /* Change Op to a Buffer */
1391 
1392     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
1393     Op->Common.AmlOpcode = AML_BUFFER_OP;
1394 
1395     /* Disable further optimization */
1396 
1397     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
1398     UtSetParseOpName (Op);
1399 
1400     /* Child node is the buffer length */
1401 
1402     NewOp = TrAllocateNode (PARSEOP_INTEGER);
1403 
1404     NewOp->Asl.AmlOpcode = AML_BYTE_OP;
1405     NewOp->Asl.Value.Integer = 16;
1406     NewOp->Asl.Parent = Op;
1407 
1408     Op->Asl.Child = NewOp;
1409     Op = NewOp;
1410 
1411     /* Peer to the child is the raw buffer data */
1412 
1413     NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
1414     NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
1415     NewOp->Asl.AmlLength = 16;
1416     NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
1417     NewOp->Asl.Parent = Op->Asl.Parent;
1418 
1419     Op->Asl.Next = NewOp;
1420 }
1421 
1422 
1423 /*******************************************************************************
1424  *
1425  * FUNCTION:    OpcGenerateAmlOpcode
1426  *
1427  * PARAMETERS:  Op                  - Parse node
1428  *
1429  * RETURN:      None
1430  *
1431  * DESCRIPTION: Generate the AML opcode associated with the node and its
1432  *              parse (lex/flex) keyword opcode. Essentially implements
1433  *              a mapping between the parse opcodes and the actual AML opcodes.
1434  *
1435  ******************************************************************************/
1436 
1437 void
1438 OpcGenerateAmlOpcode (
1439     ACPI_PARSE_OBJECT       *Op)
1440 {
1441     UINT16                  Index;
1442 
1443 
1444     Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
1445 
1446     Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
1447     Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
1448     Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
1449 
1450     if (!Op->Asl.Value.Integer)
1451     {
1452         Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
1453     }
1454 
1455     /* Special handling for some opcodes */
1456 
1457     switch (Op->Asl.ParseOpcode)
1458     {
1459     case PARSEOP_INTEGER:
1460         /*
1461          * Set the opcode based on the size of the integer
1462          */
1463         (void) OpcSetOptimalIntegerSize (Op);
1464         break;
1465 
1466     case PARSEOP_OFFSET:
1467 
1468         Op->Asl.AmlOpcodeLength = 1;
1469         break;
1470 
1471     case PARSEOP_ACCESSAS:
1472 
1473         OpcDoAccessAs (Op);
1474         break;
1475 
1476     case PARSEOP_CONNECTION:
1477 
1478         OpcDoConnection (Op);
1479         break;
1480 
1481     case PARSEOP_EISAID:
1482 
1483         OpcDoEisaId (Op);
1484         break;
1485 
1486     case PARSEOP_PRINTF:
1487 
1488         OpcDoPrintf (Op);
1489         break;
1490 
1491     case PARSEOP_FPRINTF:
1492 
1493         OpcDoFprintf (Op);
1494         break;
1495 
1496     case PARSEOP_TOPLD:
1497 
1498         OpcDoPld (Op);
1499         break;
1500 
1501     case PARSEOP_TOUUID:
1502 
1503         OpcDoUuId (Op);
1504         break;
1505 
1506     case PARSEOP_UNICODE:
1507 
1508         OpcDoUnicode (Op);
1509         break;
1510 
1511     case PARSEOP_INCLUDE:
1512 
1513         Gbl_HasIncludeFiles = TRUE;
1514         break;
1515 
1516     case PARSEOP_EXTERNAL:
1517 
1518         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1519         Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1520         break;
1521 
1522     case PARSEOP_TIMER:
1523 
1524         if (AcpiGbl_IntegerBitWidth == 32)
1525         {
1526             AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
1527         }
1528         break;
1529 
1530     default:
1531 
1532         /* Nothing to do for other opcodes */
1533 
1534         break;
1535     }
1536 
1537     return;
1538 }
1539