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