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 <contrib/dev/acpica/compiler/aslcompiler.h> 47 #include <contrib/dev/acpica/compiler/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 } 427