dtexpress.c revision 218590
155714Skris/******************************************************************************
255714Skris *
355714Skris * Module Name: dtexpress.c - Support for integer expressions and labels
455714Skris *
555714Skris *****************************************************************************/
655714Skris
755714Skris/*
8280304Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
955714Skris * All rights reserved.
1055714Skris *
1155714Skris * Redistribution and use in source and binary forms, with or without
1255714Skris * modification, are permitted provided that the following conditions
1355714Skris * are met:
1455714Skris * 1. Redistributions of source code must retain the above copyright
15280304Sjkim *    notice, this list of conditions, and the following disclaimer,
1655714Skris *    without modification.
1755714Skris * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1855714Skris *    substantially similar to the "NO WARRANTY" disclaimer below
1955714Skris *    ("Disclaimer") and any redistribution must be conditioned upon
2055714Skris *    including a substantially similar Disclaimer requirement for further
2155714Skris *    binary redistribution.
22280304Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
2355714Skris *    of any contributors may be used to endorse or promote products derived
2455714Skris *    from this software without specific prior written permission.
2555714Skris *
2655714Skris * Alternatively, this software may be distributed under the terms of the
2755714Skris * GNU General Public License ("GPL") version 2 as published by the Free
2855714Skris * Software Foundation.
2955714Skris *
3055714Skris * NO WARRANTY
3155714Skris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3255714Skris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3355714Skris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3455714Skris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3555714Skris * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37280304Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40280304Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4155714Skris * POSSIBILITY OF SUCH DAMAGES.
4255714Skris */
4355714Skris
4455714Skris#define __DTEXPRESS_C__
4555714Skris
4655714Skris#include <contrib/dev/acpica/compiler/aslcompiler.h>
4755714Skris#include <contrib/dev/acpica/compiler/dtcompiler.h>
4855714Skris
4955714Skris#define _COMPONENT          DT_COMPILER
5055714Skris        ACPI_MODULE_NAME    ("dtexpress")
5155714Skris
52280304Sjkim
5355714Skris/* Local prototypes */
5455714Skris
5555714Skrisstatic UINT64
5655714SkrisDtResolveInteger (
5755714Skris    DT_FIELD                *Field,
5855714Skris    char                    *IntegerString);
5955714Skris
6055714Skrisstatic void
6155714SkrisDtInsertLabelField (
6255714Skris    DT_FIELD                *Field);
6355714Skris
6455714Skrisstatic DT_FIELD *
6555714SkrisDtLookupLabel (
6655714Skris    char                    *Name);
67280304Sjkim
68280304Sjkim
69280304Sjkim/******************************************************************************
70280304Sjkim *
71280304Sjkim * FUNCTION:    DtResolveIntegerExpression
7255714Skris *
7355714Skris * PARAMETERS:  Field               - Field object with Integer expression
74280304Sjkim *
75280304Sjkim * RETURN:      A 64-bit integer value
76280304Sjkim *
77280304Sjkim * DESCRIPTION: Resolve an integer expression to a single value. Supports
78280304Sjkim *              both integer constants and labels. Supported operators are:
7955714Skris *              +,-,*,/,%,|,&,^
8055714Skris *
81280304Sjkim *****************************************************************************/
82280304Sjkim
83280304SjkimUINT64
84280304SjkimDtResolveIntegerExpression (
85280304Sjkim    DT_FIELD                *Field)
86{
87    char                    *IntegerString;
88    char                    *Operator;
89    UINT64                  Value;
90    UINT64                  Value2;
91
92
93    DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n",
94        Field->Value);
95
96    strcpy (MsgBuffer, Field->Value); /* Must take a copy for strtok() */
97
98    /* Obtain and resolve the first operand */
99
100    IntegerString = strtok (MsgBuffer, " ");
101    if (!IntegerString)
102    {
103        DtError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, Field, Field->Value);
104        return (0);
105    }
106
107    Value = DtResolveInteger (Field, IntegerString);
108    DbgPrint (ASL_DEBUG_OUTPUT, "Integer resolved to V1: %8.8X%8.8X\n",
109        ACPI_FORMAT_UINT64 (Value));
110
111    /*
112     * Consume the entire expression string. For the rest of the
113     * expression string, values are of the form:
114     * <operator> <integer>
115     */
116    while (1)
117    {
118        Operator = strtok (NULL, " ");
119        if (!Operator)
120        {
121            /* Normal exit */
122
123            DbgPrint (ASL_DEBUG_OUTPUT, "Expression Resolved to: %8.8X%8.8X\n",
124                ACPI_FORMAT_UINT64 (Value));
125
126            return (Value);
127        }
128
129        IntegerString = strtok (NULL, " ");
130        if (!IntegerString ||
131            (strlen (Operator) > 1))
132        {
133            /* No corresponding operand for operator or invalid operator */
134
135            DtError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, Field, Field->Value);
136            return (0);
137        }
138
139        Value2 = DtResolveInteger (Field, IntegerString);
140        DbgPrint (ASL_DEBUG_OUTPUT, "Integer resolved to V2: %8.8X%8.8X\n",
141            ACPI_FORMAT_UINT64 (Value2));
142
143        /* Perform the requested operation */
144
145        switch (*Operator)
146        {
147        case '-':
148            Value -= Value2;
149            break;
150
151        case '+':
152            Value += Value2;
153            break;
154
155        case '*':
156            Value *= Value2;
157            break;
158
159        case '|':
160            Value |= Value2;
161            break;
162
163        case '&':
164            Value &= Value2;
165            break;
166
167        case '^':
168            Value ^= Value2;
169            break;
170
171        case '/':
172            if (!Value2)
173            {
174                DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, Field, Field->Value);
175                return (0);
176            }
177            Value /= Value2;
178            break;
179
180        case '%':
181            if (!Value2)
182            {
183                DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, Field, Field->Value);
184                return (0);
185            }
186            Value %= Value2;
187            break;
188
189        default:
190
191            /* Unknown operator */
192
193            DtFatal (ASL_MSG_INVALID_EXPRESSION, Field, Field->Value);
194            break;
195        }
196    }
197
198    return (Value);
199}
200
201
202/******************************************************************************
203 *
204 * FUNCTION:    DtResolveInteger
205 *
206 * PARAMETERS:  Field               - Field object with string to be resolved
207 *              IntegerString       - Integer to be resolved
208 *
209 * RETURN:      A 64-bit integer value
210 *
211 * DESCRIPTION: Resolve a single integer string to a value. Supports both
212 *              integer constants and labels.
213 *
214 * NOTE:        References to labels must begin with a dollar sign ($)
215 *
216 *****************************************************************************/
217
218static UINT64
219DtResolveInteger (
220    DT_FIELD                *Field,
221    char                    *IntegerString)
222{
223    DT_FIELD                *LabelField;
224    UINT64                  Value = 0;
225    char                    *Message = NULL;
226    ACPI_STATUS             Status;
227
228
229    DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Integer: %s\n", IntegerString);
230
231    /* Resolve a label reference to an integer (table offset) */
232
233    if (*IntegerString == '$')
234    {
235        LabelField = DtLookupLabel (IntegerString);
236        if (!LabelField)
237        {
238            DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, Field, IntegerString);
239            return (0);
240        }
241
242        /* All we need from the label is the offset in the table */
243
244        Value = LabelField->TableOffset;
245        return (Value);
246    }
247
248    /* Convert string to an actual integer */
249
250    Status = DtStrtoul64 (IntegerString, &Value);
251    if (ACPI_FAILURE (Status))
252    {
253        if (Status == AE_LIMIT)
254        {
255            Message = "Constant larger than 64 bits";
256        }
257        else if (Status == AE_BAD_CHARACTER)
258        {
259            Message = "Invalid character in constant";
260        }
261
262        DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, Message);
263    }
264
265    return (Value);
266}
267
268
269/******************************************************************************
270 *
271 * FUNCTION:    DtDetectAllLabels
272 *
273 * PARAMETERS:  FieldList           - Field object at start of generic list
274 *
275 * RETURN:      None
276 *
277 * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as
278 *              a UEFI table.) and insert them into the global label list.
279 *
280 *****************************************************************************/
281
282void
283DtDetectAllLabels (
284    DT_FIELD                *FieldList)
285{
286    ACPI_DMTABLE_INFO       *Info;
287    DT_FIELD                *GenericField;
288    UINT32                  TableOffset;
289
290
291    TableOffset = Gbl_CurrentTableOffset;
292    GenericField = FieldList;
293
294    /*
295     * Process all "Label:" fields within the parse tree. We need
296     * to know the offsets for all labels before we can compile
297     * the parse tree in order to handle forward references. Traverse
298     * tree and get/set all field lengths of all operators in order to
299     * determine the label offsets.
300     */
301    while (GenericField)
302    {
303        Info = DtGetGenericTableInfo (GenericField->Name);
304        if (Info)
305        {
306            /* Maintain table offsets */
307
308            GenericField->TableOffset = TableOffset;
309            TableOffset += DtGetFieldLength (GenericField, Info);
310
311            /* Insert all labels in the global label list */
312
313            if (Info->Opcode == ACPI_DMT_LABEL)
314            {
315                DtInsertLabelField (GenericField);
316            }
317        }
318
319        GenericField = GenericField->Next;
320    }
321}
322
323
324/******************************************************************************
325 *
326 * FUNCTION:    DtInsertLabelField
327 *
328 * PARAMETERS:  Field               - Field object with Label to be inserted
329 *
330 * RETURN:      None
331 *
332 * DESCRIPTION: Insert a label field into the global label list
333 *
334 *****************************************************************************/
335
336static void
337DtInsertLabelField (
338    DT_FIELD                *Field)
339{
340
341    DbgPrint (ASL_DEBUG_OUTPUT,
342        "DtInsertLabelField: Found Label : %s at output table offset %X\n",
343        Field->Value, Field->TableOffset);
344
345    Field->NextLabel = Gbl_LabelList;
346    Gbl_LabelList = Field;
347}
348
349
350/******************************************************************************
351 *
352 * FUNCTION:    DtLookupLabel
353 *
354 * PARAMETERS:  Name                - Label to be resolved
355 *
356 * RETURN:      Field object associated with the label
357 *
358 * DESCRIPTION: Lookup a label in the global label list. Used during the
359 *              resolution of integer expressions.
360 *
361 *****************************************************************************/
362
363static DT_FIELD *
364DtLookupLabel (
365    char                    *Name)
366{
367    DT_FIELD                *LabelField;
368
369
370    /* Skip a leading $ */
371
372    if (*Name == '$')
373    {
374        Name++;
375    }
376
377    /* Search global list */
378
379    LabelField = Gbl_LabelList;
380    while (LabelField)
381    {
382        if (!ACPI_STRCMP (Name, LabelField->Value))
383        {
384            return (LabelField);
385        }
386        LabelField = LabelField->NextLabel;
387    }
388
389    return (NULL);
390}
391