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

@@ -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;
}