BaseTool/VfrCompiler: Support Bit fields in EFI/Buffer VarStore

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=545

Enhance VfrCompiler to parse following case:
1. EFI/Buffer VarStore can contain bit fields in their structure.
2. For question Oneof/Checkbox/numeric, their storage can be
   bit fields of an EFI VarStore/Buffer VarStore.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Dandan Bi 2017-08-23 16:27:26 +08:00 committed by Eric Dong
parent 2b7f3d4a6b
commit 42c808d4cb
8 changed files with 1200 additions and 494 deletions

View File

@ -1,7 +1,7 @@
/** @file
EDK II specific HII relative definition.
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
@ -212,10 +212,28 @@ typedef struct _EFI_IFR_GUID_VAREQNAME {
UINT16 NameId;
} EFI_IFR_GUID_VAREQNAME;
///
/// EDKII implementation extension GUID, used to indaicate there are bit fields in the varstore.
///
#define EDKII_IFR_BIT_VARSTORE_GUID \
{ 0x82DDD68B, 0x9163, 0x4187, {0x9B, 0x27, 0x20, 0xA8, 0xFD, 0x60 ,0xA7, 0x1D}}
///
/// EDKII implementation extension flags, used to indaicate the disply style and bit width for bit filed storage.
/// Two high bits for display style and the low six bits for bit width.
///
#define EDKII_IFR_DISPLAY_BIT 0xC0
#define EDKII_IFR_DISPLAY_INT_DEC_BIT 0x00
#define EDKII_IFR_DISPLAY_UINT_DEC_BIT 0x40
#define EDKII_IFR_DISPLAY_UINT_HEX_BIT 0x80
#define EDKII_IFR_NUMERIC_SIZE_BIT 0x3F
#pragma pack()
extern EFI_GUID gEfiIfrTianoGuid;
extern EFI_GUID gEfiIfrFrameworkGuid;
extern EFI_GUID gEdkiiIfrBitVarStoreGuid;
#endif

View File

@ -2,7 +2,7 @@
VfrCompiler error handler.
Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -46,6 +46,7 @@ static SVFR_ERROR_HANDLE VFR_ERROR_HANDLE_TABLE [] = {
{ VFR_RETURN_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"},
{ VFR_RETURN_CONSTANT_ONLY, ": only constant is allowed in the expression"},
{ VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR, ": Varstore name is defined by more than one varstores, it can't be referred as varstore, only varstore strucure name could be used."},
{ VFR_RETURN_BIT_WIDTH_ERROR, ": bit width must be <= sizeof (type) * 8 and the max width can not > 32" },
{ VFR_RETURN_CODEUNDEFINED, ": undefined Error Code" }
};

View File

@ -2,7 +2,7 @@
VfrCompiler Error definition
Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -44,6 +44,7 @@ typedef enum {
VFR_RETURN_DEFAULT_VALUE_REDEFINED,
VFR_RETURN_CONSTANT_ONLY,
VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR,
VFR_RETURN_BIT_WIDTH_ERROR,
VFR_RETURN_CODEUNDEFINED
} EFI_VFR_RETURN_CODE;

View File

@ -2,7 +2,7 @@
The definition of CFormPkg's member function
Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -829,6 +829,9 @@ CFormPkg::DeclarePendingQuestion (
UINT32 ShrinkSize = 0;
EFI_VFR_RETURN_CODE ReturnCode;
EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID;
UINT8 LFlags;
UINT32 MaxValue;
CIfrGuid *GuidObj = NULL;
//
// Declare all questions as Numeric in DisableIf True
@ -844,14 +847,8 @@ CFormPkg::DeclarePendingQuestion (
// Declare Numeric qeustion for each undefined question.
for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
if (pNode->mFlag == PENDING) {
CIfrNumeric CNObj;
EFI_VARSTORE_INFO Info;
EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID;
CNObj.SetLineNo (LineNo);
CNObj.SetPrompt (0x0);
CNObj.SetHelp (0x0);
//
// Register this question, assume it is normal question, not date or time question
//
@ -888,7 +885,7 @@ CFormPkg::DeclarePendingQuestion (
} else {
if (VarStoreType == EFI_VFR_VARSTORE_EFI) {
ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info);
} else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER) {
} else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_BUFFER_BITS) {
VarStr = pNode->mKey;
//convert VarStr with store name to VarStr with structure name
ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (Info.mVarStoreId, &SName);
@ -897,7 +894,7 @@ CFormPkg::DeclarePendingQuestion (
NewStr[0] = '\0';
strcpy (NewStr, SName);
strcat (NewStr, VarStr + strlen (FName));
ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize);
ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize, Info.mIsBitVar);
delete[] NewStr;
}
} else {
@ -908,39 +905,63 @@ CFormPkg::DeclarePendingQuestion (
gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
return ReturnCode;
}
//
// If the storage is bit fields, create Guid opcode to wrap the numeric opcode.
//
if (Info.mIsBitVar) {
GuidObj = new CIfrGuid(0);
GuidObj->SetGuid (&gEdkiiIfrBitVarGuid);
GuidObj->SetLineNo(LineNo);
}
CIfrNumeric CNObj;
CNObj.SetLineNo (LineNo);
CNObj.SetPrompt (0x0);
CNObj.SetHelp (0x0);
CNObj.SetQuestionId (QId);
CNObj.SetVarStoreInfo (&Info);
//
// Numeric doesn't support BOOLEAN data type.
// BOOLEAN type has the same data size to UINT8.
// Set Min/Max/Step Data and flags for the question with bit fields.Min/Max/Step Data are saved as UINT32 type for bit question.
//
if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) {
Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
}
CNObj.SetFlags (0, Info.mVarType);
//
// Use maximum value not to limit the vaild value for the undefined question.
//
switch (Info.mVarType) {
case EFI_IFR_TYPE_NUM_SIZE_64:
CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0);
ShrinkSize = 0;
break;
case EFI_IFR_TYPE_NUM_SIZE_32:
CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0);
if (Info.mIsBitVar) {
MaxValue = (1 << Info.mVarTotalSize) -1;
CNObj.SetMinMaxStepData ((UINT32) 0, MaxValue, (UINT32) 0);
ShrinkSize = 12;
break;
case EFI_IFR_TYPE_NUM_SIZE_16:
CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0);
ShrinkSize = 18;
break;
case EFI_IFR_TYPE_NUM_SIZE_8:
CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0);
ShrinkSize = 21;
break;
default:
break;
LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & Info.mVarTotalSize);
CNObj.SetFlagsForBitField (0, LFlags);
} else {
//
// Numeric doesn't support BOOLEAN data type.
// BOOLEAN type has the same data size to UINT8.
//
if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) {
Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
}
CNObj.SetFlags (0, Info.mVarType);
//
// Use maximum value not to limit the vaild value for the undefined question.
//
switch (Info.mVarType) {
case EFI_IFR_TYPE_NUM_SIZE_64:
CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0);
ShrinkSize = 0;
break;
case EFI_IFR_TYPE_NUM_SIZE_32:
CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0);
ShrinkSize = 12;
break;
case EFI_IFR_TYPE_NUM_SIZE_16:
CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0);
ShrinkSize = 18;
break;
case EFI_IFR_TYPE_NUM_SIZE_8:
CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0);
ShrinkSize = 21;
break;
default:
break;
}
}
CNObj.ShrinkBinSize (ShrinkSize);
@ -956,8 +977,18 @@ CFormPkg::DeclarePendingQuestion (
//
// End for Numeric
//
CIfrEnd CEObj;
CIfrEnd CEObj;
CEObj.SetLineNo (LineNo);
//
// End for Guided opcode
//
if (GuidObj != NULL) {
CIfrEnd CEObjGuid;
CEObjGuid.SetLineNo (LineNo);
GuidObj->SetScope(1);
delete GuidObj;
GuidObj = NULL;
}
}
}

View File

@ -2,7 +2,7 @@
The definition of CFormPkg's member function
Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -567,8 +567,12 @@ public:
mMinMaxStepData->u8.Step = Step;
}
UINT64 GetMinData (UINT8 VarType) {
UINT64 GetMinData (UINT8 VarType, BOOLEAN IsBitVar) {
UINT64 MinValue = 0;
if (IsBitVar) {
MinValue = mMinMaxStepData->u32.MinValue;
return MinValue;
}
switch (VarType) {
case EFI_IFR_TYPE_NUM_SIZE_64:
MinValue = mMinMaxStepData->u64.MinValue;
@ -588,8 +592,12 @@ public:
return MinValue;
}
UINT64 GetMaxData (UINT8 VarType) {
UINT64 GetMaxData (UINT8 VarType, BOOLEAN IsBitVar) {
UINT64 MaxValue = 0;
if (IsBitVar) {
MaxValue = mMinMaxStepData->u32.MaxValue;
return MaxValue;
}
switch (VarType) {
case EFI_IFR_TYPE_NUM_SIZE_64:
MaxValue = mMinMaxStepData->u64.MaxValue;
@ -609,8 +617,12 @@ public:
return MaxValue;
}
UINT64 GetStepData (UINT8 VarType) {
UINT64 GetStepData (UINT8 VarType, BOOLEAN IsBitVar) {
UINT64 MaxValue = 0;
if (IsBitVar) {
MaxValue = mMinMaxStepData->u32.Step;
return MaxValue;
}
switch (VarType) {
case EFI_IFR_TYPE_NUM_SIZE_64:
MaxValue = mMinMaxStepData->u64.Step;
@ -1407,6 +1419,22 @@ public:
return VFR_RETURN_SUCCESS;
}
EFI_VFR_RETURN_CODE SetFlagsForBitField (IN UINT8 HFlags, IN UINT8 LFlags, BOOLEAN DisplaySettingsSpecified = FALSE) {
EFI_VFR_RETURN_CODE Ret;
Ret = CIfrQuestionHeader::SetFlags (HFlags);
if (Ret != VFR_RETURN_SUCCESS) {
return Ret;
}
if (DisplaySettingsSpecified == FALSE) {
mNumeric->Flags = LFlags | EDKII_IFR_DISPLAY_UINT_DEC_BIT;
} else {
mNumeric->Flags = LFlags;
}
return VFR_RETURN_SUCCESS;
}
UINT8 GetNumericFlags () {
return mNumeric->Flags;
}
@ -1447,6 +1475,22 @@ public:
return VFR_RETURN_SUCCESS;
}
EFI_VFR_RETURN_CODE SetFlagsForBitField (IN UINT8 HFlags, IN UINT8 LFlags) {
EFI_VFR_RETURN_CODE Ret;
Ret = CIfrQuestionHeader::SetFlags (HFlags);
if (Ret != VFR_RETURN_SUCCESS) {
return Ret;
}
if (LFlags & EFI_IFR_DISPLAY) {
mOneOf->Flags = LFlags;
} else {
mOneOf->Flags = LFlags | EDKII_IFR_DISPLAY_UINT_DEC_BIT;
}
return VFR_RETURN_SUCCESS;
}
VOID ShrinkBinSize (IN UINT16 Size) {
//
// Update the buffer size which is truly be used later.

File diff suppressed because it is too large Load Diff

View File

@ -600,6 +600,61 @@ CVfrVarDataTypeDB::ExtractStructTypeName (
return VFR_RETURN_SUCCESS;
}
/**
Check whether the DataType contain bit field.
@param TypeName The name of the type.
**/
BOOLEAN
CVfrVarDataTypeDB::DataTypeHasBitField (
IN CHAR8 *TypeName
)
{
SVfrDataType *pType = NULL;
SVfrDataField *pTmp;
GetDataType (TypeName, &pType);
for (pTmp = pType->mMembers; pTmp!= NULL; pTmp = pTmp->mNext) {
if (pTmp->mIsBitField) {
return TRUE;
}
}
return FALSE;
}
/**
Check whether the field is bit field or not.
@param VarStr Point to the field name which may contain the structure name.
**/
BOOLEAN
CVfrVarDataTypeDB::IsThisBitField (
IN CHAR8 *VarStr
)
{
CHAR8 FName[MAX_NAME_LEN];
CHAR8 TName[MAX_NAME_LEN];
UINT32 ArrayIdx;
SVfrDataType *pType = NULL;
SVfrDataField *pField = NULL;
CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS);
CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS);
while (*VarStr != '\0') {
CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS);
CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS);
pType = pField->mFieldType;
}
if (pField->mIsBitField) {
return TRUE;
} else {
return FALSE;
}
}
EFI_VFR_RETURN_CODE
CVfrVarDataTypeDB::ExtractFieldNameAndArrary (
IN CHAR8 *&VarStr,
@ -697,7 +752,8 @@ EFI_VFR_RETURN_CODE
CVfrVarDataTypeDB::GetFieldOffset (
IN SVfrDataField *Field,
IN UINT32 ArrayIdx,
OUT UINT32 &Offset
OUT UINT32 &Offset,
IN BOOLEAN IsBitField
)
{
if (Field == NULL) {
@ -729,8 +785,11 @@ CVfrVarDataTypeDB::GetFieldOffset (
// return VFR_RETURN_ERROR_ARRARY_NUM;
// }
//
Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx);
if (IsBitField) {
Offset = Field->mBitOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx) * 8;
} else {
Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx);
}
return VFR_RETURN_SUCCESS;
}
@ -749,7 +808,8 @@ CVfrVarDataTypeDB::GetFieldWidth (
UINT32
CVfrVarDataTypeDB::GetFieldSize (
IN SVfrDataField *Field,
IN UINT32 ArrayIdx
IN UINT32 ArrayIdx,
IN BOOLEAN BitField
)
{
if (Field == NULL) {
@ -757,9 +817,13 @@ CVfrVarDataTypeDB::GetFieldSize (
}
if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum != 0)) {
return Field->mFieldType->mTotalSize * Field->mArrayNum;
return Field->mFieldType->mTotalSize * Field->mArrayNum;
} else {
return Field->mFieldType->mTotalSize;
if (BitField) {
return Field->mBitWidth;
} else {
return Field->mFieldType->mTotalSize;
}
}
}
@ -788,18 +852,21 @@ CVfrVarDataTypeDB::InternalTypesListInit (
pYearField->mOffset = 0;
pYearField->mNext = pMonthField;
pYearField->mArrayNum = 0;
pYearField->mIsBitField = FALSE;
strcpy (pMonthField->mFieldName, "Month");
GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType);
pMonthField->mOffset = 2;
pMonthField->mNext = pDayField;
pMonthField->mArrayNum = 0;
pMonthField->mIsBitField = FALSE;
strcpy (pDayField->mFieldName, "Day");
GetDataType ((CHAR8 *)"UINT8", &pDayField->mFieldType);
pDayField->mOffset = 3;
pDayField->mNext = NULL;
pDayField->mArrayNum = 0;
pDayField->mIsBitField = FALSE;
New->mMembers = pYearField;
} else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_TIME") == 0) {
@ -812,18 +879,21 @@ CVfrVarDataTypeDB::InternalTypesListInit (
pHoursField->mOffset = 0;
pHoursField->mNext = pMinutesField;
pHoursField->mArrayNum = 0;
pHoursField->mIsBitField = FALSE;
strcpy (pMinutesField->mFieldName, "Minutes");
GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType);
pMinutesField->mOffset = 1;
pMinutesField->mNext = pSecondsField;
pMinutesField->mArrayNum = 0;
pMinutesField->mIsBitField = FALSE;
strcpy (pSecondsField->mFieldName, "Seconds");
GetDataType ((CHAR8 *)"UINT8", &pSecondsField->mFieldType);
pSecondsField->mOffset = 2;
pSecondsField->mNext = NULL;
pSecondsField->mArrayNum = 0;
pSecondsField->mIsBitField = FALSE;
New->mMembers = pHoursField;
} else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_REF") == 0) {
@ -837,24 +907,28 @@ CVfrVarDataTypeDB::InternalTypesListInit (
pQuestionIdField->mOffset = 0;
pQuestionIdField->mNext = pFormIdField;
pQuestionIdField->mArrayNum = 0;
pQuestionIdField->mIsBitField = FALSE;
strcpy (pFormIdField->mFieldName, "FormId");
GetDataType ((CHAR8 *)"UINT16", &pFormIdField->mFieldType);
pFormIdField->mOffset = 2;
pFormIdField->mNext = pFormSetGuidField;
pFormIdField->mArrayNum = 0;
pFormIdField->mIsBitField = FALSE;
strcpy (pFormSetGuidField->mFieldName, "FormSetGuid");
GetDataType ((CHAR8 *)"EFI_GUID", &pFormSetGuidField->mFieldType);
pFormSetGuidField->mOffset = 4;
pFormSetGuidField->mNext = pDevicePathField;
pFormSetGuidField->mArrayNum = 0;
pFormSetGuidField->mIsBitField = FALSE;
strcpy (pDevicePathField->mFieldName, "DevicePath");
GetDataType ((CHAR8 *)"EFI_STRING_ID", &pDevicePathField->mFieldType);
pDevicePathField->mOffset = 20;
pDevicePathField->mNext = NULL;
pDevicePathField->mArrayNum = 0;
pDevicePathField->mIsBitField = FALSE;
New->mMembers = pQuestionIdField;
} else {
@ -978,6 +1052,7 @@ CVfrVarDataTypeDB::DeclareDataTypeBegin (
pNewType->mTotalSize = 0;
pNewType->mMembers = NULL;
pNewType->mNext = NULL;
pNewType->mHasBitField = FALSE;
mNewDataType = pNewType;
}
@ -1009,6 +1084,125 @@ CVfrVarDataTypeDB::SetNewTypeName (
return VFR_RETURN_SUCCESS;
}
/**
Record the bit field info in the data type.
@param FieldName Point to the field name.
@param TypeName Point to the type name.
@param Width The bit width.
@param FieldInUnion The filed is in Union type or Structure type.
**/
EFI_VFR_RETURN_CODE
CVfrVarDataTypeDB::DataTypeAddBitField (
IN CHAR8 *FieldName,
IN CHAR8 *TypeName,
IN UINT32 Width,
IN BOOLEAN FieldInUnion
)
{
SVfrDataField *pNewField = NULL;
SVfrDataType *pFieldType = NULL;
SVfrDataField *pTmp;
UINT32 Align;
UINT32 MaxDataTypeSize;
BOOLEAN UpdateTotalSize;
CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS);
if (Width > MAX_BIT_WIDTH) {
return VFR_RETURN_BIT_WIDTH_ERROR;
}
if (Width > pFieldType->mTotalSize * 8) {
return VFR_RETURN_BIT_WIDTH_ERROR;
}
if (FieldName != NULL && strlen (FieldName) >= MAX_NAME_LEN) {
return VFR_RETURN_INVALID_PARAMETER;
}
if (Width == 0 && FieldName != NULL) {
return VFR_RETURN_INVALID_PARAMETER;
}
for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) {
if (FieldName != NULL && strcmp (pTmp->mFieldName, FieldName) == 0) {
return VFR_RETURN_REDEFINED;
}
}
Align = MIN (mPackAlign, pFieldType->mAlign);
UpdateTotalSize = FALSE;
if ((pNewField = new SVfrDataField) == NULL) {
return VFR_RETURN_OUT_FOR_RESOURCES;
}
MaxDataTypeSize = mNewDataType->mTotalSize;
if (FieldName != NULL) {
strcpy (pNewField->mFieldName, FieldName);
}
pNewField->mFieldType = pFieldType;
pNewField->mIsBitField = TRUE;
pNewField->mBitWidth = Width;
pNewField->mArrayNum = 0;
pNewField->mBitOffset = 0;
pNewField->mOffset = 0;
if (mNewDataType->mMembers == NULL) {
mNewDataType->mMembers = pNewField;
pNewField->mNext = NULL;
} else {
for (pTmp = mNewDataType->mMembers; pTmp->mNext != NULL; pTmp = pTmp->mNext)
;
pTmp->mNext = pNewField;
pNewField->mNext = NULL;
}
if (FieldInUnion) {
pNewField->mOffset = 0;
if (MaxDataTypeSize < pNewField->mFieldType->mTotalSize) {
mNewDataType->mTotalSize = pNewField->mFieldType->mTotalSize;
}
} else {
//
// Check whether the bit fileds can be contained within one FieldType.
//
if (pTmp != NULL && pTmp->mIsBitField && strcmp (pTmp->mFieldType->mTypeName, pNewField->mFieldType->mTypeName) == 0 &&
(pTmp->mBitOffset - pTmp->mOffset * 8) + pTmp->mBitWidth + pNewField->mBitWidth <= pNewField->mFieldType->mTotalSize * 8) {
pNewField->mBitOffset = pTmp->mBitOffset + pTmp->mBitWidth;
pNewField->mOffset = pTmp->mOffset;
//
// If BitWidth=0,used to force alignment at the next word boundary.
// So make this bit field occupy the remaing bit width of current field type.
//
if (pNewField->mBitWidth == 0) {
pNewField->mBitWidth = pNewField->mFieldType->mTotalSize * 8 - (pNewField->mBitOffset - pTmp->mOffset * 8);
}
} else {
//
// The bit filed start a new memory
//
pNewField->mBitOffset = mNewDataType->mTotalSize * 8;
UpdateTotalSize = TRUE;
}
}
if (UpdateTotalSize){
if ((mNewDataType->mTotalSize % Align) == 0) {
pNewField->mOffset = mNewDataType->mTotalSize;
} else {
pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align);
}
mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize);
}
mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign));
mNewDataType->mHasBitField = TRUE;
return VFR_RETURN_SUCCESS;
}
EFI_VFR_RETURN_CODE
CVfrVarDataTypeDB::DataTypeAddField (
IN CHAR8 *FieldName,
@ -1044,6 +1238,7 @@ CVfrVarDataTypeDB::DataTypeAddField (
strcpy (pNewField->mFieldName, FieldName);
pNewField->mFieldType = pFieldType;
pNewField->mArrayNum = ArrayNum;
pNewField->mIsBitField = FALSE;
if ((mNewDataType->mTotalSize % Align) == 0) {
pNewField->mOffset = mNewDataType->mTotalSize;
} else {
@ -1183,21 +1378,26 @@ CVfrVarDataTypeDB::GetDataFieldInfo (
IN CHAR8 *VarStr,
OUT UINT16 &Offset,
OUT UINT8 &Type,
OUT UINT32 &Size
OUT UINT32 &Size,
OUT BOOLEAN &BitField
)
{
CHAR8 TName[MAX_NAME_LEN], FName[MAX_NAME_LEN];
UINT32 ArrayIdx, Tmp;
SVfrDataType *pType = NULL;
SVfrDataField *pField = NULL;
CHAR8 *VarStrName;
Offset = 0;
Type = EFI_IFR_TYPE_OTHER;
Size = 0;
VarStrName = VarStr;
CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS);
CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS);
BitField = IsThisBitField (VarStrName);
//
// if it is not struct data type
//
@ -1205,13 +1405,17 @@ CVfrVarDataTypeDB::GetDataFieldInfo (
Size = pType->mTotalSize;
while (*VarStr != '\0') {
CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS);
CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS);
CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS);
pType = pField->mFieldType;
CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp), VFR_RETURN_SUCCESS);
Offset = (UINT16) (Offset + Tmp);
CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp, pField->mIsBitField), VFR_RETURN_SUCCESS);
if (BitField && !pField->mIsBitField) {
Offset = (UINT16) (Offset + Tmp * 8);
} else {
Offset = (UINT16) (Offset + Tmp);
}
Type = GetFieldWidth (pField);
Size = GetFieldSize (pField, ArrayIdx);
Size = GetFieldSize (pField, ArrayIdx, BitField);
}
return VFR_RETURN_SUCCESS;
}
@ -1360,6 +1564,7 @@ SVfrVarStorageNode::SVfrVarStorageNode (
IN CHAR8 *StoreName,
IN EFI_VARSTORE_ID VarStoreId,
IN SVfrDataType *DataType,
IN BOOLEAN BitsVarstore,
IN BOOLEAN Flag
)
{
@ -1376,7 +1581,11 @@ SVfrVarStorageNode::SVfrVarStorageNode (
}
mNext = NULL;
mVarStoreId = VarStoreId;
mVarStoreType = EFI_VFR_VARSTORE_BUFFER;
if (BitsVarstore) {
mVarStoreType = EFI_VFR_VARSTORE_BUFFER_BITS;
} else {
mVarStoreType = EFI_VFR_VARSTORE_BUFFER;
}
mStorageInfo.mDataType = DataType;
mAssignedFlag = Flag;
}
@ -1648,6 +1857,7 @@ CVfrDataStorage::DeclareBufferVarStore (
IN CVfrVarDataTypeDB *DataTypeDB,
IN CHAR8 *TypeName,
IN EFI_VARSTORE_ID VarStoreId,
IN BOOLEAN IsBitVarStore,
IN BOOLEAN Flag
)
{
@ -1674,7 +1884,7 @@ CVfrDataStorage::DeclareBufferVarStore (
MarkVarStoreIdUsed (VarStoreId);
}
if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, Flag)) == NULL) {
if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, IsBitVarStore, Flag)) == NULL) {
return VFR_RETURN_OUT_FOR_RESOURCES;
}
@ -2388,6 +2598,7 @@ EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
mInfo.mVarOffset = EFI_VAROFFSET_INVALID;
mVarType = EFI_IFR_TYPE_OTHER;
mVarTotalSize = 0;
mIsBitVar = FALSE;
}
EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
@ -2399,6 +2610,7 @@ EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
mInfo.mVarOffset = Info.mInfo.mVarOffset;
mVarType = Info.mVarType;
mVarTotalSize = Info.mVarTotalSize;
mIsBitVar = Info.mIsBitVar;
}
EFI_VARSTORE_INFO&
@ -2412,6 +2624,7 @@ EFI_VARSTORE_INFO::operator= (
mInfo.mVarOffset = Info.mInfo.mVarOffset;
mVarType = Info.mVarType;
mVarTotalSize = Info.mVarTotalSize;
mIsBitVar = Info.mIsBitVar;
}
return *this;
@ -2426,7 +2639,8 @@ EFI_VARSTORE_INFO::operator == (
(mInfo.mVarName == Info->mInfo.mVarName) &&
(mInfo.mVarOffset == Info->mInfo.mVarOffset) &&
(mVarType == Info->mVarType) &&
(mVarTotalSize == Info->mVarTotalSize)) {
(mVarTotalSize == Info->mVarTotalSize) &&
(mIsBitVar == Info->mIsBitVar)) {
return TRUE;
}

View File

@ -22,7 +22,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "VfrError.h"
extern BOOLEAN VfrCompatibleMode;
static EFI_GUID gEdkiiIfrBitVarGuid = EDKII_IFR_BIT_VARSTORE_GUID;
#define MAX_BIT_WIDTH 32
#define MAX_NAME_LEN 64
#define MAX_STRING_LEN 0x100
#define DEFAULT_ALIGN 1
@ -116,6 +118,9 @@ struct SVfrDataField {
SVfrDataType *mFieldType;
UINT32 mOffset;
UINT32 mArrayNum;
BOOLEAN mIsBitField;
UINT8 mBitWidth;
UINT32 mBitOffset;
SVfrDataField *mNext;
};
@ -124,6 +129,7 @@ struct SVfrDataType {
UINT8 mType;
UINT32 mAlign;
UINT32 mTotalSize;
BOOLEAN mHasBitField;
SVfrDataField *mMembers;
SVfrDataType *mNext;
};
@ -195,9 +201,9 @@ private:
EFI_VFR_RETURN_CODE ExtractStructTypeName (IN CHAR8 *&, OUT CHAR8 *);
EFI_VFR_RETURN_CODE GetTypeField (IN CONST CHAR8 *, IN SVfrDataType *, IN SVfrDataField *&);
EFI_VFR_RETURN_CODE GetFieldOffset (IN SVfrDataField *, IN UINT32, OUT UINT32 &);
EFI_VFR_RETURN_CODE GetFieldOffset (IN SVfrDataField *, IN UINT32, OUT UINT32 &, IN BOOLEAN);
UINT8 GetFieldWidth (IN SVfrDataField *);
UINT32 GetFieldSize (IN SVfrDataField *, IN UINT32);
UINT32 GetFieldSize (IN SVfrDataField *, IN UINT32, IN BOOLEAN);
public:
CVfrVarDataTypeDB (VOID);
@ -206,15 +212,18 @@ public:
VOID DeclareDataTypeBegin (VOID);
EFI_VFR_RETURN_CODE SetNewTypeName (IN CHAR8 *);
EFI_VFR_RETURN_CODE DataTypeAddField (IN CHAR8 *, IN CHAR8 *, IN UINT32, IN BOOLEAN);
EFI_VFR_RETURN_CODE DataTypeAddBitField (IN CHAR8 *, IN CHAR8 *, IN UINT32, IN BOOLEAN);
VOID DeclareDataTypeEnd (VOID);
EFI_VFR_RETURN_CODE GetDataType (IN CHAR8 *, OUT SVfrDataType **);
EFI_VFR_RETURN_CODE GetDataTypeSize (IN CHAR8 *, OUT UINT32 *);
EFI_VFR_RETURN_CODE GetDataTypeSize (IN UINT8, OUT UINT32 *);
EFI_VFR_RETURN_CODE GetDataFieldInfo (IN CHAR8 *, OUT UINT16 &, OUT UINT8 &, OUT UINT32 &);
EFI_VFR_RETURN_CODE GetDataFieldInfo (IN CHAR8 *, OUT UINT16 &, OUT UINT8 &, OUT UINT32 &, OUT BOOLEAN &);
EFI_VFR_RETURN_CODE GetUserDefinedTypeNameList (OUT CHAR8 ***, OUT UINT32 *);
EFI_VFR_RETURN_CODE ExtractFieldNameAndArrary (IN CHAR8 *&, OUT CHAR8 *, OUT UINT32 &);
BOOLEAN DataTypeHasBitField (IN CHAR8 *);
BOOLEAN IsThisBitField (IN CHAR8 *);
BOOLEAN IsTypeNameDefined (IN CHAR8 *);
@ -238,7 +247,8 @@ typedef enum {
EFI_VFR_VARSTORE_INVALID,
EFI_VFR_VARSTORE_BUFFER,
EFI_VFR_VARSTORE_EFI,
EFI_VFR_VARSTORE_NAME
EFI_VFR_VARSTORE_NAME,
EFI_VFR_VARSTORE_BUFFER_BITS
} EFI_VFR_VARSTORE_TYPE;
struct SVfrVarStorageNode {
@ -268,7 +278,7 @@ struct SVfrVarStorageNode {
public:
SVfrVarStorageNode (IN EFI_GUID *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN EFI_STRING_ID, IN UINT32, IN BOOLEAN Flag = TRUE);
SVfrVarStorageNode (IN EFI_GUID *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN SVfrDataType *, IN BOOLEAN Flag = TRUE);
SVfrVarStorageNode (IN EFI_GUID *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN SVfrDataType *,IN BOOLEAN, IN BOOLEAN Flag = TRUE);
SVfrVarStorageNode (IN CHAR8 *, IN EFI_VARSTORE_ID);
~SVfrVarStorageNode (VOID);
@ -285,6 +295,7 @@ struct EFI_VARSTORE_INFO {
} mInfo;
UINT8 mVarType;
UINT32 mVarTotalSize;
BOOLEAN mIsBitVar;
EFI_VARSTORE_INFO (VOID);
EFI_VARSTORE_INFO (IN EFI_VARSTORE_INFO &);
@ -343,7 +354,7 @@ public:
EFI_VFR_RETURN_CODE DeclareEfiVarStore (IN CHAR8 *, IN EFI_GUID *, IN EFI_STRING_ID, IN UINT32, IN BOOLEAN Flag = TRUE);
EFI_VFR_RETURN_CODE DeclareBufferVarStore (IN CHAR8 *, IN EFI_GUID *, IN CVfrVarDataTypeDB *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN BOOLEAN Flag = TRUE);
EFI_VFR_RETURN_CODE DeclareBufferVarStore (IN CHAR8 *, IN EFI_GUID *, IN CVfrVarDataTypeDB *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN BOOLEAN, IN BOOLEAN Flag = TRUE);
EFI_VFR_RETURN_CODE GetVarStoreId (IN CHAR8 *, OUT EFI_VARSTORE_ID *, IN EFI_GUID *VarGuid = NULL);
EFI_VFR_VARSTORE_TYPE GetVarStoreType (IN EFI_VARSTORE_ID);