dtexpress.c revision 218590
155714Skris/****************************************************************************** 255714Skris * 355714Skris * Module Name: dtexpress.c - Support for integer expressions and labels 455714Skris * 555714Skris *****************************************************************************/ 655714Skris 755714Skris/* 8280304Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 955714Skris * All rights reserved. 1055714Skris * 1155714Skris * Redistribution and use in source and binary forms, with or without 1255714Skris * modification, are permitted provided that the following conditions 1355714Skris * are met: 1455714Skris * 1. Redistributions of source code must retain the above copyright 15280304Sjkim * notice, this list of conditions, and the following disclaimer, 1655714Skris * without modification. 1755714Skris * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1855714Skris * substantially similar to the "NO WARRANTY" disclaimer below 1955714Skris * ("Disclaimer") and any redistribution must be conditioned upon 2055714Skris * including a substantially similar Disclaimer requirement for further 2155714Skris * binary redistribution. 22280304Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 2355714Skris * of any contributors may be used to endorse or promote products derived 2455714Skris * from this software without specific prior written permission. 2555714Skris * 2655714Skris * Alternatively, this software may be distributed under the terms of the 2755714Skris * GNU General Public License ("GPL") version 2 as published by the Free 2855714Skris * Software Foundation. 2955714Skris * 3055714Skris * NO WARRANTY 3155714Skris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3255714Skris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3355714Skris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3455714Skris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3555714Skris * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37280304Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40280304Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4155714Skris * POSSIBILITY OF SUCH DAMAGES. 4255714Skris */ 4355714Skris 4455714Skris#define __DTEXPRESS_C__ 4555714Skris 4655714Skris#include <contrib/dev/acpica/compiler/aslcompiler.h> 4755714Skris#include <contrib/dev/acpica/compiler/dtcompiler.h> 4855714Skris 4955714Skris#define _COMPONENT DT_COMPILER 5055714Skris ACPI_MODULE_NAME ("dtexpress") 5155714Skris 52280304Sjkim 5355714Skris/* Local prototypes */ 5455714Skris 5555714Skrisstatic UINT64 5655714SkrisDtResolveInteger ( 5755714Skris DT_FIELD *Field, 5855714Skris char *IntegerString); 5955714Skris 6055714Skrisstatic void 6155714SkrisDtInsertLabelField ( 6255714Skris DT_FIELD *Field); 6355714Skris 6455714Skrisstatic DT_FIELD * 6555714SkrisDtLookupLabel ( 6655714Skris char *Name); 67280304Sjkim 68280304Sjkim 69280304Sjkim/****************************************************************************** 70280304Sjkim * 71280304Sjkim * FUNCTION: DtResolveIntegerExpression 7255714Skris * 7355714Skris * PARAMETERS: Field - Field object with Integer expression 74280304Sjkim * 75280304Sjkim * RETURN: A 64-bit integer value 76280304Sjkim * 77280304Sjkim * DESCRIPTION: Resolve an integer expression to a single value. Supports 78280304Sjkim * both integer constants and labels. Supported operators are: 7955714Skris * +,-,*,/,%,|,&,^ 8055714Skris * 81280304Sjkim *****************************************************************************/ 82280304Sjkim 83280304SjkimUINT64 84280304SjkimDtResolveIntegerExpression ( 85280304Sjkim DT_FIELD *Field) 86{ 87 char *IntegerString; 88 char *Operator; 89 UINT64 Value; 90 UINT64 Value2; 91 92 93 DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n", 94 Field->Value); 95 96 strcpy (MsgBuffer, Field->Value); /* Must take a copy for strtok() */ 97 98 /* Obtain and resolve the first operand */ 99 100 IntegerString = strtok (MsgBuffer, " "); 101 if (!IntegerString) 102 { 103 DtError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, Field, Field->Value); 104 return (0); 105 } 106 107 Value = DtResolveInteger (Field, IntegerString); 108 DbgPrint (ASL_DEBUG_OUTPUT, "Integer resolved to V1: %8.8X%8.8X\n", 109 ACPI_FORMAT_UINT64 (Value)); 110 111 /* 112 * Consume the entire expression string. For the rest of the 113 * expression string, values are of the form: 114 * <operator> <integer> 115 */ 116 while (1) 117 { 118 Operator = strtok (NULL, " "); 119 if (!Operator) 120 { 121 /* Normal exit */ 122 123 DbgPrint (ASL_DEBUG_OUTPUT, "Expression Resolved to: %8.8X%8.8X\n", 124 ACPI_FORMAT_UINT64 (Value)); 125 126 return (Value); 127 } 128 129 IntegerString = strtok (NULL, " "); 130 if (!IntegerString || 131 (strlen (Operator) > 1)) 132 { 133 /* No corresponding operand for operator or invalid operator */ 134 135 DtError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, Field, Field->Value); 136 return (0); 137 } 138 139 Value2 = DtResolveInteger (Field, IntegerString); 140 DbgPrint (ASL_DEBUG_OUTPUT, "Integer resolved to V2: %8.8X%8.8X\n", 141 ACPI_FORMAT_UINT64 (Value2)); 142 143 /* Perform the requested operation */ 144 145 switch (*Operator) 146 { 147 case '-': 148 Value -= Value2; 149 break; 150 151 case '+': 152 Value += Value2; 153 break; 154 155 case '*': 156 Value *= Value2; 157 break; 158 159 case '|': 160 Value |= Value2; 161 break; 162 163 case '&': 164 Value &= Value2; 165 break; 166 167 case '^': 168 Value ^= Value2; 169 break; 170 171 case '/': 172 if (!Value2) 173 { 174 DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, Field, Field->Value); 175 return (0); 176 } 177 Value /= Value2; 178 break; 179 180 case '%': 181 if (!Value2) 182 { 183 DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, Field, Field->Value); 184 return (0); 185 } 186 Value %= Value2; 187 break; 188 189 default: 190 191 /* Unknown operator */ 192 193 DtFatal (ASL_MSG_INVALID_EXPRESSION, Field, Field->Value); 194 break; 195 } 196 } 197 198 return (Value); 199} 200 201 202/****************************************************************************** 203 * 204 * FUNCTION: DtResolveInteger 205 * 206 * PARAMETERS: Field - Field object with string to be resolved 207 * IntegerString - Integer to be resolved 208 * 209 * RETURN: A 64-bit integer value 210 * 211 * DESCRIPTION: Resolve a single integer string to a value. Supports both 212 * integer constants and labels. 213 * 214 * NOTE: References to labels must begin with a dollar sign ($) 215 * 216 *****************************************************************************/ 217 218static UINT64 219DtResolveInteger ( 220 DT_FIELD *Field, 221 char *IntegerString) 222{ 223 DT_FIELD *LabelField; 224 UINT64 Value = 0; 225 char *Message = NULL; 226 ACPI_STATUS Status; 227 228 229 DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Integer: %s\n", IntegerString); 230 231 /* Resolve a label reference to an integer (table offset) */ 232 233 if (*IntegerString == '$') 234 { 235 LabelField = DtLookupLabel (IntegerString); 236 if (!LabelField) 237 { 238 DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, Field, IntegerString); 239 return (0); 240 } 241 242 /* All we need from the label is the offset in the table */ 243 244 Value = LabelField->TableOffset; 245 return (Value); 246 } 247 248 /* Convert string to an actual integer */ 249 250 Status = DtStrtoul64 (IntegerString, &Value); 251 if (ACPI_FAILURE (Status)) 252 { 253 if (Status == AE_LIMIT) 254 { 255 Message = "Constant larger than 64 bits"; 256 } 257 else if (Status == AE_BAD_CHARACTER) 258 { 259 Message = "Invalid character in constant"; 260 } 261 262 DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, Message); 263 } 264 265 return (Value); 266} 267 268 269/****************************************************************************** 270 * 271 * FUNCTION: DtDetectAllLabels 272 * 273 * PARAMETERS: FieldList - Field object at start of generic list 274 * 275 * RETURN: None 276 * 277 * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as 278 * a UEFI table.) and insert them into the global label list. 279 * 280 *****************************************************************************/ 281 282void 283DtDetectAllLabels ( 284 DT_FIELD *FieldList) 285{ 286 ACPI_DMTABLE_INFO *Info; 287 DT_FIELD *GenericField; 288 UINT32 TableOffset; 289 290 291 TableOffset = Gbl_CurrentTableOffset; 292 GenericField = FieldList; 293 294 /* 295 * Process all "Label:" fields within the parse tree. We need 296 * to know the offsets for all labels before we can compile 297 * the parse tree in order to handle forward references. Traverse 298 * tree and get/set all field lengths of all operators in order to 299 * determine the label offsets. 300 */ 301 while (GenericField) 302 { 303 Info = DtGetGenericTableInfo (GenericField->Name); 304 if (Info) 305 { 306 /* Maintain table offsets */ 307 308 GenericField->TableOffset = TableOffset; 309 TableOffset += DtGetFieldLength (GenericField, Info); 310 311 /* Insert all labels in the global label list */ 312 313 if (Info->Opcode == ACPI_DMT_LABEL) 314 { 315 DtInsertLabelField (GenericField); 316 } 317 } 318 319 GenericField = GenericField->Next; 320 } 321} 322 323 324/****************************************************************************** 325 * 326 * FUNCTION: DtInsertLabelField 327 * 328 * PARAMETERS: Field - Field object with Label to be inserted 329 * 330 * RETURN: None 331 * 332 * DESCRIPTION: Insert a label field into the global label list 333 * 334 *****************************************************************************/ 335 336static void 337DtInsertLabelField ( 338 DT_FIELD *Field) 339{ 340 341 DbgPrint (ASL_DEBUG_OUTPUT, 342 "DtInsertLabelField: Found Label : %s at output table offset %X\n", 343 Field->Value, Field->TableOffset); 344 345 Field->NextLabel = Gbl_LabelList; 346 Gbl_LabelList = Field; 347} 348 349 350/****************************************************************************** 351 * 352 * FUNCTION: DtLookupLabel 353 * 354 * PARAMETERS: Name - Label to be resolved 355 * 356 * RETURN: Field object associated with the label 357 * 358 * DESCRIPTION: Lookup a label in the global label list. Used during the 359 * resolution of integer expressions. 360 * 361 *****************************************************************************/ 362 363static DT_FIELD * 364DtLookupLabel ( 365 char *Name) 366{ 367 DT_FIELD *LabelField; 368 369 370 /* Skip a leading $ */ 371 372 if (*Name == '$') 373 { 374 Name++; 375 } 376 377 /* Search global list */ 378 379 LabelField = Gbl_LabelList; 380 while (LabelField) 381 { 382 if (!ACPI_STRCMP (Name, LabelField->Value)) 383 { 384 return (LabelField); 385 } 386 LabelField = LabelField->NextLabel; 387 } 388 389 return (NULL); 390} 391