xref: /freebsd/sys/contrib/dev/acpica/compiler/aslopcodes.c (revision d244b2279c2f63fc930fa1c11a6033b7119d426a)
153289f6aSNate Lawson 
253289f6aSNate Lawson /******************************************************************************
353289f6aSNate Lawson  *
453289f6aSNate Lawson  * Module Name: aslopcode - AML opcode generation
553289f6aSNate Lawson  *
653289f6aSNate Lawson  *****************************************************************************/
753289f6aSNate Lawson 
8*d244b227SJung-uk Kim /*
9*d244b227SJung-uk Kim  * Copyright (C) 2000 - 2011, Intel Corp.
1053289f6aSNate Lawson  * All rights reserved.
1153289f6aSNate Lawson  *
12*d244b227SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
13*d244b227SJung-uk Kim  * modification, are permitted provided that the following conditions
14*d244b227SJung-uk Kim  * are met:
15*d244b227SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
16*d244b227SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
17*d244b227SJung-uk Kim  *    without modification.
18*d244b227SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19*d244b227SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
20*d244b227SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
21*d244b227SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
22*d244b227SJung-uk Kim  *    binary redistribution.
23*d244b227SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
24*d244b227SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
25*d244b227SJung-uk Kim  *    from this software without specific prior written permission.
2653289f6aSNate Lawson  *
27*d244b227SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
28*d244b227SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
29*d244b227SJung-uk Kim  * Software Foundation.
3053289f6aSNate Lawson  *
31*d244b227SJung-uk Kim  * NO WARRANTY
32*d244b227SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33*d244b227SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34*d244b227SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35*d244b227SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36*d244b227SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*d244b227SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*d244b227SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*d244b227SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40*d244b227SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41*d244b227SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42*d244b227SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
43*d244b227SJung-uk Kim  */
4453289f6aSNate Lawson 
4553289f6aSNate Lawson 
46ab6f3bf9SJung-uk Kim #include <contrib/dev/acpica/compiler/aslcompiler.h>
4753289f6aSNate Lawson #include "aslcompiler.y.h"
48ab6f3bf9SJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h>
4953289f6aSNate Lawson 
5053289f6aSNate Lawson #define _COMPONENT          ACPI_COMPILER
5153289f6aSNate Lawson         ACPI_MODULE_NAME    ("aslopcodes")
5253289f6aSNate Lawson 
5353289f6aSNate Lawson 
54fba7fc7eSJung-uk Kim /* Local prototypes */
55fba7fc7eSJung-uk Kim 
56fba7fc7eSJung-uk Kim static void
57fba7fc7eSJung-uk Kim OpcDoAccessAs (
58fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op);
59fba7fc7eSJung-uk Kim 
60fba7fc7eSJung-uk Kim static void
61fba7fc7eSJung-uk Kim OpcDoUnicode (
62fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op);
63fba7fc7eSJung-uk Kim 
64fba7fc7eSJung-uk Kim static void
65fba7fc7eSJung-uk Kim OpcDoEisaId (
66fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op);
67fba7fc7eSJung-uk Kim 
68fba7fc7eSJung-uk Kim static void
69fba7fc7eSJung-uk Kim OpcDoUuId (
70fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op);
71fba7fc7eSJung-uk Kim 
72fba7fc7eSJung-uk Kim 
73fba7fc7eSJung-uk Kim /*******************************************************************************
74fba7fc7eSJung-uk Kim  *
75fba7fc7eSJung-uk Kim  * FUNCTION:    OpcAmlOpcodeUpdateWalk
76fba7fc7eSJung-uk Kim  *
77fba7fc7eSJung-uk Kim  * PARAMETERS:  ASL_WALK_CALLBACK
78fba7fc7eSJung-uk Kim  *
79fba7fc7eSJung-uk Kim  * RETURN:      Status
80fba7fc7eSJung-uk Kim  *
81fba7fc7eSJung-uk Kim  * DESCRIPTION: Opcode update walk, ascending callback
82fba7fc7eSJung-uk Kim  *
83fba7fc7eSJung-uk Kim  ******************************************************************************/
84fba7fc7eSJung-uk Kim 
85fba7fc7eSJung-uk Kim ACPI_STATUS
86fba7fc7eSJung-uk Kim OpcAmlOpcodeUpdateWalk (
87fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
88fba7fc7eSJung-uk Kim     UINT32                  Level,
89fba7fc7eSJung-uk Kim     void                    *Context)
90fba7fc7eSJung-uk Kim {
91fba7fc7eSJung-uk Kim 
92fba7fc7eSJung-uk Kim     /*
93fba7fc7eSJung-uk Kim      * Handle the Package() case where the actual opcode cannot be determined
94fba7fc7eSJung-uk Kim      * until the PackageLength operand has been folded and minimized.
95fba7fc7eSJung-uk Kim      * (PackageOp versus VarPackageOp)
96fba7fc7eSJung-uk Kim      *
97fba7fc7eSJung-uk Kim      * This is (as of ACPI 3.0) the only case where the AML opcode can change
98fba7fc7eSJung-uk Kim      * based upon the value of a parameter.
99fba7fc7eSJung-uk Kim      *
100fba7fc7eSJung-uk Kim      * The parser always inserts a VarPackage opcode, which can possibly be
101fba7fc7eSJung-uk Kim      * optimized to a Package opcode.
102fba7fc7eSJung-uk Kim      */
103fba7fc7eSJung-uk Kim     if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
104fba7fc7eSJung-uk Kim     {
105fba7fc7eSJung-uk Kim         OpnDoPackage (Op);
106fba7fc7eSJung-uk Kim     }
107fba7fc7eSJung-uk Kim 
108fba7fc7eSJung-uk Kim     return (AE_OK);
109fba7fc7eSJung-uk Kim }
110fba7fc7eSJung-uk Kim 
111fba7fc7eSJung-uk Kim 
11253289f6aSNate Lawson /*******************************************************************************
11353289f6aSNate Lawson  *
11453289f6aSNate Lawson  * FUNCTION:    OpcAmlOpcodeWalk
11553289f6aSNate Lawson  *
11653289f6aSNate Lawson  * PARAMETERS:  ASL_WALK_CALLBACK
11753289f6aSNate Lawson  *
11853289f6aSNate Lawson  * RETURN:      Status
11953289f6aSNate Lawson  *
12053289f6aSNate Lawson  * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
12153289f6aSNate Lawson  *              operands.
12253289f6aSNate Lawson  *
12353289f6aSNate Lawson  ******************************************************************************/
12453289f6aSNate Lawson 
12553289f6aSNate Lawson ACPI_STATUS
12653289f6aSNate Lawson OpcAmlOpcodeWalk (
12753289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op,
12853289f6aSNate Lawson     UINT32                  Level,
12953289f6aSNate Lawson     void                    *Context)
13053289f6aSNate Lawson {
13153289f6aSNate Lawson 
13253289f6aSNate Lawson     TotalParseNodes++;
13353289f6aSNate Lawson 
13453289f6aSNate Lawson     OpcGenerateAmlOpcode (Op);
13553289f6aSNate Lawson     OpnGenerateAmlOperands (Op);
13653289f6aSNate Lawson     return (AE_OK);
13753289f6aSNate Lawson }
13853289f6aSNate Lawson 
13953289f6aSNate Lawson 
14053289f6aSNate Lawson /*******************************************************************************
14153289f6aSNate Lawson  *
14253289f6aSNate Lawson  * FUNCTION:    OpcGetIntegerWidth
14353289f6aSNate Lawson  *
14453289f6aSNate Lawson  * PARAMETERS:  Op          - DEFINITION BLOCK op
14553289f6aSNate Lawson  *
14653289f6aSNate Lawson  * RETURN:      none
14753289f6aSNate Lawson  *
14853289f6aSNate Lawson  * DESCRIPTION: Extract integer width from the table revision
14953289f6aSNate Lawson  *
15053289f6aSNate Lawson  ******************************************************************************/
15153289f6aSNate Lawson 
15253289f6aSNate Lawson void
15353289f6aSNate Lawson OpcGetIntegerWidth (
15453289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op)
15553289f6aSNate Lawson {
15653289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Child;
15753289f6aSNate Lawson 
158fba7fc7eSJung-uk Kim 
15953289f6aSNate Lawson     if (!Op)
16053289f6aSNate Lawson     {
16153289f6aSNate Lawson         return;
16253289f6aSNate Lawson     }
16353289f6aSNate Lawson 
164fba7fc7eSJung-uk Kim     if (Gbl_RevisionOverride)
165fba7fc7eSJung-uk Kim     {
166fba7fc7eSJung-uk Kim         AcpiUtSetIntegerWidth (Gbl_RevisionOverride);
167fba7fc7eSJung-uk Kim     }
168fba7fc7eSJung-uk Kim     else
169fba7fc7eSJung-uk Kim     {
17053289f6aSNate Lawson         Child = Op->Asl.Child;
17153289f6aSNate Lawson         Child = Child->Asl.Next;
17253289f6aSNate Lawson         Child = Child->Asl.Next;
17353289f6aSNate Lawson 
17453289f6aSNate Lawson         /* Use the revision to set the integer width */
17553289f6aSNate Lawson 
17653289f6aSNate Lawson         AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
17753289f6aSNate Lawson     }
178fba7fc7eSJung-uk Kim }
17953289f6aSNate Lawson 
18053289f6aSNate Lawson 
18153289f6aSNate Lawson /*******************************************************************************
18253289f6aSNate Lawson  *
18353289f6aSNate Lawson  * FUNCTION:    OpcSetOptimalIntegerSize
18453289f6aSNate Lawson  *
18553289f6aSNate Lawson  * PARAMETERS:  Op        - A parse tree node
18653289f6aSNate Lawson  *
18753289f6aSNate Lawson  * RETURN:      Integer width, in bytes.  Also sets the node AML opcode to the
18853289f6aSNate Lawson  *              optimal integer AML prefix opcode.
18953289f6aSNate Lawson  *
19053289f6aSNate Lawson  * DESCRIPTION: Determine the optimal AML encoding of an integer.  All leading
19153289f6aSNate Lawson  *              zeros can be truncated to squeeze the integer into the
19253289f6aSNate Lawson  *              minimal number of AML bytes.
19353289f6aSNate Lawson  *
19453289f6aSNate Lawson  ******************************************************************************/
19553289f6aSNate Lawson 
19653289f6aSNate Lawson UINT32
19753289f6aSNate Lawson OpcSetOptimalIntegerSize (
19853289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op)
19953289f6aSNate Lawson {
20053289f6aSNate Lawson 
201fba7fc7eSJung-uk Kim #if 0
20253289f6aSNate Lawson     /*
203fba7fc7eSJung-uk Kim      * TBD: - we don't want to optimize integers in the block header, but the
204fba7fc7eSJung-uk Kim      * code below does not work correctly.
205fba7fc7eSJung-uk Kim      */
206c8466860SMark Santcroos     if (Op->Asl.Parent &&
207c8466860SMark Santcroos         Op->Asl.Parent->Asl.Parent &&
208c8466860SMark Santcroos        (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK))
209c8466860SMark Santcroos     {
210c8466860SMark Santcroos         return 0;
211c8466860SMark Santcroos     }
212fba7fc7eSJung-uk Kim #endif
213c8466860SMark Santcroos 
214c8466860SMark Santcroos     /*
21553289f6aSNate Lawson      * Check for the special AML integers first - Zero, One, Ones.
21653289f6aSNate Lawson      * These are single-byte opcodes that are the smallest possible
21753289f6aSNate Lawson      * representation of an integer.
21853289f6aSNate Lawson      *
21953289f6aSNate Lawson      * This optimization is optional.
22053289f6aSNate Lawson      */
22153289f6aSNate Lawson     if (Gbl_IntegerOptimizationFlag)
22253289f6aSNate Lawson     {
22353289f6aSNate Lawson         switch (Op->Asl.Value.Integer)
22453289f6aSNate Lawson         {
22553289f6aSNate Lawson         case 0:
22653289f6aSNate Lawson 
22753289f6aSNate Lawson             Op->Asl.AmlOpcode = AML_ZERO_OP;
228fba7fc7eSJung-uk Kim             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
229fba7fc7eSJung-uk Kim                 Op, "Zero");
23053289f6aSNate Lawson             return 1;
23153289f6aSNate Lawson 
23253289f6aSNate Lawson         case 1:
23353289f6aSNate Lawson 
23453289f6aSNate Lawson             Op->Asl.AmlOpcode = AML_ONE_OP;
235fba7fc7eSJung-uk Kim             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
236fba7fc7eSJung-uk Kim                 Op, "One");
23753289f6aSNate Lawson             return 1;
23853289f6aSNate Lawson 
23953289f6aSNate Lawson         case ACPI_UINT32_MAX:
24053289f6aSNate Lawson 
24153289f6aSNate Lawson             /* Check for table integer width (32 or 64) */
24253289f6aSNate Lawson 
24353289f6aSNate Lawson             if (AcpiGbl_IntegerByteWidth == 4)
24453289f6aSNate Lawson             {
24553289f6aSNate Lawson                 Op->Asl.AmlOpcode = AML_ONES_OP;
246fba7fc7eSJung-uk Kim                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
247fba7fc7eSJung-uk Kim                     Op, "Ones");
24853289f6aSNate Lawson                 return 1;
24953289f6aSNate Lawson             }
25053289f6aSNate Lawson             break;
25153289f6aSNate Lawson 
2529a179dd8SJung-uk Kim         case ACPI_UINT64_MAX:
25353289f6aSNate Lawson 
25453289f6aSNate Lawson             /* Check for table integer width (32 or 64) */
25553289f6aSNate Lawson 
25653289f6aSNate Lawson             if (AcpiGbl_IntegerByteWidth == 8)
25753289f6aSNate Lawson             {
25853289f6aSNate Lawson                 Op->Asl.AmlOpcode = AML_ONES_OP;
259fba7fc7eSJung-uk Kim                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
260fba7fc7eSJung-uk Kim                     Op, "Ones");
26153289f6aSNate Lawson                 return 1;
26253289f6aSNate Lawson             }
26353289f6aSNate Lawson             break;
26453289f6aSNate Lawson 
26553289f6aSNate Lawson         default:
26653289f6aSNate Lawson             break;
26753289f6aSNate Lawson         }
26853289f6aSNate Lawson     }
26953289f6aSNate Lawson 
27053289f6aSNate Lawson     /* Find the best fit using the various AML integer prefixes */
27153289f6aSNate Lawson 
27253289f6aSNate Lawson     if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
27353289f6aSNate Lawson     {
27453289f6aSNate Lawson         Op->Asl.AmlOpcode = AML_BYTE_OP;
27553289f6aSNate Lawson         return 1;
27653289f6aSNate Lawson     }
27753289f6aSNate Lawson     if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
27853289f6aSNate Lawson     {
27953289f6aSNate Lawson         Op->Asl.AmlOpcode = AML_WORD_OP;
28053289f6aSNate Lawson         return 2;
28153289f6aSNate Lawson     }
28253289f6aSNate Lawson     if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
28353289f6aSNate Lawson     {
28453289f6aSNate Lawson         Op->Asl.AmlOpcode = AML_DWORD_OP;
28553289f6aSNate Lawson         return 4;
28653289f6aSNate Lawson     }
28753289f6aSNate Lawson     else
28853289f6aSNate Lawson     {
289fba7fc7eSJung-uk Kim         if (AcpiGbl_IntegerByteWidth == 4)
290fba7fc7eSJung-uk Kim         {
291fba7fc7eSJung-uk Kim             AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
292fba7fc7eSJung-uk Kim                 Op, NULL);
293fba7fc7eSJung-uk Kim 
294fba7fc7eSJung-uk Kim             if (!Gbl_IgnoreErrors)
295fba7fc7eSJung-uk Kim             {
296fba7fc7eSJung-uk Kim                 /* Truncate the integer to 32-bit */
297fba7fc7eSJung-uk Kim                 Op->Asl.AmlOpcode = AML_DWORD_OP;
298fba7fc7eSJung-uk Kim                 return 4;
299fba7fc7eSJung-uk Kim             }
300fba7fc7eSJung-uk Kim         }
301fba7fc7eSJung-uk Kim 
30253289f6aSNate Lawson         Op->Asl.AmlOpcode = AML_QWORD_OP;
30353289f6aSNate Lawson         return 8;
30453289f6aSNate Lawson     }
30553289f6aSNate Lawson }
30653289f6aSNate Lawson 
30753289f6aSNate Lawson 
30853289f6aSNate Lawson /*******************************************************************************
30953289f6aSNate Lawson  *
31053289f6aSNate Lawson  * FUNCTION:    OpcDoAccessAs
31153289f6aSNate Lawson  *
31253289f6aSNate Lawson  * PARAMETERS:  Op        - Parse node
31353289f6aSNate Lawson  *
31453289f6aSNate Lawson  * RETURN:      None
31553289f6aSNate Lawson  *
31653289f6aSNate Lawson  * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
31753289f6aSNate Lawson  *
31853289f6aSNate Lawson  ******************************************************************************/
31953289f6aSNate Lawson 
320fba7fc7eSJung-uk Kim static void
32153289f6aSNate Lawson OpcDoAccessAs (
32253289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op)
32353289f6aSNate Lawson {
32453289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Next;
32553289f6aSNate Lawson 
32653289f6aSNate Lawson 
32753289f6aSNate Lawson     Op->Asl.AmlOpcodeLength = 1;
32853289f6aSNate Lawson     Next = Op->Asl.Child;
32953289f6aSNate Lawson 
33053289f6aSNate Lawson     /* First child is the access type */
33153289f6aSNate Lawson 
33253289f6aSNate Lawson     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
33353289f6aSNate Lawson     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
33453289f6aSNate Lawson 
33553289f6aSNate Lawson     /* Second child is the optional access attribute */
33653289f6aSNate Lawson 
33753289f6aSNate Lawson     Next = Next->Asl.Next;
33853289f6aSNate Lawson     if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
33953289f6aSNate Lawson     {
34053289f6aSNate Lawson         Next->Asl.Value.Integer = 0;
34153289f6aSNate Lawson     }
34253289f6aSNate Lawson     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
34353289f6aSNate Lawson     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
34453289f6aSNate Lawson }
34553289f6aSNate Lawson 
34653289f6aSNate Lawson 
34753289f6aSNate Lawson /*******************************************************************************
34853289f6aSNate Lawson  *
34953289f6aSNate Lawson  * FUNCTION:    OpcDoUnicode
35053289f6aSNate Lawson  *
35153289f6aSNate Lawson  * PARAMETERS:  Op        - Parse node
35253289f6aSNate Lawson  *
35353289f6aSNate Lawson  * RETURN:      None
35453289f6aSNate Lawson  *
35553289f6aSNate Lawson  * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
35653289f6aSNate Lawson  *              to a unicode buffer.  There is no Unicode AML opcode.
35753289f6aSNate Lawson  *
35853289f6aSNate Lawson  * Note:  The Unicode string is 16 bits per character, no leading signature,
35953289f6aSNate Lawson  *        with a 16-bit terminating NULL.
36053289f6aSNate Lawson  *
36153289f6aSNate Lawson  ******************************************************************************/
36253289f6aSNate Lawson 
363fba7fc7eSJung-uk Kim static void
36453289f6aSNate Lawson OpcDoUnicode (
36553289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op)
36653289f6aSNate Lawson {
36753289f6aSNate Lawson     ACPI_PARSE_OBJECT       *InitializerOp;
36853289f6aSNate Lawson     UINT32                  Length;
36953289f6aSNate Lawson     UINT32                  Count;
37053289f6aSNate Lawson     UINT32                  i;
37153289f6aSNate Lawson     UINT8                   *AsciiString;
37253289f6aSNate Lawson     UINT16                  *UnicodeString;
37353289f6aSNate Lawson     ACPI_PARSE_OBJECT       *BufferLengthOp;
37453289f6aSNate Lawson 
37553289f6aSNate Lawson 
37653289f6aSNate Lawson     /* Change op into a buffer object */
37753289f6aSNate Lawson 
37853289f6aSNate Lawson     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
37953289f6aSNate Lawson     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
38053289f6aSNate Lawson     UtSetParseOpName (Op);
38153289f6aSNate Lawson 
38253289f6aSNate Lawson     /* Buffer Length is first, followed by the string */
38353289f6aSNate Lawson 
38453289f6aSNate Lawson     BufferLengthOp = Op->Asl.Child;
38553289f6aSNate Lawson     InitializerOp = BufferLengthOp->Asl.Next;
38653289f6aSNate Lawson 
38753289f6aSNate Lawson     AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
38853289f6aSNate Lawson 
38953289f6aSNate Lawson     /* Create a new buffer for the Unicode string */
39053289f6aSNate Lawson 
39153289f6aSNate Lawson     Count = strlen (InitializerOp->Asl.Value.String) + 1;
39253289f6aSNate Lawson     Length = Count * sizeof (UINT16);
39353289f6aSNate Lawson     UnicodeString = UtLocalCalloc (Length);
39453289f6aSNate Lawson 
39553289f6aSNate Lawson     /* Convert to Unicode string (including null terminator) */
39653289f6aSNate Lawson 
39753289f6aSNate Lawson     for (i = 0; i < Count; i++)
39853289f6aSNate Lawson     {
39953289f6aSNate Lawson         UnicodeString[i] = (UINT16) AsciiString[i];
40053289f6aSNate Lawson     }
40153289f6aSNate Lawson 
40253289f6aSNate Lawson     /*
40353289f6aSNate Lawson      * Just set the buffer size node to be the buffer length, regardless
40453289f6aSNate Lawson      * of whether it was previously an integer or a default_arg placeholder
40553289f6aSNate Lawson      */
40653289f6aSNate Lawson     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
40753289f6aSNate Lawson     BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
40853289f6aSNate Lawson     BufferLengthOp->Asl.Value.Integer = Length;
40953289f6aSNate Lawson     UtSetParseOpName (BufferLengthOp);
41053289f6aSNate Lawson 
41153289f6aSNate Lawson     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
41253289f6aSNate Lawson 
41353289f6aSNate Lawson     /* The Unicode string is a raw data buffer */
41453289f6aSNate Lawson 
41553289f6aSNate Lawson     InitializerOp->Asl.Value.Buffer   = (UINT8 *) UnicodeString;
41653289f6aSNate Lawson     InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
41753289f6aSNate Lawson     InitializerOp->Asl.AmlLength      = Length;
41853289f6aSNate Lawson     InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
41953289f6aSNate Lawson     InitializerOp->Asl.Child          = NULL;
42053289f6aSNate Lawson     UtSetParseOpName (InitializerOp);
42153289f6aSNate Lawson }
42253289f6aSNate Lawson 
42353289f6aSNate Lawson 
42453289f6aSNate Lawson /*******************************************************************************
42553289f6aSNate Lawson  *
42653289f6aSNate Lawson  * FUNCTION:    OpcDoEisaId
42753289f6aSNate Lawson  *
42853289f6aSNate Lawson  * PARAMETERS:  Op        - Parse node
42953289f6aSNate Lawson  *
43053289f6aSNate Lawson  * RETURN:      None
43153289f6aSNate Lawson  *
43253289f6aSNate Lawson  * DESCRIPTION: Convert a string EISA ID to numeric representation.  See the
43353289f6aSNate Lawson  *              Pnp BIOS Specification for details.  Here is an excerpt:
43453289f6aSNate Lawson  *
43553289f6aSNate Lawson  *              A seven character ASCII representation of the product
43653289f6aSNate Lawson  *              identifier compressed into a 32-bit identifier.  The seven
43753289f6aSNate Lawson  *              character ID consists of a three character manufacturer code,
43853289f6aSNate Lawson  *              a three character hexadecimal product identifier, and a one
43953289f6aSNate Lawson  *              character hexadecimal revision number.  The manufacturer code
44053289f6aSNate Lawson  *              is a 3 uppercase character code that is compressed into 3 5-bit
44153289f6aSNate Lawson  *              values as follows:
44253289f6aSNate Lawson  *                  1) Find hex ASCII value for each letter
44353289f6aSNate Lawson  *                  2) Subtract 40h from each ASCII value
44453289f6aSNate Lawson  *                  3) Retain 5 least signficant bits for each letter by
44553289f6aSNate Lawson  *                     discarding upper 3 bits because they are always 0.
44653289f6aSNate Lawson  *                  4) Compressed code = concatenate 0 and the 3 5-bit values
44753289f6aSNate Lawson  *
44853289f6aSNate Lawson  *              The format of the compressed product identifier is as follows:
44953289f6aSNate Lawson  *              Byte 0: Bit 7       - Reserved (0)
45053289f6aSNate Lawson  *                      Bits 6-2:   - 1st character of compressed mfg code
45153289f6aSNate Lawson  *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
45253289f6aSNate Lawson  *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
45353289f6aSNate Lawson  *                      Bits 4-0    - 3rd character of mfg code
45453289f6aSNate Lawson  *              Byte 2: Bits 7-4    - 1st hex digit of product number
45553289f6aSNate Lawson  *                      Bits 3-0    - 2nd hex digit of product number
45653289f6aSNate Lawson  *              Byte 3: Bits 7-4    - 3st hex digit of product number
45753289f6aSNate Lawson  *                      Bits 3-0    - Hex digit of the revision number
45853289f6aSNate Lawson  *
45953289f6aSNate Lawson  ******************************************************************************/
46053289f6aSNate Lawson 
461fba7fc7eSJung-uk Kim static void
46253289f6aSNate Lawson OpcDoEisaId (
46353289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op)
46453289f6aSNate Lawson {
46553289f6aSNate Lawson     UINT32                  EisaId = 0;
46653289f6aSNate Lawson     UINT32                  BigEndianId;
46753289f6aSNate Lawson     char                    *InString;
46853289f6aSNate Lawson     ACPI_STATUS             Status = AE_OK;
469a9f12690SJung-uk Kim     UINT32                  i;
47053289f6aSNate Lawson 
47153289f6aSNate Lawson 
47253289f6aSNate Lawson     InString = (char *) Op->Asl.Value.String;
47353289f6aSNate Lawson 
47453289f6aSNate Lawson     /*
47553289f6aSNate Lawson      * The EISAID string must be exactly 7 characters and of the form
476fba7fc7eSJung-uk Kim      * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
47753289f6aSNate Lawson      */
47853289f6aSNate Lawson     if (ACPI_STRLEN (InString) != 7)
47953289f6aSNate Lawson     {
48053289f6aSNate Lawson         Status = AE_BAD_PARAMETER;
48153289f6aSNate Lawson     }
48253289f6aSNate Lawson     else
48353289f6aSNate Lawson     {
48453289f6aSNate Lawson         /* Check all 7 characters for correct format */
48553289f6aSNate Lawson 
48653289f6aSNate Lawson         for (i = 0; i < 7; i++)
48753289f6aSNate Lawson         {
488c8466860SMark Santcroos             /* First 3 characters must be uppercase letters */
48953289f6aSNate Lawson 
49053289f6aSNate Lawson             if (i < 3)
49153289f6aSNate Lawson             {
4929a179dd8SJung-uk Kim                 if (!isupper ((int) InString[i]))
49353289f6aSNate Lawson                 {
49453289f6aSNate Lawson                     Status = AE_BAD_PARAMETER;
49553289f6aSNate Lawson                 }
49653289f6aSNate Lawson             }
49753289f6aSNate Lawson 
49853289f6aSNate Lawson             /* Last 4 characters must be hex digits */
49953289f6aSNate Lawson 
5009a179dd8SJung-uk Kim             else if (!isxdigit ((int) InString[i]))
50153289f6aSNate Lawson             {
50253289f6aSNate Lawson                 Status = AE_BAD_PARAMETER;
50353289f6aSNate Lawson             }
50453289f6aSNate Lawson         }
50553289f6aSNate Lawson     }
50653289f6aSNate Lawson 
50753289f6aSNate Lawson     if (ACPI_FAILURE (Status))
50853289f6aSNate Lawson     {
50953289f6aSNate Lawson         AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
51053289f6aSNate Lawson     }
51153289f6aSNate Lawson     else
51253289f6aSNate Lawson     {
51353289f6aSNate Lawson         /* Create ID big-endian first (bits are contiguous) */
51453289f6aSNate Lawson 
5151a39cfb0SJung-uk Kim         BigEndianId =
51642fecd12SJung-uk Kim             (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
51742fecd12SJung-uk Kim             (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
51842fecd12SJung-uk Kim             (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
51953289f6aSNate Lawson 
52053289f6aSNate Lawson             (UtHexCharToValue (InString[3])) << 12 |
52153289f6aSNate Lawson             (UtHexCharToValue (InString[4])) << 8  |
52253289f6aSNate Lawson             (UtHexCharToValue (InString[5])) << 4  |
52353289f6aSNate Lawson              UtHexCharToValue (InString[6]);
52453289f6aSNate Lawson 
52553289f6aSNate Lawson         /* Swap to little-endian to get final ID (see function header) */
52653289f6aSNate Lawson 
52753289f6aSNate Lawson         EisaId = AcpiUtDwordByteSwap (BigEndianId);
52853289f6aSNate Lawson     }
52953289f6aSNate Lawson 
53053289f6aSNate Lawson     /*
53153289f6aSNate Lawson      * Morph the Op into an integer, regardless of whether there
53253289f6aSNate Lawson      * was an error in the EISAID string
53353289f6aSNate Lawson      */
53453289f6aSNate Lawson     Op->Asl.Value.Integer = EisaId;
53553289f6aSNate Lawson 
53653289f6aSNate Lawson     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
53753289f6aSNate Lawson     Op->Asl.ParseOpcode = PARSEOP_INTEGER;
53853289f6aSNate Lawson     (void) OpcSetOptimalIntegerSize (Op);
53953289f6aSNate Lawson 
54053289f6aSNate Lawson     /* Op is now an integer */
54153289f6aSNate Lawson 
54253289f6aSNate Lawson     UtSetParseOpName (Op);
54353289f6aSNate Lawson }
54453289f6aSNate Lawson 
54553289f6aSNate Lawson 
54653289f6aSNate Lawson /*******************************************************************************
54753289f6aSNate Lawson  *
548c8466860SMark Santcroos  * FUNCTION:    OpcDoUiId
549c8466860SMark Santcroos  *
550c8466860SMark Santcroos  * PARAMETERS:  Op        - Parse node
551c8466860SMark Santcroos  *
552c8466860SMark Santcroos  * RETURN:      None
553c8466860SMark Santcroos  *
554fba7fc7eSJung-uk Kim  * DESCRIPTION: Convert UUID string to 16-byte buffer
555c8466860SMark Santcroos  *
556c8466860SMark Santcroos  ******************************************************************************/
557c8466860SMark Santcroos 
558fba7fc7eSJung-uk Kim static void
559c8466860SMark Santcroos OpcDoUuId (
560c8466860SMark Santcroos     ACPI_PARSE_OBJECT       *Op)
561c8466860SMark Santcroos {
562c8466860SMark Santcroos     char                    *InString;
563c8466860SMark Santcroos     char                    *Buffer;
564c8466860SMark Santcroos     ACPI_STATUS             Status = AE_OK;
565c8466860SMark Santcroos     ACPI_PARSE_OBJECT       *NewOp;
566c8466860SMark Santcroos 
567c8466860SMark Santcroos 
568c8466860SMark Santcroos     InString = (char *) Op->Asl.Value.String;
569c8466860SMark Santcroos     Buffer = UtLocalCalloc (16);
570c8466860SMark Santcroos 
571*d244b227SJung-uk Kim     Status = AuValidateUuid (InString);
572c8466860SMark Santcroos     if (ACPI_FAILURE (Status))
573c8466860SMark Santcroos     {
574c8466860SMark Santcroos         AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
575c8466860SMark Santcroos     }
576*d244b227SJung-uk Kim     else
577c8466860SMark Santcroos     {
578*d244b227SJung-uk Kim         (void) AuConvertStringToUuid (InString, Buffer);
579c8466860SMark Santcroos     }
580c8466860SMark Santcroos 
581c8466860SMark Santcroos     /* Change Op to a Buffer */
582c8466860SMark Santcroos 
583c8466860SMark Santcroos     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
584c8466860SMark Santcroos     Op->Common.AmlOpcode = AML_BUFFER_OP;
585fba7fc7eSJung-uk Kim 
586fba7fc7eSJung-uk Kim     /* Disable further optimization */
587fba7fc7eSJung-uk Kim 
588fba7fc7eSJung-uk Kim     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
589c8466860SMark Santcroos     UtSetParseOpName (Op);
590c8466860SMark Santcroos 
591c8466860SMark Santcroos     /* Child node is the buffer length */
592c8466860SMark Santcroos 
593c8466860SMark Santcroos     NewOp = TrAllocateNode (PARSEOP_INTEGER);
594c8466860SMark Santcroos 
595c8466860SMark Santcroos     NewOp->Asl.AmlOpcode     = AML_BYTE_OP;
596c8466860SMark Santcroos     NewOp->Asl.Value.Integer = 16;
597c8466860SMark Santcroos     NewOp->Asl.Parent        = Op;
598c8466860SMark Santcroos 
599c8466860SMark Santcroos     Op->Asl.Child = NewOp;
600c8466860SMark Santcroos     Op = NewOp;
601c8466860SMark Santcroos 
602c8466860SMark Santcroos     /* Peer to the child is the raw buffer data */
603c8466860SMark Santcroos 
604c8466860SMark Santcroos     NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
605c8466860SMark Santcroos     NewOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
606c8466860SMark Santcroos     NewOp->Asl.AmlLength     = 16;
607c8466860SMark Santcroos     NewOp->Asl.Value.String  = (char *) Buffer;
608c8466860SMark Santcroos     NewOp->Asl.Parent        = Op->Asl.Parent;
609c8466860SMark Santcroos 
610c8466860SMark Santcroos     Op->Asl.Next = NewOp;
611c8466860SMark Santcroos }
612c8466860SMark Santcroos 
613c8466860SMark Santcroos 
614c8466860SMark Santcroos /*******************************************************************************
615c8466860SMark Santcroos  *
61653289f6aSNate Lawson  * FUNCTION:    OpcGenerateAmlOpcode
61753289f6aSNate Lawson  *
61853289f6aSNate Lawson  * PARAMETERS:  Op        - Parse node
61953289f6aSNate Lawson  *
62053289f6aSNate Lawson  * RETURN:      None
62153289f6aSNate Lawson  *
62253289f6aSNate Lawson  * DESCRIPTION: Generate the AML opcode associated with the node and its
62353289f6aSNate Lawson  *              parse (lex/flex) keyword opcode.  Essentially implements
62453289f6aSNate Lawson  *              a mapping between the parse opcodes and the actual AML opcodes.
62553289f6aSNate Lawson  *
62653289f6aSNate Lawson  ******************************************************************************/
62753289f6aSNate Lawson 
62853289f6aSNate Lawson void
62953289f6aSNate Lawson OpcGenerateAmlOpcode (
63053289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op)
63153289f6aSNate Lawson {
63253289f6aSNate Lawson 
63353289f6aSNate Lawson     UINT16                  Index;
63453289f6aSNate Lawson 
63553289f6aSNate Lawson 
63653289f6aSNate Lawson     Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
63753289f6aSNate Lawson 
63853289f6aSNate Lawson     Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
63953289f6aSNate Lawson     Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
64053289f6aSNate Lawson     Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
64153289f6aSNate Lawson 
64253289f6aSNate Lawson     if (!Op->Asl.Value.Integer)
64353289f6aSNate Lawson     {
64453289f6aSNate Lawson         Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
64553289f6aSNate Lawson     }
64653289f6aSNate Lawson 
64753289f6aSNate Lawson     /* Special handling for some opcodes */
64853289f6aSNate Lawson 
64953289f6aSNate Lawson     switch (Op->Asl.ParseOpcode)
65053289f6aSNate Lawson     {
65153289f6aSNate Lawson     case PARSEOP_INTEGER:
65253289f6aSNate Lawson         /*
65353289f6aSNate Lawson          * Set the opcode based on the size of the integer
65453289f6aSNate Lawson          */
65553289f6aSNate Lawson         (void) OpcSetOptimalIntegerSize (Op);
65653289f6aSNate Lawson         break;
65753289f6aSNate Lawson 
65853289f6aSNate Lawson     case PARSEOP_OFFSET:
65953289f6aSNate Lawson 
66053289f6aSNate Lawson         Op->Asl.AmlOpcodeLength = 1;
66153289f6aSNate Lawson         break;
66253289f6aSNate Lawson 
66353289f6aSNate Lawson     case PARSEOP_ACCESSAS:
66453289f6aSNate Lawson 
66553289f6aSNate Lawson         OpcDoAccessAs (Op);
66653289f6aSNate Lawson         break;
66753289f6aSNate Lawson 
66853289f6aSNate Lawson     case PARSEOP_EISAID:
66953289f6aSNate Lawson 
67053289f6aSNate Lawson         OpcDoEisaId (Op);
67153289f6aSNate Lawson         break;
67253289f6aSNate Lawson 
673c8466860SMark Santcroos     case PARSEOP_TOUUID:
674c8466860SMark Santcroos 
675c8466860SMark Santcroos         OpcDoUuId (Op);
676c8466860SMark Santcroos         break;
677c8466860SMark Santcroos 
67853289f6aSNate Lawson     case PARSEOP_UNICODE:
67953289f6aSNate Lawson 
68053289f6aSNate Lawson         OpcDoUnicode (Op);
68153289f6aSNate Lawson         break;
68253289f6aSNate Lawson 
68353289f6aSNate Lawson     case PARSEOP_INCLUDE:
68453289f6aSNate Lawson 
68553289f6aSNate Lawson         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
68653289f6aSNate Lawson         Gbl_HasIncludeFiles = TRUE;
68753289f6aSNate Lawson         break;
68853289f6aSNate Lawson 
68953289f6aSNate Lawson     case PARSEOP_EXTERNAL:
69053289f6aSNate Lawson 
69153289f6aSNate Lawson         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
69253289f6aSNate Lawson         Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
69353289f6aSNate Lawson         break;
69453289f6aSNate Lawson 
69553289f6aSNate Lawson     default:
69653289f6aSNate Lawson         /* Nothing to do for other opcodes */
69753289f6aSNate Lawson         break;
69853289f6aSNate Lawson     }
69953289f6aSNate Lawson 
70053289f6aSNate Lawson     return;
70153289f6aSNate Lawson }
70253289f6aSNate Lawson 
70353289f6aSNate Lawson 
704