xref: /freebsd/sys/contrib/dev/acpica/compiler/aslopcodes.c (revision 298022457a9a016cbdda4e22d751abb5cd91c919)
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 
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_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 
376 static void
377 OpcDoAccessAs (
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 
450 static void
451 OpcDoConnection (
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 
524 static void
525 OpcDoUnicode (
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 
622 static void
623 OpcDoEisaId (
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 (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 
719 static UINT8 *
720 OpcEncodePldBuffer (
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 
806 static void
807 OpcStrupr (
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 
844 static BOOLEAN
845 OpcFindName (
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 (!(strncmp (Str, Name, 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 
881 static void
882 OpcDoPld (
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     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 
1408 static void
1409 OpcDoUuId (
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 
1478 void
1479 OpcGenerateAmlOpcode (
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