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