xref: /freebsd/sys/contrib/dev/acpica/compiler/aslopcodes.c (revision 076ad2f836d5f49dc1375f1677335a48fe0d4b82)
1 /******************************************************************************
2  *
3  * Module Name: aslopcode - AML opcode generation
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, 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 /* 64-bit integer */
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 
303                 Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
304 
305                 /* Now set the optimal integer size */
306 
307                 return (OpcSetOptimalIntegerSize (Op));
308             }
309         }
310 
311         Op->Asl.AmlOpcode = AML_QWORD_OP;
312         return (8);
313     }
314 }
315 
316 
317 /*******************************************************************************
318  *
319  * FUNCTION:    OpcDoAccessAs
320  *
321  * PARAMETERS:  Op        - Parse node
322  *
323  * RETURN:      None
324  *
325  * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
326  *
327  ******************************************************************************/
328 
329 static void
330 OpcDoAccessAs (
331     ACPI_PARSE_OBJECT       *Op)
332 {
333     ACPI_PARSE_OBJECT       *TypeOp;
334     ACPI_PARSE_OBJECT       *AttribOp;
335     ACPI_PARSE_OBJECT       *LengthOp;
336     UINT8                   Attribute;
337 
338 
339     Op->Asl.AmlOpcodeLength = 1;
340     TypeOp = Op->Asl.Child;
341 
342     /* First child is the access type */
343 
344     TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
345     TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
346 
347     /* Second child is the optional access attribute */
348 
349     AttribOp = TypeOp->Asl.Next;
350     if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
351     {
352         AttribOp->Asl.Value.Integer = 0;
353     }
354 
355     AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
356     AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
357 
358     /* Only a few AccessAttributes support AccessLength */
359 
360     Attribute = (UINT8) AttribOp->Asl.Value.Integer;
361     if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
362         (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
363         (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
364     {
365         return;
366     }
367 
368     Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
369 
370     /*
371      * Child of Attributes is the AccessLength (required for Multibyte,
372      * RawBytes, RawProcess.)
373      */
374     LengthOp = AttribOp->Asl.Child;
375     if (!LengthOp)
376     {
377         return;
378     }
379 
380     /* TBD: probably can remove */
381 
382     if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
383     {
384         LengthOp->Asl.Value.Integer = 16;
385     }
386 
387     LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
388     LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
389 }
390 
391 
392 /*******************************************************************************
393  *
394  * FUNCTION:    OpcDoConnection
395  *
396  * PARAMETERS:  Op        - Parse node
397  *
398  * RETURN:      None
399  *
400  * DESCRIPTION: Implement the Connection ASL keyword.
401  *
402  ******************************************************************************/
403 
404 static void
405 OpcDoConnection (
406     ACPI_PARSE_OBJECT       *Op)
407 {
408     ASL_RESOURCE_NODE       *Rnode;
409     ACPI_PARSE_OBJECT       *BufferOp;
410     ACPI_PARSE_OBJECT       *BufferLengthOp;
411     ACPI_PARSE_OBJECT       *BufferDataOp;
412     ASL_RESOURCE_INFO       Info;
413     UINT8                   State;
414 
415 
416     Op->Asl.AmlOpcodeLength = 1;
417 
418     if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
419     {
420         return;
421     }
422 
423     BufferOp = Op->Asl.Child;
424     BufferLengthOp = BufferOp->Asl.Child;
425     BufferDataOp = BufferLengthOp->Asl.Next;
426 
427     Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
428     Info.CurrentByteOffset = 0;
429     State = ACPI_RSTATE_NORMAL;
430     Rnode = RsDoOneResourceDescriptor (&Info, &State);
431     if (!Rnode)
432     {
433         return; /* error */
434     }
435 
436     /*
437      * Transform the nodes into the following
438      *
439      * Op           -> AML_BUFFER_OP
440      * First Child  -> BufferLength
441      * Second Child -> Descriptor Buffer (raw byte data)
442      */
443     BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
444     BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
445     BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
446     UtSetParseOpName (BufferOp);
447 
448     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
449     BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
450     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
451     UtSetParseOpName (BufferLengthOp);
452 
453     BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
454     BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
455     BufferDataOp->Asl.AmlOpcodeLength = 0;
456     BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
457     BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
458     UtSetParseOpName (BufferDataOp);
459 }
460 
461 
462 /*******************************************************************************
463  *
464  * FUNCTION:    OpcDoUnicode
465  *
466  * PARAMETERS:  Op        - Parse node
467  *
468  * RETURN:      None
469  *
470  * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
471  *              to a unicode buffer. There is no Unicode AML opcode.
472  *
473  * Note:  The Unicode string is 16 bits per character, no leading signature,
474  *        with a 16-bit terminating NULL.
475  *
476  ******************************************************************************/
477 
478 static void
479 OpcDoUnicode (
480     ACPI_PARSE_OBJECT       *Op)
481 {
482     ACPI_PARSE_OBJECT       *InitializerOp;
483     UINT32                  Length;
484     UINT32                  Count;
485     UINT32                  i;
486     UINT8                   *AsciiString;
487     UINT16                  *UnicodeString;
488     ACPI_PARSE_OBJECT       *BufferLengthOp;
489 
490 
491     /* Change op into a buffer object */
492 
493     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
494     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
495     UtSetParseOpName (Op);
496 
497     /* Buffer Length is first, followed by the string */
498 
499     BufferLengthOp = Op->Asl.Child;
500     InitializerOp = BufferLengthOp->Asl.Next;
501 
502     AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
503 
504     /* Create a new buffer for the Unicode string */
505 
506     Count = strlen (InitializerOp->Asl.Value.String) + 1;
507     Length = Count * sizeof (UINT16);
508     UnicodeString = UtLocalCalloc (Length);
509 
510     /* Convert to Unicode string (including null terminator) */
511 
512     for (i = 0; i < Count; i++)
513     {
514         UnicodeString[i] = (UINT16) AsciiString[i];
515     }
516 
517     /*
518      * Just set the buffer size node to be the buffer length, regardless
519      * of whether it was previously an integer or a default_arg placeholder
520      */
521     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
522     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
523     BufferLengthOp->Asl.Value.Integer = Length;
524     UtSetParseOpName (BufferLengthOp);
525 
526     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
527 
528     /* The Unicode string is a raw data buffer */
529 
530     InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
531     InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
532     InitializerOp->Asl.AmlLength = Length;
533     InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
534     InitializerOp->Asl.Child = NULL;
535     UtSetParseOpName (InitializerOp);
536 }
537 
538 
539 /*******************************************************************************
540  *
541  * FUNCTION:    OpcDoEisaId
542  *
543  * PARAMETERS:  Op        - Parse node
544  *
545  * RETURN:      None
546  *
547  * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
548  *              Pnp BIOS Specification for details. Here is an excerpt:
549  *
550  *              A seven character ASCII representation of the product
551  *              identifier compressed into a 32-bit identifier. The seven
552  *              character ID consists of a three character manufacturer code,
553  *              a three character hexadecimal product identifier, and a one
554  *              character hexadecimal revision number. The manufacturer code
555  *              is a 3 uppercase character code that is compressed into 3 5-bit
556  *              values as follows:
557  *                  1) Find hex ASCII value for each letter
558  *                  2) Subtract 40h from each ASCII value
559  *                  3) Retain 5 least significant bits for each letter by
560  *                     discarding upper 3 bits because they are always 0.
561  *                  4) Compressed code = concatenate 0 and the 3 5-bit values
562  *
563  *              The format of the compressed product identifier is as follows:
564  *              Byte 0: Bit 7       - Reserved (0)
565  *                      Bits 6-2:   - 1st character of compressed mfg code
566  *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
567  *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
568  *                      Bits 4-0    - 3rd character of mfg code
569  *              Byte 2: Bits 7-4    - 1st hex digit of product number
570  *                      Bits 3-0    - 2nd hex digit of product number
571  *              Byte 3: Bits 7-4    - 3st hex digit of product number
572  *                      Bits 3-0    - Hex digit of the revision number
573  *
574  ******************************************************************************/
575 
576 static void
577 OpcDoEisaId (
578     ACPI_PARSE_OBJECT       *Op)
579 {
580     UINT32                  EisaId = 0;
581     UINT32                  BigEndianId;
582     char                    *InString;
583     ACPI_STATUS             Status = AE_OK;
584     UINT32                  i;
585 
586 
587     InString = (char *) Op->Asl.Value.String;
588 
589     /*
590      * The EISAID string must be exactly 7 characters and of the form
591      * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
592      */
593     if (strlen (InString) != 7)
594     {
595         Status = AE_BAD_PARAMETER;
596     }
597     else
598     {
599         /* Check all 7 characters for correct format */
600 
601         for (i = 0; i < 7; i++)
602         {
603             /* First 3 characters must be uppercase letters */
604 
605             if (i < 3)
606             {
607                 if (!isupper ((int) InString[i]))
608                 {
609                     Status = AE_BAD_PARAMETER;
610                 }
611             }
612 
613             /* Last 4 characters must be hex digits */
614 
615             else if (!isxdigit ((int) InString[i]))
616             {
617                 Status = AE_BAD_PARAMETER;
618             }
619         }
620     }
621 
622     if (ACPI_FAILURE (Status))
623     {
624         AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
625     }
626     else
627     {
628         /* Create ID big-endian first (bits are contiguous) */
629 
630         BigEndianId =
631             (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
632             (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
633             (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
634 
635             (AcpiUtAsciiCharToHex (InString[3])) << 12 |
636             (AcpiUtAsciiCharToHex (InString[4])) << 8  |
637             (AcpiUtAsciiCharToHex (InString[5])) << 4  |
638              AcpiUtAsciiCharToHex (InString[6]);
639 
640         /* Swap to little-endian to get final ID (see function header) */
641 
642         EisaId = AcpiUtDwordByteSwap (BigEndianId);
643     }
644 
645     /*
646      * Morph the Op into an integer, regardless of whether there
647      * was an error in the EISAID string
648      */
649     Op->Asl.Value.Integer = EisaId;
650 
651     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
652     Op->Asl.ParseOpcode = PARSEOP_INTEGER;
653     (void) OpcSetOptimalIntegerSize (Op);
654 
655     /* Op is now an integer */
656 
657     UtSetParseOpName (Op);
658 }
659 
660 
661 /*******************************************************************************
662  *
663  * FUNCTION:    OpcDoUuId
664  *
665  * PARAMETERS:  Op                  - Parse node
666  *
667  * RETURN:      None
668  *
669  * DESCRIPTION: Convert UUID string to 16-byte buffer
670  *
671  ******************************************************************************/
672 
673 static void
674 OpcDoUuId (
675     ACPI_PARSE_OBJECT       *Op)
676 {
677     char                    *InString;
678     UINT8                   *Buffer;
679     ACPI_STATUS             Status = AE_OK;
680     ACPI_PARSE_OBJECT       *NewOp;
681 
682 
683     InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
684     Buffer = UtLocalCalloc (16);
685 
686     Status = AuValidateUuid (InString);
687     if (ACPI_FAILURE (Status))
688     {
689         AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
690     }
691     else
692     {
693         AcpiUtConvertStringToUuid (InString, Buffer);
694     }
695 
696     /* Change Op to a Buffer */
697 
698     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
699     Op->Common.AmlOpcode = AML_BUFFER_OP;
700 
701     /* Disable further optimization */
702 
703     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
704     UtSetParseOpName (Op);
705 
706     /* Child node is the buffer length */
707 
708     NewOp = TrAllocateNode (PARSEOP_INTEGER);
709 
710     NewOp->Asl.AmlOpcode = AML_BYTE_OP;
711     NewOp->Asl.Value.Integer = 16;
712     NewOp->Asl.Parent = Op;
713 
714     Op->Asl.Child = NewOp;
715     Op = NewOp;
716 
717     /* Peer to the child is the raw buffer data */
718 
719     NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
720     NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
721     NewOp->Asl.AmlLength = 16;
722     NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
723     NewOp->Asl.Parent = Op->Asl.Parent;
724 
725     Op->Asl.Next = NewOp;
726 }
727 
728 
729 /*******************************************************************************
730  *
731  * FUNCTION:    OpcGenerateAmlOpcode
732  *
733  * PARAMETERS:  Op                  - Parse node
734  *
735  * RETURN:      None
736  *
737  * DESCRIPTION: Generate the AML opcode associated with the node and its
738  *              parse (lex/flex) keyword opcode. Essentially implements
739  *              a mapping between the parse opcodes and the actual AML opcodes.
740  *
741  ******************************************************************************/
742 
743 void
744 OpcGenerateAmlOpcode (
745     ACPI_PARSE_OBJECT       *Op)
746 {
747     UINT16                  Index;
748 
749 
750     Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
751 
752     Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
753     Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
754     Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
755 
756     if (!Op->Asl.Value.Integer)
757     {
758         Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
759     }
760 
761     /* Special handling for some opcodes */
762 
763     switch (Op->Asl.ParseOpcode)
764     {
765     case PARSEOP_INTEGER:
766         /*
767          * Set the opcode based on the size of the integer
768          */
769         (void) OpcSetOptimalIntegerSize (Op);
770         break;
771 
772     case PARSEOP_OFFSET:
773 
774         Op->Asl.AmlOpcodeLength = 1;
775         break;
776 
777     case PARSEOP_ACCESSAS:
778 
779         OpcDoAccessAs (Op);
780         break;
781 
782     case PARSEOP_CONNECTION:
783 
784         OpcDoConnection (Op);
785         break;
786 
787     case PARSEOP_EISAID:
788 
789         OpcDoEisaId (Op);
790         break;
791 
792     case PARSEOP_PRINTF:
793 
794         OpcDoPrintf (Op);
795         break;
796 
797     case PARSEOP_FPRINTF:
798 
799         OpcDoFprintf (Op);
800         break;
801 
802     case PARSEOP_TOPLD:
803 
804         OpcDoPld (Op);
805         break;
806 
807     case PARSEOP_TOUUID:
808 
809         OpcDoUuId (Op);
810         break;
811 
812     case PARSEOP_UNICODE:
813 
814         OpcDoUnicode (Op);
815         break;
816 
817     case PARSEOP_INCLUDE:
818 
819         Gbl_HasIncludeFiles = TRUE;
820         break;
821 
822     case PARSEOP_EXTERNAL:
823 
824         if (Gbl_DoExternals == FALSE)
825         {
826             Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
827             Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
828         }
829         break;
830 
831     case PARSEOP_TIMER:
832 
833         if (AcpiGbl_IntegerBitWidth == 32)
834         {
835             AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
836         }
837         break;
838 
839     default:
840 
841         /* Nothing to do for other opcodes */
842 
843         break;
844     }
845 
846     return;
847 }
848