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