1 /******************************************************************************
   2  *
   3  * Module Name: dtexpress.c - Support for integer expressions and labels
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 #define __DTEXPRESS_C__
  45 
  46 #include "aslcompiler.h"
  47 #include "dtcompiler.h"
  48 #include "dtparser.y.h"
  49 
  50 #define _COMPONENT          DT_COMPILER
  51         ACPI_MODULE_NAME    ("dtexpress")
  52 
  53 
  54 /* Local prototypes */
  55 
  56 static void
  57 DtInsertLabelField (
  58     DT_FIELD                *Field);
  59 
  60 static DT_FIELD *
  61 DtLookupLabel (
  62     char                    *Name);
  63 
  64 /* Global used for errors during parse and related functions */
  65 
  66 DT_FIELD                *Gbl_CurrentField;
  67 
  68 
  69 /******************************************************************************
  70  *
  71  * FUNCTION:    DtResolveIntegerExpression
  72  *
  73  * PARAMETERS:  Field               - Field object with Integer expression
  74  *              ReturnValue         - Where the integer is returned
  75  *
  76  * RETURN:      Status, and the resolved 64-bit integer value
  77  *
  78  * DESCRIPTION: Resolve an integer expression to a single value. Supports
  79  *              both integer constants and labels.
  80  *
  81  *****************************************************************************/
  82 
  83 ACPI_STATUS
  84 DtResolveIntegerExpression (
  85     DT_FIELD                *Field,
  86     UINT64                  *ReturnValue)
  87 {
  88     UINT64                  Result;
  89 
  90 
  91     DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n",
  92         Field->Value);
  93 
  94     Gbl_CurrentField = Field;
  95 
  96     Result = DtEvaluateExpression (Field->Value);
  97     *ReturnValue = Result;
  98     return (AE_OK);
  99 }
 100 
 101 
 102 /******************************************************************************
 103  *
 104  * FUNCTION:    DtDoOperator
 105  *
 106  * PARAMETERS:  LeftValue           - First 64-bit operand
 107  *              Operator            - Parse token for the operator (EXPOP_*)
 108  *              RightValue          - Second 64-bit operand
 109  *
 110  * RETURN:      64-bit result of the requested operation
 111  *
 112  * DESCRIPTION: Perform the various 64-bit integer math functions
 113  *
 114  *****************************************************************************/
 115 
 116 UINT64
 117 DtDoOperator (
 118     UINT64                  LeftValue,
 119     UINT32                  Operator,
 120     UINT64                  RightValue)
 121 {
 122     UINT64                  Result;
 123 
 124 
 125     /* Perform the requested operation */
 126 
 127     switch (Operator)
 128     {
 129     case EXPOP_ONES_COMPLIMENT:
 130 
 131         Result = ~RightValue;
 132         break;
 133 
 134     case EXPOP_LOGICAL_NOT:
 135 
 136         Result = !RightValue;
 137         break;
 138 
 139     case EXPOP_MULTIPLY:
 140 
 141         Result = LeftValue * RightValue;
 142         break;
 143 
 144     case EXPOP_DIVIDE:
 145 
 146         if (!RightValue)
 147         {
 148             DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO,
 149                 Gbl_CurrentField, NULL);
 150             return (0);
 151         }
 152         Result = LeftValue / RightValue;
 153         break;
 154 
 155     case EXPOP_MODULO:
 156 
 157         if (!RightValue)
 158         {
 159             DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO,
 160                 Gbl_CurrentField, NULL);
 161             return (0);
 162         }
 163         Result = LeftValue % RightValue;
 164         break;
 165 
 166     case EXPOP_ADD:
 167         Result = LeftValue + RightValue;
 168         break;
 169 
 170     case EXPOP_SUBTRACT:
 171 
 172         Result = LeftValue - RightValue;
 173         break;
 174 
 175     case EXPOP_SHIFT_RIGHT:
 176 
 177         Result = LeftValue >> RightValue;
 178         break;
 179 
 180     case EXPOP_SHIFT_LEFT:
 181 
 182         Result = LeftValue << RightValue;
 183         break;
 184 
 185     case EXPOP_LESS:
 186 
 187         Result = LeftValue < RightValue;
 188         break;
 189 
 190     case EXPOP_GREATER:
 191 
 192         Result = LeftValue > RightValue;
 193         break;
 194 
 195     case EXPOP_LESS_EQUAL:
 196 
 197         Result = LeftValue <= RightValue;
 198         break;
 199 
 200     case EXPOP_GREATER_EQUAL:
 201 
 202         Result = LeftValue >= RightValue;
 203         break;
 204 
 205     case EXPOP_EQUAL:
 206 
 207         Result = LeftValue == RightValue;
 208         break;
 209 
 210     case EXPOP_NOT_EQUAL:
 211 
 212         Result = LeftValue != RightValue;
 213         break;
 214 
 215     case EXPOP_AND:
 216 
 217         Result = LeftValue & RightValue;
 218         break;
 219 
 220     case EXPOP_XOR:
 221 
 222         Result = LeftValue ^ RightValue;
 223         break;
 224 
 225     case EXPOP_OR:
 226 
 227         Result = LeftValue | RightValue;
 228         break;
 229 
 230     case EXPOP_LOGICAL_AND:
 231 
 232         Result = LeftValue && RightValue;
 233         break;
 234 
 235     case EXPOP_LOGICAL_OR:
 236 
 237         Result = LeftValue || RightValue;
 238         break;
 239 
 240    default:
 241 
 242         /* Unknown operator */
 243 
 244         DtFatal (ASL_MSG_INVALID_EXPRESSION,
 245             Gbl_CurrentField, NULL);
 246         return (0);
 247     }
 248 
 249     DbgPrint (ASL_DEBUG_OUTPUT,
 250         "IntegerEval: (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n",
 251         ACPI_FORMAT_UINT64 (LeftValue),
 252         DtGetOpName (Operator),
 253         ACPI_FORMAT_UINT64 (RightValue),
 254         ACPI_FORMAT_UINT64 (Result));
 255 
 256     return (Result);
 257 }
 258 
 259 
 260 /******************************************************************************
 261  *
 262  * FUNCTION:    DtResolveLabel
 263  *
 264  * PARAMETERS:  LabelString         - Contains the label
 265  *
 266  * RETURN:      Table offset associated with the label
 267  *
 268  * DESCRIPTION: Lookup a lable and return its value.
 269  *
 270  *****************************************************************************/
 271 
 272 UINT64
 273 DtResolveLabel (
 274     char                    *LabelString)
 275 {
 276     DT_FIELD                *LabelField;
 277 
 278 
 279     DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString);
 280 
 281     /* Resolve a label reference to an integer (table offset) */
 282 
 283     if (*LabelString != '$')
 284     {
 285         return (0);
 286     }
 287 
 288     LabelField = DtLookupLabel (LabelString);
 289     if (!LabelField)
 290     {
 291         DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL,
 292             Gbl_CurrentField, LabelString);
 293         return (0);
 294     }
 295 
 296     /* All we need from the label is the offset in the table */
 297 
 298     DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n",
 299         LabelField->TableOffset);
 300 
 301     return (LabelField->TableOffset);
 302 }
 303 
 304 
 305 /******************************************************************************
 306  *
 307  * FUNCTION:    DtDetectAllLabels
 308  *
 309  * PARAMETERS:  FieldList           - Field object at start of generic list
 310  *
 311  * RETURN:      None
 312  *
 313  * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as
 314  *              a UEFI table.) and insert them into the global label list.
 315  *
 316  *****************************************************************************/
 317 
 318 void
 319 DtDetectAllLabels (
 320     DT_FIELD                *FieldList)
 321 {
 322     ACPI_DMTABLE_INFO       *Info;
 323     DT_FIELD                *GenericField;
 324     UINT32                  TableOffset;
 325 
 326 
 327     TableOffset = Gbl_CurrentTableOffset;
 328     GenericField = FieldList;
 329 
 330     /*
 331      * Process all "Label:" fields within the parse tree. We need
 332      * to know the offsets for all labels before we can compile
 333      * the parse tree in order to handle forward references. Traverse
 334      * tree and get/set all field lengths of all operators in order to
 335      * determine the label offsets.
 336      */
 337     while (GenericField)
 338     {
 339         Info = DtGetGenericTableInfo (GenericField->Name);
 340         if (Info)
 341         {
 342             /* Maintain table offsets */
 343 
 344             GenericField->TableOffset = TableOffset;
 345             TableOffset += DtGetFieldLength (GenericField, Info);
 346 
 347             /* Insert all labels in the global label list */
 348 
 349             if (Info->Opcode == ACPI_DMT_LABEL)
 350             {
 351                 DtInsertLabelField (GenericField);
 352             }
 353         }
 354 
 355         GenericField = GenericField->Next;
 356     }
 357 }
 358 
 359 
 360 /******************************************************************************
 361  *
 362  * FUNCTION:    DtInsertLabelField
 363  *
 364  * PARAMETERS:  Field               - Field object with Label to be inserted
 365  *
 366  * RETURN:      None
 367  *
 368  * DESCRIPTION: Insert a label field into the global label list
 369  *
 370  *****************************************************************************/
 371 
 372 static void
 373 DtInsertLabelField (
 374     DT_FIELD                *Field)
 375 {
 376 
 377     DbgPrint (ASL_DEBUG_OUTPUT,
 378         "DtInsertLabelField: Found Label : %s at output table offset %X\n",
 379         Field->Value, Field->TableOffset);
 380 
 381     Field->NextLabel = Gbl_LabelList;
 382     Gbl_LabelList = Field;
 383 }
 384 
 385 
 386 /******************************************************************************
 387  *
 388  * FUNCTION:    DtLookupLabel
 389  *
 390  * PARAMETERS:  Name                - Label to be resolved
 391  *
 392  * RETURN:      Field object associated with the label
 393  *
 394  * DESCRIPTION: Lookup a label in the global label list. Used during the
 395  *              resolution of integer expressions.
 396  *
 397  *****************************************************************************/
 398 
 399 static DT_FIELD *
 400 DtLookupLabel (
 401     char                    *Name)
 402 {
 403     DT_FIELD                *LabelField;
 404 
 405 
 406     /* Skip a leading $ */
 407 
 408     if (*Name == '$')
 409     {
 410         Name++;
 411     }
 412 
 413     /* Search global list */
 414 
 415     LabelField = Gbl_LabelList;
 416     while (LabelField)
 417     {
 418         if (!ACPI_STRCMP (Name, LabelField->Value))
 419         {
 420             return (LabelField);
 421         }
 422         LabelField = LabelField->NextLabel;
 423     }
 424 
 425     return (NULL);
 426 }