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