dtexpress.c revision 229989
197049Speter/****************************************************************************** 2166124Srafan * 397049Speter * Module Name: dtexpress.c - Support for integer expressions and labels 497049Speter * 597049Speter *****************************************************************************/ 697049Speter 797049Speter/* 897049Speter * Copyright (C) 2000 - 2012, Intel Corp. 997049Speter * All rights reserved. 1097049Speter * 1197049Speter * Redistribution and use in source and binary forms, with or without 1297049Speter * modification, are permitted provided that the following conditions 1397049Speter * are met: 1497049Speter * 1. Redistributions of source code must retain the above copyright 1597049Speter * notice, this list of conditions, and the following disclaimer, 1697049Speter * without modification. 1797049Speter * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1897049Speter * substantially similar to the "NO WARRANTY" disclaimer below 1997049Speter * ("Disclaimer") and any redistribution must be conditioned upon 2097049Speter * including a substantially similar Disclaimer requirement for further 2197049Speter * binary redistribution. 2297049Speter * 3. Neither the names of the above-listed copyright holders nor the names 2397049Speter * of any contributors may be used to endorse or promote products derived 2497049Speter * from this software without specific prior written permission. 2597049Speter * 2697049Speter * Alternatively, this software may be distributed under the terms of the 2797049Speter * GNU General Public License ("GPL") version 2 as published by the Free 2897049Speter * Software Foundation. 2997049Speter * 3097049Speter * NO WARRANTY 3197049Speter * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3297049Speter * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3350276Speter * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3450276Speter * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3550276Speter * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3650276Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3750276Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3850276Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3950276Speter * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4050276Speter * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41166124Srafan * POSSIBILITY OF SUCH DAMAGES. 4250276Speter */ 4397049Speter 4497049Speter#define __DTEXPRESS_C__ 4597049Speter 4697049Speter#include <contrib/dev/acpica/compiler/aslcompiler.h> 4797049Speter#include <contrib/dev/acpica/compiler/dtcompiler.h> 4897049Speter#include "dtparser.y.h" 4997049Speter 5097049Speter#define _COMPONENT DT_COMPILER 5197049Speter ACPI_MODULE_NAME ("dtexpress") 5297049Speter 5397049Speter 5497049Speter/* Local prototypes */ 5597049Speter 5697049Speterstatic void 5797049SpeterDtInsertLabelField ( 5897049Speter DT_FIELD *Field); 5997049Speter 6097049Speterstatic DT_FIELD * 6197049SpeterDtLookupLabel ( 6297049Speter char *Name); 6397049Speter 6497049Speter/* Global used for errors during parse and related functions */ 6597049Speter 6697049SpeterDT_FIELD *Gbl_CurrentField; 6797049Speter 6897049Speter 6997049Speter/****************************************************************************** 7097049Speter * 7197049Speter * FUNCTION: DtResolveIntegerExpression 7297049Speter * 7397049Speter * PARAMETERS: Field - Field object with Integer expression 7497049Speter * ReturnValue - Where the integer is returned 7597049Speter * 7697049Speter * RETURN: Status, and the resolved 64-bit integer value 7797049Speter * 7897049Speter * DESCRIPTION: Resolve an integer expression to a single value. Supports 7997049Speter * both integer constants and labels. 8097049Speter * 8197049Speter *****************************************************************************/ 8297049Speter 8397049SpeterACPI_STATUS 8497049SpeterDtResolveIntegerExpression ( 8597049Speter DT_FIELD *Field, 8697049Speter UINT64 *ReturnValue) 8797049Speter{ 8897049Speter UINT64 Result; 8997049Speter 9097049Speter 9197049Speter DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n", 9297049Speter Field->Value); 9397049Speter 9497049Speter Gbl_CurrentField = Field; 9597049Speter 9697049Speter Result = DtEvaluateExpression (Field->Value); 9797049Speter *ReturnValue = Result; 9897049Speter return (AE_OK); 9997049Speter} 10097049Speter 10197049Speter 10297049Speter/****************************************************************************** 10397049Speter * 10497049Speter * FUNCTION: DtDoOperator 10597049Speter * 10697049Speter * PARAMETERS: LeftValue - First 64-bit operand 10797049Speter * Operator - Parse token for the operator (EXPOP_*) 10897049Speter * RightValue - Second 64-bit operand 10997049Speter * 11097049Speter * RETURN: 64-bit result of the requested operation 11197049Speter * 11297049Speter * DESCRIPTION: Perform the various 64-bit integer math functions 11397049Speter * 11497049Speter *****************************************************************************/ 11597049Speter 11697049SpeterUINT64 11797049SpeterDtDoOperator ( 11897049Speter UINT64 LeftValue, 11997049Speter UINT32 Operator, 12097049Speter UINT64 RightValue) 12197049Speter{ 12297049Speter UINT64 Result; 12397049Speter 12497049Speter 12597049Speter /* Perform the requested operation */ 12697049Speter 12797049Speter switch (Operator) 12897049Speter { 12997049Speter case EXPOP_ONES_COMPLIMENT: 13097049Speter Result = ~RightValue; 13197049Speter break; 13297049Speter 13397049Speter case EXPOP_LOGICAL_NOT: 13497049Speter Result = !RightValue; 13597049Speter break; 13697049Speter 13797049Speter case EXPOP_MULTIPLY: 13897049Speter Result = LeftValue * RightValue; 13997049Speter break; 14097049Speter 14197049Speter case EXPOP_DIVIDE: 14297049Speter if (!RightValue) 14397049Speter { 14497049Speter DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 14597049Speter Gbl_CurrentField, Gbl_CurrentField->Value); 14697049Speter return (0); 14797049Speter } 14897049Speter Result = LeftValue / RightValue; 14997049Speter break; 15097049Speter 15197049Speter case EXPOP_MODULO: 15297049Speter if (!RightValue) 15397049Speter { 15497049Speter DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 15597049Speter Gbl_CurrentField, Gbl_CurrentField->Value); 15697049Speter return (0); 15797049Speter } 15897049Speter Result = LeftValue % RightValue; 15997049Speter break; 16097049Speter 16197049Speter case EXPOP_ADD: 16250276Speter Result = LeftValue + RightValue; 16376726Speter break; 16497049Speter 16550276Speter case EXPOP_SUBTRACT: 16697049Speter Result = LeftValue - RightValue; 16776726Speter break; 16876726Speter 16976726Speter case EXPOP_SHIFT_RIGHT: 17076726Speter Result = LeftValue >> RightValue; 17150276Speter break; 17276726Speter 17376726Speter case EXPOP_SHIFT_LEFT: 17476726Speter Result = LeftValue << RightValue; 17576726Speter break; 17650276Speter 17750276Speter case EXPOP_LESS: 17876726Speter Result = LeftValue < RightValue; 17950276Speter break; 18076726Speter 18150276Speter case EXPOP_GREATER: 18250276Speter Result = LeftValue > RightValue; 18397049Speter break; 18497049Speter 18597049Speter case EXPOP_LESS_EQUAL: 18697049Speter Result = LeftValue <= RightValue; 18797049Speter break; 18897049Speter 18997049Speter case EXPOP_GREATER_EQUAL: 19097049Speter Result = LeftValue >= RightValue; 19197049Speter break; 19276726Speter 19397049Speter case EXPOP_EQUAL: 19497049Speter Result = LeftValue = RightValue; 19597049Speter break; 19697049Speter 19776726Speter case EXPOP_NOT_EQUAL: 19897049Speter Result = LeftValue != RightValue; 19997049Speter break; 20097049Speter 20197049Speter case EXPOP_AND: 20297049Speter Result = LeftValue & RightValue; 20397049Speter break; 20497049Speter 20597049Speter case EXPOP_XOR: 20697049Speter Result = LeftValue ^ RightValue; 20797049Speter break; 20897049Speter 20997049Speter case EXPOP_OR: 21097049Speter Result = LeftValue | RightValue; 21197049Speter break; 21297049Speter 213166124Srafan case EXPOP_LOGICAL_AND: 214166124Srafan Result = LeftValue && RightValue; 21597049Speter break; 21697049Speter 21797049Speter case EXPOP_LOGICAL_OR: 21897049Speter Result = LeftValue || RightValue; 21997049Speter break; 22097049Speter 22197049Speter default: 22297049Speter 22397049Speter /* Unknown operator */ 22497049Speter 22597049Speter DtFatal (ASL_MSG_INVALID_EXPRESSION, 22697049Speter Gbl_CurrentField, Gbl_CurrentField->Value); 22797049Speter return (0); 22897049Speter } 22997049Speter 23097049Speter DbgPrint (ASL_DEBUG_OUTPUT, 23197049Speter "IntegerEval: %s (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n", 23297049Speter Gbl_CurrentField->Value, 233166124Srafan ACPI_FORMAT_UINT64 (LeftValue), 23497049Speter DtGetOpName (Operator), 23597049Speter ACPI_FORMAT_UINT64 (RightValue), 23697049Speter ACPI_FORMAT_UINT64 (Result)); 23797049Speter 23897049Speter return (Result); 23997049Speter} 24097049Speter 24197049Speter 24297049Speter/****************************************************************************** 24397049Speter * 24497049Speter * FUNCTION: DtResolveLabel 24597049Speter * 24697049Speter * PARAMETERS: LabelString - Contains the label 24797049Speter * 24897049Speter * RETURN: Table offset associated with the label 24997049Speter * 25097049Speter * DESCRIPTION: Lookup a lable and return its value. 25197049Speter * 25297049Speter *****************************************************************************/ 25397049Speter 25497049SpeterUINT64 25597049SpeterDtResolveLabel ( 25697049Speter char *LabelString) 25797049Speter{ 25897049Speter DT_FIELD *LabelField; 25997049Speter 26097049Speter 26197049Speter DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString); 26297049Speter 26397049Speter /* Resolve a label reference to an integer (table offset) */ 26497049Speter 26597049Speter if (*LabelString != '$') 26697049Speter { 26797049Speter return (0); 26897049Speter } 269166124Srafan 27097049Speter LabelField = DtLookupLabel (LabelString); 271166124Srafan if (!LabelField) 272166124Srafan { 273166124Srafan DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, 274166124Srafan Gbl_CurrentField, LabelString); 27597049Speter return (0); 27697049Speter } 27797049Speter 27897049Speter /* All we need from the label is the offset in the table */ 27997049Speter 28097049Speter DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n", 28197049Speter LabelField->TableOffset); 28297049Speter 28397049Speter return (LabelField->TableOffset); 28497049Speter} 28597049Speter 28697049Speter 28797049Speter/****************************************************************************** 28897049Speter * 28997049Speter * FUNCTION: DtDetectAllLabels 29097049Speter * 29197049Speter * PARAMETERS: FieldList - Field object at start of generic list 29297049Speter * 29397049Speter * RETURN: None 29497049Speter * 29597049Speter * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as 29697049Speter * a UEFI table.) and insert them into the global label list. 29797049Speter * 29897049Speter *****************************************************************************/ 29997049Speter 30097049Spetervoid 30197049SpeterDtDetectAllLabels ( 30297049Speter DT_FIELD *FieldList) 30397049Speter{ 30497049Speter ACPI_DMTABLE_INFO *Info; 30597049Speter DT_FIELD *GenericField; 30697049Speter UINT32 TableOffset; 30797049Speter 30897049Speter 30997049Speter TableOffset = Gbl_CurrentTableOffset; 31097049Speter GenericField = FieldList; 31197049Speter 31297049Speter /* 31397049Speter * Process all "Label:" fields within the parse tree. We need 31497049Speter * to know the offsets for all labels before we can compile 31597049Speter * the parse tree in order to handle forward references. Traverse 31697049Speter * tree and get/set all field lengths of all operators in order to 31797049Speter * determine the label offsets. 31897049Speter */ 31997049Speter while (GenericField) 32097049Speter { 32197049Speter Info = DtGetGenericTableInfo (GenericField->Name); 32297049Speter if (Info) 32397049Speter { 32497049Speter /* Maintain table offsets */ 32597049Speter 32697049Speter GenericField->TableOffset = TableOffset; 32797049Speter TableOffset += DtGetFieldLength (GenericField, Info); 32897049Speter 32997049Speter /* Insert all labels in the global label list */ 33097049Speter 33197049Speter if (Info->Opcode == ACPI_DMT_LABEL) 33297049Speter { 33397049Speter DtInsertLabelField (GenericField); 33497049Speter } 33597049Speter } 33697049Speter 33797049Speter GenericField = GenericField->Next; 33897049Speter } 33997049Speter} 34097049Speter 34197049Speter 34297049Speter/****************************************************************************** 34397049Speter * 34497049Speter * FUNCTION: DtInsertLabelField 34597049Speter * 34697049Speter * PARAMETERS: Field - Field object with Label to be inserted 34750276Speter * 34850276Speter * RETURN: None 34976726Speter * 35076726Speter * DESCRIPTION: Insert a label field into the global label list 35176726Speter * 35276726Speter *****************************************************************************/ 35376726Speter 35476726Speterstatic void 35576726SpeterDtInsertLabelField ( 35650276Speter DT_FIELD *Field) 357{ 358 359 DbgPrint (ASL_DEBUG_OUTPUT, 360 "DtInsertLabelField: Found Label : %s at output table offset %X\n", 361 Field->Value, Field->TableOffset); 362 363 Field->NextLabel = Gbl_LabelList; 364 Gbl_LabelList = Field; 365} 366 367 368/****************************************************************************** 369 * 370 * FUNCTION: DtLookupLabel 371 * 372 * PARAMETERS: Name - Label to be resolved 373 * 374 * RETURN: Field object associated with the label 375 * 376 * DESCRIPTION: Lookup a label in the global label list. Used during the 377 * resolution of integer expressions. 378 * 379 *****************************************************************************/ 380 381static DT_FIELD * 382DtLookupLabel ( 383 char *Name) 384{ 385 DT_FIELD *LabelField; 386 387 388 /* Skip a leading $ */ 389 390 if (*Name == '$') 391 { 392 Name++; 393 } 394 395 /* Search global list */ 396 397 LabelField = Gbl_LabelList; 398 while (LabelField) 399 { 400 if (!ACPI_STRCMP (Name, LabelField->Value)) 401 { 402 return (LabelField); 403 } 404 LabelField = LabelField->NextLabel; 405 } 406 407 return (NULL); 408} 409