xref: /freebsd/sys/contrib/dev/acpica/compiler/aslopcodes.c (revision 273c26a3c3bea87a241d6879abd4f991db180bf0)
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 <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 OpcDoUuId (
72     ACPI_PARSE_OBJECT       *Op);
73 
74 
75 /*******************************************************************************
76  *
77  * FUNCTION:    OpcAmlOpcodeUpdateWalk
78  *
79  * PARAMETERS:  ASL_WALK_CALLBACK
80  *
81  * RETURN:      Status
82  *
83  * DESCRIPTION: Opcode update walk, ascending callback
84  *
85  ******************************************************************************/
86 
87 ACPI_STATUS
88 OpcAmlOpcodeUpdateWalk (
89     ACPI_PARSE_OBJECT       *Op,
90     UINT32                  Level,
91     void                    *Context)
92 {
93 
94     /*
95      * Handle the Package() case where the actual opcode cannot be determined
96      * until the PackageLength operand has been folded and minimized.
97      * (PackageOp versus VarPackageOp)
98      *
99      * This is (as of ACPI 3.0) the only case where the AML opcode can change
100      * based upon the value of a parameter.
101      *
102      * The parser always inserts a VarPackage opcode, which can possibly be
103      * optimized to a Package opcode.
104      */
105     if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
106     {
107         OpnDoPackage (Op);
108     }
109 
110     return (AE_OK);
111 }
112 
113 
114 /*******************************************************************************
115  *
116  * FUNCTION:    OpcAmlOpcodeWalk
117  *
118  * PARAMETERS:  ASL_WALK_CALLBACK
119  *
120  * RETURN:      Status
121  *
122  * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
123  *              operands.
124  *
125  ******************************************************************************/
126 
127 ACPI_STATUS
128 OpcAmlOpcodeWalk (
129     ACPI_PARSE_OBJECT       *Op,
130     UINT32                  Level,
131     void                    *Context)
132 {
133 
134     TotalParseNodes++;
135 
136     OpcGenerateAmlOpcode (Op);
137     OpnGenerateAmlOperands (Op);
138     return (AE_OK);
139 }
140 
141 
142 /*******************************************************************************
143  *
144  * FUNCTION:    OpcGetIntegerWidth
145  *
146  * PARAMETERS:  Op          - DEFINITION BLOCK op
147  *
148  * RETURN:      none
149  *
150  * DESCRIPTION: Extract integer width from the table revision
151  *
152  ******************************************************************************/
153 
154 void
155 OpcGetIntegerWidth (
156     ACPI_PARSE_OBJECT       *Op)
157 {
158     ACPI_PARSE_OBJECT       *Child;
159 
160 
161     if (!Op)
162     {
163         return;
164     }
165 
166     if (Gbl_RevisionOverride)
167     {
168         AcpiUtSetIntegerWidth (Gbl_RevisionOverride);
169     }
170     else
171     {
172         Child = Op->Asl.Child;
173         Child = Child->Asl.Next;
174         Child = Child->Asl.Next;
175 
176         /* Use the revision to set the integer width */
177 
178         AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
179     }
180 }
181 
182 
183 /*******************************************************************************
184  *
185  * FUNCTION:    OpcSetOptimalIntegerSize
186  *
187  * PARAMETERS:  Op        - A parse tree node
188  *
189  * RETURN:      Integer width, in bytes. Also sets the node AML opcode to the
190  *              optimal integer AML prefix opcode.
191  *
192  * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading
193  *              zeros can be truncated to squeeze the integer into the
194  *              minimal number of AML bytes.
195  *
196  ******************************************************************************/
197 
198 UINT32
199 OpcSetOptimalIntegerSize (
200     ACPI_PARSE_OBJECT       *Op)
201 {
202 
203 #if 0
204     /*
205      * TBD: - we don't want to optimize integers in the block header, but the
206      * code below does not work correctly.
207      */
208     if (Op->Asl.Parent &&
209         Op->Asl.Parent->Asl.Parent &&
210        (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK))
211     {
212         return (0);
213     }
214 #endif
215 
216     /*
217      * Check for the special AML integers first - Zero, One, Ones.
218      * These are single-byte opcodes that are the smallest possible
219      * representation of an integer.
220      *
221      * This optimization is optional.
222      */
223     if (Gbl_IntegerOptimizationFlag)
224     {
225         switch (Op->Asl.Value.Integer)
226         {
227         case 0:
228 
229             Op->Asl.AmlOpcode = AML_ZERO_OP;
230             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
231                 Op, "Zero");
232             return (1);
233 
234         case 1:
235 
236             Op->Asl.AmlOpcode = AML_ONE_OP;
237             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
238                 Op, "One");
239             return (1);
240 
241         case ACPI_UINT32_MAX:
242 
243             /* Check for table integer width (32 or 64) */
244 
245             if (AcpiGbl_IntegerByteWidth == 4)
246             {
247                 Op->Asl.AmlOpcode = AML_ONES_OP;
248                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
249                     Op, "Ones");
250                 return (1);
251             }
252             break;
253 
254         case ACPI_UINT64_MAX:
255 
256             /* Check for table integer width (32 or 64) */
257 
258             if (AcpiGbl_IntegerByteWidth == 8)
259             {
260                 Op->Asl.AmlOpcode = AML_ONES_OP;
261                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
262                     Op, "Ones");
263                 return (1);
264             }
265             break;
266 
267         default:
268 
269             break;
270         }
271     }
272 
273     /* Find the best fit using the various AML integer prefixes */
274 
275     if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
276     {
277         Op->Asl.AmlOpcode = AML_BYTE_OP;
278         return (1);
279     }
280 
281     if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
282     {
283         Op->Asl.AmlOpcode = AML_WORD_OP;
284         return (2);
285     }
286 
287     if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
288     {
289         Op->Asl.AmlOpcode = AML_DWORD_OP;
290         return (4);
291     }
292     else
293     {
294         if (AcpiGbl_IntegerByteWidth == 4)
295         {
296             AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
297                 Op, NULL);
298 
299             if (!Gbl_IgnoreErrors)
300             {
301                 /* Truncate the integer to 32-bit */
302                 Op->Asl.AmlOpcode = AML_DWORD_OP;
303                 return (4);
304             }
305         }
306 
307         Op->Asl.AmlOpcode = AML_QWORD_OP;
308         return (8);
309     }
310 }
311 
312 
313 /*******************************************************************************
314  *
315  * FUNCTION:    OpcDoAccessAs
316  *
317  * PARAMETERS:  Op        - Parse node
318  *
319  * RETURN:      None
320  *
321  * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
322  *
323  ******************************************************************************/
324 
325 static void
326 OpcDoAccessAs (
327     ACPI_PARSE_OBJECT       *Op)
328 {
329     ACPI_PARSE_OBJECT       *TypeOp;
330     ACPI_PARSE_OBJECT       *AttribOp;
331     ACPI_PARSE_OBJECT       *LengthOp;
332     UINT8                   Attribute;
333 
334 
335     Op->Asl.AmlOpcodeLength = 1;
336     TypeOp = Op->Asl.Child;
337 
338     /* First child is the access type */
339 
340     TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
341     TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
342 
343     /* Second child is the optional access attribute */
344 
345     AttribOp = TypeOp->Asl.Next;
346     if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
347     {
348         AttribOp->Asl.Value.Integer = 0;
349     }
350 
351     AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
352     AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
353 
354     /* Only a few AccessAttributes support AccessLength */
355 
356     Attribute = (UINT8) AttribOp->Asl.Value.Integer;
357     if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
358         (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
359         (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
360     {
361         return;
362     }
363 
364     Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
365 
366     /*
367      * Child of Attributes is the AccessLength (required for Multibyte,
368      * RawBytes, RawProcess.)
369      */
370     LengthOp = AttribOp->Asl.Child;
371     if (!LengthOp)
372     {
373         return;
374     }
375 
376     /* TBD: probably can remove */
377 
378     if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
379     {
380         LengthOp->Asl.Value.Integer = 16;
381     }
382 
383     LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
384     LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
385 }
386 
387 
388 /*******************************************************************************
389  *
390  * FUNCTION:    OpcDoConnection
391  *
392  * PARAMETERS:  Op        - Parse node
393  *
394  * RETURN:      None
395  *
396  * DESCRIPTION: Implement the Connection ASL keyword.
397  *
398  ******************************************************************************/
399 
400 static void
401 OpcDoConnection (
402     ACPI_PARSE_OBJECT       *Op)
403 {
404     ASL_RESOURCE_NODE       *Rnode;
405     ACPI_PARSE_OBJECT       *BufferOp;
406     ACPI_PARSE_OBJECT       *BufferLengthOp;
407     ACPI_PARSE_OBJECT       *BufferDataOp;
408     ASL_RESOURCE_INFO       Info;
409     UINT8                   State;
410 
411 
412     Op->Asl.AmlOpcodeLength = 1;
413 
414     if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
415     {
416         return;
417     }
418 
419     BufferOp = Op->Asl.Child;
420     BufferLengthOp = BufferOp->Asl.Child;
421     BufferDataOp = BufferLengthOp->Asl.Next;
422 
423     Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
424     Info.CurrentByteOffset = 0;
425     State = ACPI_RSTATE_NORMAL;
426     Rnode = RsDoOneResourceDescriptor (&Info, &State);
427     if (!Rnode)
428     {
429         return; /* error */
430     }
431 
432     /*
433      * Transform the nodes into the following
434      *
435      * Op           -> AML_BUFFER_OP
436      * First Child  -> BufferLength
437      * Second Child -> Descriptor Buffer (raw byte data)
438      */
439     BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
440     BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
441     BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
442     UtSetParseOpName (BufferOp);
443 
444     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
445     BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
446     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
447     UtSetParseOpName (BufferLengthOp);
448 
449     BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
450     BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
451     BufferDataOp->Asl.AmlOpcodeLength = 0;
452     BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
453     BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
454     UtSetParseOpName (BufferDataOp);
455 }
456 
457 
458 /*******************************************************************************
459  *
460  * FUNCTION:    OpcDoUnicode
461  *
462  * PARAMETERS:  Op        - Parse node
463  *
464  * RETURN:      None
465  *
466  * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
467  *              to a unicode buffer. There is no Unicode AML opcode.
468  *
469  * Note:  The Unicode string is 16 bits per character, no leading signature,
470  *        with a 16-bit terminating NULL.
471  *
472  ******************************************************************************/
473 
474 static void
475 OpcDoUnicode (
476     ACPI_PARSE_OBJECT       *Op)
477 {
478     ACPI_PARSE_OBJECT       *InitializerOp;
479     UINT32                  Length;
480     UINT32                  Count;
481     UINT32                  i;
482     UINT8                   *AsciiString;
483     UINT16                  *UnicodeString;
484     ACPI_PARSE_OBJECT       *BufferLengthOp;
485 
486 
487     /* Change op into a buffer object */
488 
489     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
490     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
491     UtSetParseOpName (Op);
492 
493     /* Buffer Length is first, followed by the string */
494 
495     BufferLengthOp = Op->Asl.Child;
496     InitializerOp = BufferLengthOp->Asl.Next;
497 
498     AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
499 
500     /* Create a new buffer for the Unicode string */
501 
502     Count = strlen (InitializerOp->Asl.Value.String) + 1;
503     Length = Count * sizeof (UINT16);
504     UnicodeString = UtLocalCalloc (Length);
505 
506     /* Convert to Unicode string (including null terminator) */
507 
508     for (i = 0; i < Count; i++)
509     {
510         UnicodeString[i] = (UINT16) AsciiString[i];
511     }
512 
513     /*
514      * Just set the buffer size node to be the buffer length, regardless
515      * of whether it was previously an integer or a default_arg placeholder
516      */
517     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
518     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
519     BufferLengthOp->Asl.Value.Integer = Length;
520     UtSetParseOpName (BufferLengthOp);
521 
522     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
523 
524     /* The Unicode string is a raw data buffer */
525 
526     InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
527     InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
528     InitializerOp->Asl.AmlLength = Length;
529     InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
530     InitializerOp->Asl.Child = NULL;
531     UtSetParseOpName (InitializerOp);
532 }
533 
534 
535 /*******************************************************************************
536  *
537  * FUNCTION:    OpcDoEisaId
538  *
539  * PARAMETERS:  Op        - Parse node
540  *
541  * RETURN:      None
542  *
543  * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
544  *              Pnp BIOS Specification for details. Here is an excerpt:
545  *
546  *              A seven character ASCII representation of the product
547  *              identifier compressed into a 32-bit identifier. The seven
548  *              character ID consists of a three character manufacturer code,
549  *              a three character hexadecimal product identifier, and a one
550  *              character hexadecimal revision number. The manufacturer code
551  *              is a 3 uppercase character code that is compressed into 3 5-bit
552  *              values as follows:
553  *                  1) Find hex ASCII value for each letter
554  *                  2) Subtract 40h from each ASCII value
555  *                  3) Retain 5 least significant bits for each letter by
556  *                     discarding upper 3 bits because they are always 0.
557  *                  4) Compressed code = concatenate 0 and the 3 5-bit values
558  *
559  *              The format of the compressed product identifier is as follows:
560  *              Byte 0: Bit 7       - Reserved (0)
561  *                      Bits 6-2:   - 1st character of compressed mfg code
562  *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
563  *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
564  *                      Bits 4-0    - 3rd character of mfg code
565  *              Byte 2: Bits 7-4    - 1st hex digit of product number
566  *                      Bits 3-0    - 2nd hex digit of product number
567  *              Byte 3: Bits 7-4    - 3st hex digit of product number
568  *                      Bits 3-0    - Hex digit of the revision number
569  *
570  ******************************************************************************/
571 
572 static void
573 OpcDoEisaId (
574     ACPI_PARSE_OBJECT       *Op)
575 {
576     UINT32                  EisaId = 0;
577     UINT32                  BigEndianId;
578     char                    *InString;
579     ACPI_STATUS             Status = AE_OK;
580     UINT32                  i;
581 
582 
583     InString = (char *) Op->Asl.Value.String;
584 
585     /*
586      * The EISAID string must be exactly 7 characters and of the form
587      * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
588      */
589     if (strlen (InString) != 7)
590     {
591         Status = AE_BAD_PARAMETER;
592     }
593     else
594     {
595         /* Check all 7 characters for correct format */
596 
597         for (i = 0; i < 7; i++)
598         {
599             /* First 3 characters must be uppercase letters */
600 
601             if (i < 3)
602             {
603                 if (!isupper ((int) InString[i]))
604                 {
605                     Status = AE_BAD_PARAMETER;
606                 }
607             }
608 
609             /* Last 4 characters must be hex digits */
610 
611             else if (!isxdigit ((int) InString[i]))
612             {
613                 Status = AE_BAD_PARAMETER;
614             }
615         }
616     }
617 
618     if (ACPI_FAILURE (Status))
619     {
620         AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
621     }
622     else
623     {
624         /* Create ID big-endian first (bits are contiguous) */
625 
626         BigEndianId =
627             (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
628             (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
629             (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
630 
631             (AcpiUtAsciiCharToHex (InString[3])) << 12 |
632             (AcpiUtAsciiCharToHex (InString[4])) << 8  |
633             (AcpiUtAsciiCharToHex (InString[5])) << 4  |
634              AcpiUtAsciiCharToHex (InString[6]);
635 
636         /* Swap to little-endian to get final ID (see function header) */
637 
638         EisaId = AcpiUtDwordByteSwap (BigEndianId);
639     }
640 
641     /*
642      * Morph the Op into an integer, regardless of whether there
643      * was an error in the EISAID string
644      */
645     Op->Asl.Value.Integer = EisaId;
646 
647     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
648     Op->Asl.ParseOpcode = PARSEOP_INTEGER;
649     (void) OpcSetOptimalIntegerSize (Op);
650 
651     /* Op is now an integer */
652 
653     UtSetParseOpName (Op);
654 }
655 
656 
657 /*******************************************************************************
658  *
659  * FUNCTION:    OpcDoUuId
660  *
661  * PARAMETERS:  Op                  - Parse node
662  *
663  * RETURN:      None
664  *
665  * DESCRIPTION: Convert UUID string to 16-byte buffer
666  *
667  ******************************************************************************/
668 
669 static void
670 OpcDoUuId (
671     ACPI_PARSE_OBJECT       *Op)
672 {
673     char                    *InString;
674     UINT8                   *Buffer;
675     ACPI_STATUS             Status = AE_OK;
676     ACPI_PARSE_OBJECT       *NewOp;
677 
678 
679     InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
680     Buffer = UtLocalCalloc (16);
681 
682     Status = AuValidateUuid (InString);
683     if (ACPI_FAILURE (Status))
684     {
685         AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
686     }
687     else
688     {
689         AcpiUtConvertStringToUuid (InString, Buffer);
690     }
691 
692     /* Change Op to a Buffer */
693 
694     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
695     Op->Common.AmlOpcode = AML_BUFFER_OP;
696 
697     /* Disable further optimization */
698 
699     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
700     UtSetParseOpName (Op);
701 
702     /* Child node is the buffer length */
703 
704     NewOp = TrAllocateNode (PARSEOP_INTEGER);
705 
706     NewOp->Asl.AmlOpcode = AML_BYTE_OP;
707     NewOp->Asl.Value.Integer = 16;
708     NewOp->Asl.Parent = Op;
709 
710     Op->Asl.Child = NewOp;
711     Op = NewOp;
712 
713     /* Peer to the child is the raw buffer data */
714 
715     NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
716     NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
717     NewOp->Asl.AmlLength = 16;
718     NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
719     NewOp->Asl.Parent = Op->Asl.Parent;
720 
721     Op->Asl.Next = NewOp;
722 }
723 
724 
725 /*******************************************************************************
726  *
727  * FUNCTION:    OpcGenerateAmlOpcode
728  *
729  * PARAMETERS:  Op                  - Parse node
730  *
731  * RETURN:      None
732  *
733  * DESCRIPTION: Generate the AML opcode associated with the node and its
734  *              parse (lex/flex) keyword opcode. Essentially implements
735  *              a mapping between the parse opcodes and the actual AML opcodes.
736  *
737  ******************************************************************************/
738 
739 void
740 OpcGenerateAmlOpcode (
741     ACPI_PARSE_OBJECT       *Op)
742 {
743     UINT16                  Index;
744 
745 
746     Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
747 
748     Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
749     Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
750     Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
751 
752     if (!Op->Asl.Value.Integer)
753     {
754         Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
755     }
756 
757     /* Special handling for some opcodes */
758 
759     switch (Op->Asl.ParseOpcode)
760     {
761     case PARSEOP_INTEGER:
762         /*
763          * Set the opcode based on the size of the integer
764          */
765         (void) OpcSetOptimalIntegerSize (Op);
766         break;
767 
768     case PARSEOP_OFFSET:
769 
770         Op->Asl.AmlOpcodeLength = 1;
771         break;
772 
773     case PARSEOP_ACCESSAS:
774 
775         OpcDoAccessAs (Op);
776         break;
777 
778     case PARSEOP_CONNECTION:
779 
780         OpcDoConnection (Op);
781         break;
782 
783     case PARSEOP_EISAID:
784 
785         OpcDoEisaId (Op);
786         break;
787 
788     case PARSEOP_PRINTF:
789 
790         OpcDoPrintf (Op);
791         break;
792 
793     case PARSEOP_FPRINTF:
794 
795         OpcDoFprintf (Op);
796         break;
797 
798     case PARSEOP_TOPLD:
799 
800         OpcDoPld (Op);
801         break;
802 
803     case PARSEOP_TOUUID:
804 
805         OpcDoUuId (Op);
806         break;
807 
808     case PARSEOP_UNICODE:
809 
810         OpcDoUnicode (Op);
811         break;
812 
813     case PARSEOP_INCLUDE:
814 
815         Gbl_HasIncludeFiles = TRUE;
816         break;
817 
818     case PARSEOP_EXTERNAL:
819 
820         if (Gbl_DoExternals == FALSE)
821         {
822             Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
823             Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
824         }
825         break;
826 
827     case PARSEOP_TIMER:
828 
829         if (AcpiGbl_IntegerBitWidth == 32)
830         {
831             AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
832         }
833         break;
834 
835     default:
836 
837         /* Nothing to do for other opcodes */
838 
839         break;
840     }
841 
842     return;
843 }
844