1 /****************************************************************************** 2 * 3 * Module Name: dtexpress.c - Support for integer expressions and labels 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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 151 Result = LeftValue / RightValue; 152 break; 153 154 case EXPOP_MODULO: 155 156 if (!RightValue) 157 { 158 DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 159 Gbl_CurrentField, NULL); 160 return (0); 161 } 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 (!strcmp (Name, LabelField->Value)) 419 { 420 return (LabelField); 421 } 422 423 LabelField = LabelField->NextLabel; 424 } 425 426 return (NULL); 427 } 428