X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FC%2FVfrCompile%2FVfrUtilityLib.cpp;h=0fe14b0d29215213c48ee38b27e9a0c3efa40130;hp=e59fbb7743dacdbc94928eef66dc6d8d670fd44c;hb=631ffb70ebbe78b6e3f342b7ad9ab9b75f8796ae;hpb=df1780f8bf5e726a1ddf0e7459d462cf06bfa672 diff --git a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp index e59fbb7743..0fe14b0d29 100644 --- a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp +++ b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp @@ -2,8 +2,8 @@ Vfr common library functions. -Copyright (c) 2004 - 2008, Intel Corporation -All rights reserved. This program and the accompanying materials +Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.
+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 http://opensource.org/licenses/bsd-license.php @@ -15,16 +15,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "stdio.h" #include "stdlib.h" +#include "CommonLib.h" #include "VfrUtilityLib.h" #include "VfrFormPkg.h" VOID CVfrBinaryOutput::WriteLine ( - IN FILE *pFile, - IN UINT32 LineBytes, - IN CHAR8 *LineHeader, - IN CHAR8 *BlkBuf, - IN UINT32 BlkSize + IN FILE *pFile, + IN UINT32 LineBytes, + IN CONST CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize ) { UINT32 Index; @@ -43,11 +44,11 @@ CVfrBinaryOutput::WriteLine ( VOID CVfrBinaryOutput::WriteEnd ( - IN FILE *pFile, - IN UINT32 LineBytes, - IN CHAR8 *LineHeader, - IN CHAR8 *BlkBuf, - IN UINT32 BlkSize + IN FILE *pFile, + IN UINT32 LineBytes, + IN CONST CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize ) { UINT32 Index; @@ -109,6 +110,10 @@ SConfigInfo::SConfigInfo ( case EFI_IFR_TYPE_STRING : memcpy (mValue, &Value.string, mWidth); break; + case EFI_IFR_TYPE_BUFFER : + memcpy (mValue, &Value.u8, mWidth); + break; + case EFI_IFR_TYPE_OTHER : return; } @@ -118,16 +123,18 @@ SConfigInfo::~SConfigInfo ( VOID ) { - BUFFER_SAFE_FREE (mValue); + ARRAY_SAFE_FREE (mValue); } SConfigItem::SConfigItem ( IN CHAR8 *Name, + IN EFI_GUID *Guid, IN CHAR8 *Id ) { mName = NULL; - mId = 0; + mGuid = NULL; + mId = NULL; mInfoStrList = NULL; mNext = NULL; @@ -137,6 +144,12 @@ SConfigItem::SConfigItem ( } } + if (Guid != NULL) { + if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) { + memcpy (mGuid, Guid, sizeof (EFI_GUID)); + } + } + if (Id != NULL) { if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) { strcpy (mId, Id); @@ -146,6 +159,7 @@ SConfigItem::SConfigItem ( SConfigItem::SConfigItem ( IN CHAR8 *Name, + IN EFI_GUID *Guid, IN CHAR8 *Id, IN UINT8 Type, IN UINT16 Offset, @@ -154,6 +168,7 @@ SConfigItem::SConfigItem ( ) { mName = NULL; + mGuid = NULL; mId = NULL; mInfoStrList = NULL; mNext = NULL; @@ -164,6 +179,12 @@ SConfigItem::SConfigItem ( } } + if (Guid != NULL) { + if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) { + memcpy (mGuid, Guid, sizeof (EFI_GUID)); + } + } + if (Id != NULL) { if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) { strcpy (mId, Id); @@ -179,8 +200,9 @@ SConfigItem::~SConfigItem ( { SConfigInfo *Info; - BUFFER_SAFE_FREE (mName); - BUFFER_SAFE_FREE (mId); + ARRAY_SAFE_FREE (mName); + ARRAY_SAFE_FREE (mGuid); + ARRAY_SAFE_FREE (mId); while (mInfoStrList != NULL) { Info = mInfoStrList; mInfoStrList = mInfoStrList->mNext; @@ -192,18 +214,20 @@ SConfigItem::~SConfigItem ( UINT8 CVfrBufferConfig::Register ( IN CHAR8 *Name, + IN EFI_GUID *Guid, IN CHAR8 *Id ) { SConfigItem *pNew; - if (Select (Name) == 0) { + if (Select (Name, Guid) == 0) { return 1; } - if ((pNew = new SConfigItem (Name, Id)) == NULL) { + if ((pNew = new SConfigItem (Name, Guid, Id)) == NULL) { return 2; } + if (mItemListHead == NULL) { mItemListHead = pNew; mItemListTail = pNew; @@ -234,18 +258,19 @@ CVfrBufferConfig::Eof( UINT8 CVfrBufferConfig::Select ( - IN CHAR8 *Name, - IN CHAR8 *Id + IN CHAR8 *Name, + IN EFI_GUID *Guid, + IN CHAR8 *Id ) { SConfigItem *p; - if (Name == NULL) { + if (Name == NULL || Guid == NULL) { mItemListPos = mItemListHead; return 0; } else { for (p = mItemListHead; p != NULL; p = p->mNext) { - if (strcmp (p->mName, Name) != 0) { + if ((strcmp (p->mName, Name) != 0) || (memcmp (p->mGuid, Guid, sizeof (EFI_GUID)) != 0)) { continue; } @@ -269,6 +294,7 @@ UINT8 CVfrBufferConfig::Write ( IN CONST CHAR8 Mode, IN CHAR8 *Name, + IN EFI_GUID *Guid, IN CHAR8 *Id, IN UINT8 Type, IN UINT16 Offset, @@ -280,14 +306,14 @@ CVfrBufferConfig::Write ( SConfigItem *pItem; SConfigInfo *pInfo; - if ((Ret = Select (Name)) != 0) { + if ((Ret = Select (Name, Guid)) != 0) { return Ret; } switch (Mode) { case 'a' : // add - if (Select (Name, Id) != 0) { - if ((pItem = new SConfigItem (Name, Id, Type, Offset, Width, Value)) == NULL) { + if (Select (Name, Guid, Id) != 0) { + if ((pItem = new SConfigItem (Name, Guid, Id, Type, Offset, (UINT16) Width, Value)) == NULL) { return 2; } if (mItemListHead == NULL) { @@ -302,10 +328,6 @@ CVfrBufferConfig::Write ( // tranverse the list to find out if there's already the value for the same offset for (pInfo = mItemListPos->mInfoStrList; pInfo != NULL; pInfo = pInfo->mNext) { if (pInfo->mOffset == Offset) { - // check if the value and width are the same; return error if not - if ((Id != NULL) && (pInfo->mWidth != Width || memcmp(pInfo->mValue, &Value, Width) != 0)) { - return VFR_RETURN_DEFAULT_VALUE_REDEFINED; - } return 0; } } @@ -455,7 +477,7 @@ CVfrBufferConfig::~CVfrBufferConfig ( CVfrBufferConfig gCVfrBufferConfig; static struct { - CHAR8 *mTypeName; + CONST CHAR8 *mTypeName; UINT8 mType; UINT32 mSize; UINT32 mAlign; @@ -468,6 +490,7 @@ static struct { {"EFI_HII_DATE", EFI_IFR_TYPE_DATE, sizeof (EFI_HII_DATE), sizeof (UINT16)}, {"EFI_STRING_ID", EFI_IFR_TYPE_STRING, sizeof (EFI_STRING_ID),sizeof (EFI_STRING_ID)}, {"EFI_HII_TIME", EFI_IFR_TYPE_TIME, sizeof (EFI_HII_TIME), sizeof (UINT8)}, + {"EFI_HII_REF", EFI_IFR_TYPE_REF, sizeof (EFI_HII_REF), sizeof (EFI_GUID)}, {NULL, EFI_IFR_TYPE_OTHER, 0, 0} }; @@ -577,6 +600,65 @@ 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); + + if (pType == NULL){ + return FALSE; + } + 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 != NULL && pField->mIsBitField) { + return TRUE; + } else { + return FALSE; + } +} + EFI_VFR_RETURN_CODE CVfrVarDataTypeDB::ExtractFieldNameAndArrary ( IN CHAR8 *&VarStr, @@ -622,6 +704,9 @@ CVfrVarDataTypeDB::ExtractFieldNameAndArrary ( if (*VarStr == ']') { VarStr++; } + if (*VarStr == '.') { + VarStr++; + } return VFR_RETURN_SUCCESS; case ']': return VFR_RETURN_DATA_STRING_ERROR; @@ -632,18 +717,32 @@ CVfrVarDataTypeDB::ExtractFieldNameAndArrary ( EFI_VFR_RETURN_CODE CVfrVarDataTypeDB::GetTypeField ( - IN CHAR8 *FName, + IN CONST CHAR8 *FName, IN SVfrDataType *Type, OUT SVfrDataField *&Field ) { SVfrDataField *pField = NULL; - if ((FName == NULL) && (Type == NULL)) { + if ((FName == NULL) || (Type == NULL)) { return VFR_RETURN_FATAL_ERROR; } for (pField = Type->mMembers; pField != NULL; pField = pField->mNext) { + // + // For type EFI_IFR_TYPE_TIME, because field name is not correctly wrote, + // add code to adjust it. + // + if (Type->mType == EFI_IFR_TYPE_TIME) { + if (strcmp (FName, "Hour") == 0) { + FName = "Hours"; + } else if (strcmp (FName, "Minute") == 0) { + FName = "Minuts"; + } else if (strcmp (FName, "Second") == 0) { + FName = "Seconds"; + } + } + if (strcmp (pField->mFieldName, FName) == 0) { Field = pField; return VFR_RETURN_SUCCESS; @@ -657,7 +756,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) { @@ -689,8 +789,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; } @@ -709,7 +812,8 @@ CVfrVarDataTypeDB::GetFieldWidth ( UINT32 CVfrVarDataTypeDB::GetFieldSize ( IN SVfrDataField *Field, - IN UINT32 ArrayIdx + IN UINT32 ArrayIdx, + IN BOOLEAN BitField ) { if (Field == NULL) { @@ -717,9 +821,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; + } } } @@ -744,22 +852,25 @@ CVfrVarDataTypeDB::InternalTypesListInit ( SVfrDataField *pDayField = new SVfrDataField; strcpy (pYearField->mFieldName, "Year"); - GetDataType ("UINT8", &pYearField->mFieldType); + GetDataType ((CHAR8 *)"UINT16", &pYearField->mFieldType); pYearField->mOffset = 0; pYearField->mNext = pMonthField; pYearField->mArrayNum = 0; + pYearField->mIsBitField = FALSE; strcpy (pMonthField->mFieldName, "Month"); - GetDataType ("UINT8", &pMonthField->mFieldType); - pMonthField->mOffset = 1; + GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType); + pMonthField->mOffset = 2; pMonthField->mNext = pDayField; pMonthField->mArrayNum = 0; + pMonthField->mIsBitField = FALSE; strcpy (pDayField->mFieldName, "Day"); - GetDataType ("UINT8", &pDayField->mFieldType); - pDayField->mOffset = 2; + 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) { @@ -768,24 +879,62 @@ CVfrVarDataTypeDB::InternalTypesListInit ( SVfrDataField *pSecondsField = new SVfrDataField; strcpy (pHoursField->mFieldName, "Hours"); - GetDataType ("UINT8", &pHoursField->mFieldType); + GetDataType ((CHAR8 *)"UINT8", &pHoursField->mFieldType); pHoursField->mOffset = 0; pHoursField->mNext = pMinutesField; pHoursField->mArrayNum = 0; + pHoursField->mIsBitField = FALSE; strcpy (pMinutesField->mFieldName, "Minutes"); - GetDataType ("UINT8", &pMinutesField->mFieldType); + GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType); pMinutesField->mOffset = 1; pMinutesField->mNext = pSecondsField; pMinutesField->mArrayNum = 0; + pMinutesField->mIsBitField = FALSE; strcpy (pSecondsField->mFieldName, "Seconds"); - GetDataType ("UINT8", &pSecondsField->mFieldType); + 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) { + SVfrDataField *pQuestionIdField = new SVfrDataField; + SVfrDataField *pFormIdField = new SVfrDataField; + SVfrDataField *pFormSetGuidField = new SVfrDataField; + SVfrDataField *pDevicePathField = new SVfrDataField; + + strcpy (pQuestionIdField->mFieldName, "QuestionId"); + GetDataType ((CHAR8 *)"UINT16", &pQuestionIdField->mFieldType); + 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 { New->mMembers = NULL; } @@ -853,7 +1002,7 @@ CVfrVarDataTypeDB::Pack ( if (Action & VFR_PACK_SHOW) { sprintf (Msg, "value of pragma pack(show) == %d", mPackAlign); - gCVfrErrorHandle.PrintMsg (LineNum, "", "Warning", Msg); + gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Warning", Msg); } if (Action & VFR_PACK_PUSH) { @@ -870,7 +1019,7 @@ CVfrVarDataTypeDB::Pack ( SVfrPackStackNode *pNode = NULL; if (mPackStack == NULL) { - gCVfrErrorHandle.PrintMsg (LineNum, "", "Warning", "#pragma pack(pop...) : more pops than pushes"); + gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "#pragma pack(pop...) : more pops than pushes"); } for (pNode = mPackStack; pNode != NULL; pNode = pNode->mNext) { @@ -884,7 +1033,7 @@ CVfrVarDataTypeDB::Pack ( if (Action & VFR_PACK_ASSIGN) { PackAlign = (Number > 1) ? Number + Number % 2 : Number; if ((PackAlign == 0) || (PackAlign > 16)) { - gCVfrErrorHandle.PrintMsg (LineNum, "", "Warning", "expected pragma parameter to be '1', '2', '4', '8', or '16'"); + gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "expected pragma parameter to be '1', '2', '4', '8', or '16'"); } else { mPackAlign = PackAlign; } @@ -907,6 +1056,7 @@ CVfrVarDataTypeDB::DeclareDataTypeBegin ( pNewType->mTotalSize = 0; pNewType->mMembers = NULL; pNewType->mNext = NULL; + pNewType->mHasBitField = FALSE; mNewDataType = pNewType; } @@ -938,19 +1088,141 @@ 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, IN CHAR8 *TypeName, - IN UINT32 ArrayNum + IN UINT32 ArrayNum, + IN BOOLEAN FieldInUnion ) { SVfrDataField *pNewField = NULL; SVfrDataType *pFieldType = NULL; SVfrDataField *pTmp; UINT32 Align; + UINT32 MaxDataTypeSize; CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS); + MaxDataTypeSize = mNewDataType->mTotalSize; if (strlen (FieldName) >= MAX_NAME_LEN) { return VFR_RETURN_INVALID_PARAMETER; @@ -970,6 +1242,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 { @@ -986,7 +1259,15 @@ CVfrVarDataTypeDB::DataTypeAddField ( } mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign)); - mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum); + + if (FieldInUnion) { + if (MaxDataTypeSize < pNewField->mFieldType->mTotalSize) { + mNewDataType->mTotalSize = pNewField->mFieldType->mTotalSize; + } + pNewField->mOffset = 0; + } else { + mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum); + } return VFR_RETURN_SUCCESS; } @@ -1101,21 +1382,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 // @@ -1123,13 +1409,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 += 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; } @@ -1257,7 +1547,7 @@ SVfrVarStorageNode::SVfrVarStorageNode ( if (Guid != NULL) { mGuid = *Guid; } else { - memset (&Guid, 0, sizeof (EFI_GUID)); + memset (&mGuid, 0, sizeof (EFI_GUID)); } if (StoreName != NULL) { mVarStoreName = new CHAR8[strlen(StoreName) + 1]; @@ -1278,13 +1568,14 @@ SVfrVarStorageNode::SVfrVarStorageNode ( IN CHAR8 *StoreName, IN EFI_VARSTORE_ID VarStoreId, IN SVfrDataType *DataType, + IN BOOLEAN BitsVarstore, IN BOOLEAN Flag ) { if (Guid != NULL) { mGuid = *Guid; } else { - memset (&Guid, 0, sizeof (EFI_GUID)); + memset (&mGuid, 0, sizeof (EFI_GUID)); } if (StoreName != NULL) { mVarStoreName = new CHAR8[strlen(StoreName) + 1]; @@ -1294,7 +1585,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; } @@ -1322,7 +1617,7 @@ SVfrVarStorageNode::~SVfrVarStorageNode ( ) { if (mVarStoreName != NULL) { - delete mVarStoreName; + delete[] mVarStoreName; } if (mVarStoreType == EFI_VFR_VARSTORE_NAME) { @@ -1348,6 +1643,8 @@ CVfrDataStorage::CVfrDataStorage ( mNameVarStoreList = NULL; mCurrVarStorageNode = NULL; mNewVarStorageNode = NULL; + mBufferFieldInfoListHead = NULL; + mBufferFieldInfoListTail = NULL; } CVfrDataStorage::~CVfrDataStorage ( @@ -1386,6 +1683,7 @@ CVfrDataStorage::GetFreeVarStoreId ( // // Assign the different ID range for the different type VarStore to support Framework Vfr // + Index = 0; if ((!VfrCompatibleMode) || (VarType == EFI_VFR_VARSTORE_BUFFER)) { Index = 0; } else if (VarType == EFI_VFR_VARSTORE_EFI) { @@ -1400,6 +1698,10 @@ CVfrDataStorage::GetFreeVarStoreId ( } } + if (Index == EFI_FREE_VARSTORE_ID_BITMAP_SIZE) { + return EFI_VARSTORE_ID_INVALID; + } + for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) { mFreeVarStoreIdBitMap[Index] |= Mask; @@ -1445,23 +1747,30 @@ CVfrDataStorage::MarkVarStoreIdUnused ( EFI_VFR_RETURN_CODE CVfrDataStorage::DeclareNameVarStoreBegin ( - IN CHAR8 *StoreName + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId ) { SVfrVarStorageNode *pNode = NULL; - EFI_VARSTORE_ID VarStoreId; + EFI_VARSTORE_ID TmpVarStoreId; if (StoreName == NULL) { return VFR_RETURN_FATAL_ERROR; } - for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - return VFR_RETURN_REDEFINED; + if (GetVarStoreId (StoreName, &TmpVarStoreId) == VFR_RETURN_SUCCESS) { + return VFR_RETURN_REDEFINED; + } + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME); + } else { + if (ChekVarStoreIdFree (VarStoreId) == FALSE) { + return VFR_RETURN_VARSTOREID_REDEFINED; } + MarkVarStoreIdUsed (VarStoreId); } - VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME); if ((pNode = new SVfrVarStorageNode (StoreName, VarStoreId)) == NULL) { return VFR_RETURN_UNDEFINED; } @@ -1530,10 +1839,8 @@ CVfrDataStorage::DeclareEfiVarStore ( return VFR_RETURN_EFIVARSTORE_SIZE_ERROR; } - for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - return VFR_RETURN_REDEFINED; - } + if (GetVarStoreId (StoreName, &VarStoreId, Guid) == VFR_RETURN_SUCCESS) { + return VFR_RETURN_REDEFINED; } VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI); @@ -1554,16 +1861,22 @@ CVfrDataStorage::DeclareBufferVarStore ( IN CVfrVarDataTypeDB *DataTypeDB, IN CHAR8 *TypeName, IN EFI_VARSTORE_ID VarStoreId, + IN BOOLEAN IsBitVarStore, IN BOOLEAN Flag ) { SVfrVarStorageNode *pNew = NULL; SVfrDataType *pDataType = NULL; + EFI_VARSTORE_ID TempVarStoreId; if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) { return VFR_RETURN_FATAL_ERROR; } + if (GetVarStoreId (StoreName, &TempVarStoreId, Guid) == VFR_RETURN_SUCCESS) { + return VFR_RETURN_REDEFINED; + } + CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS); if (VarStoreId == EFI_VARSTORE_ID_INVALID) { @@ -1575,160 +1888,274 @@ 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; } pNew->mNext = mBufferVarStoreList; mBufferVarStoreList = pNew; - if (gCVfrBufferConfig.Register(StoreName) != 0) { + if (gCVfrBufferConfig.Register(StoreName, Guid) != 0) { return VFR_RETURN_FATAL_ERROR; } return VFR_RETURN_SUCCESS; } +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetVarStoreByDataType ( + IN CHAR8 *DataTypeName, + OUT SVfrVarStorageNode **VarNode, + IN EFI_GUID *VarGuid + ) +{ + SVfrVarStorageNode *pNode; + SVfrVarStorageNode *MatchNode; + + // + // Framework VFR uses Data type name as varstore name, so don't need check again. + // + if (VfrCompatibleMode) { + return VFR_RETURN_UNDEFINED; + } + + MatchNode = NULL; + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mStorageInfo.mDataType->mTypeName, DataTypeName) != 0) { + continue; + } + + if ((VarGuid != NULL)) { + if (memcmp (VarGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) { + *VarNode = pNode; + return VFR_RETURN_SUCCESS; + } + } else { + if (MatchNode == NULL) { + MatchNode = pNode; + } else { + // + // More than one varstores referred the same data structures. + // + return VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR; + } + } + } + + if (MatchNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + *VarNode = MatchNode; + return VFR_RETURN_SUCCESS; +} + +EFI_VARSTORE_ID +CVfrDataStorage::CheckGuidField ( + IN SVfrVarStorageNode *pNode, + IN EFI_GUID *StoreGuid, + IN BOOLEAN *HasFoundOne, + OUT EFI_VFR_RETURN_CODE *ReturnCode + ) +{ + if (StoreGuid != NULL) { + // + // If has guid info, compare the guid filed. + // + if (memcmp (StoreGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) { + // + // Both name and guid are same, this this varstore. + // + mCurrVarStorageNode = pNode; + *ReturnCode = VFR_RETURN_SUCCESS; + return TRUE; + } + } else { + // + // Not has Guid field, check whether this name is the only one. + // + if (*HasFoundOne) { + // + // The name has conflict, return name redefined. + // + *ReturnCode = VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR; + return TRUE; + } + + *HasFoundOne = TRUE; + mCurrVarStorageNode = pNode; + } + + return FALSE; +} + +/** + Base on the input store name and guid to find the varstore id. + + If both name and guid are inputed, base on the name and guid to + found the varstore. If only name inputed, base on the name to + found the varstore and go on to check whether more than one varstore + has the same name. If only has found one varstore, return this + varstore; if more than one varstore has same name, return varstore + name redefined error. If no varstore found by varstore name, call + function GetVarStoreByDataType and use inputed varstore name as + data type name to search. +**/ EFI_VFR_RETURN_CODE CVfrDataStorage::GetVarStoreId ( IN CHAR8 *StoreName, - OUT EFI_VARSTORE_ID *VarStoreId + OUT EFI_VARSTORE_ID *VarStoreId, + IN EFI_GUID *StoreGuid ) { + EFI_VFR_RETURN_CODE ReturnCode; SVfrVarStorageNode *pNode; + BOOLEAN HasFoundOne = FALSE; + + mCurrVarStorageNode = NULL; for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - mCurrVarStorageNode = pNode; - *VarStoreId = pNode->mVarStoreId; - return VFR_RETURN_SUCCESS; + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } } } for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - mCurrVarStorageNode = pNode; - *VarStoreId = pNode->mVarStoreId; - return VFR_RETURN_SUCCESS; + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } } } for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - mCurrVarStorageNode = pNode; - *VarStoreId = pNode->mVarStoreId; - return VFR_RETURN_SUCCESS; + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } } } - mCurrVarStorageNode = NULL; - *VarStoreId = EFI_VARSTORE_ID_INVALID; - return VFR_RETURN_UNDEFINED; + if (HasFoundOne) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return VFR_RETURN_SUCCESS; + } + + *VarStoreId = EFI_VARSTORE_ID_INVALID; + + // + // Assume that Data strucutre name is used as StoreName, and check again. + // + ReturnCode = GetVarStoreByDataType (StoreName, &pNode, StoreGuid); + if (pNode != NULL) { + mCurrVarStorageNode = pNode; + *VarStoreId = pNode->mVarStoreId; + } + + return ReturnCode; } EFI_VFR_RETURN_CODE CVfrDataStorage::GetBufferVarStoreDataTypeName ( - IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId, OUT CHAR8 **DataTypeName ) { SVfrVarStorageNode *pNode; - if ((StoreName == NULL) || (DataTypeName == NULL)) { + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { return VFR_RETURN_FATAL_ERROR; } for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - break; + if (pNode->mVarStoreId == VarStoreId) { + *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName; + return VFR_RETURN_SUCCESS; } } - if (pNode == NULL) { - return VFR_RETURN_UNDEFINED; - } - - if (pNode->mStorageInfo.mDataType == NULL) { - return VFR_RETURN_FATAL_ERROR; - } - - *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName; - return VFR_RETURN_SUCCESS; + return VFR_RETURN_UNDEFINED; } -EFI_VFR_RETURN_CODE +EFI_VFR_VARSTORE_TYPE CVfrDataStorage::GetVarStoreType ( - IN CHAR8 *StoreName, - OUT EFI_VFR_VARSTORE_TYPE &VarStoreType + IN EFI_VARSTORE_ID VarStoreId ) { SVfrVarStorageNode *pNode; + EFI_VFR_VARSTORE_TYPE VarStoreType; - if (StoreName == NULL) { - return VFR_RETURN_FATAL_ERROR; + VarStoreType = EFI_VFR_VARSTORE_INVALID; + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + return VarStoreType; } for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (pNode->mVarStoreId == VarStoreId) { VarStoreType = pNode->mVarStoreType; - return VFR_RETURN_SUCCESS; + return VarStoreType; } } for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (pNode->mVarStoreId == VarStoreId) { VarStoreType = pNode->mVarStoreType; - return VFR_RETURN_SUCCESS; + return VarStoreType; } } for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (pNode->mVarStoreId == VarStoreId) { VarStoreType = pNode->mVarStoreType; - return VFR_RETURN_SUCCESS; + return VarStoreType; } } - VarStoreType = EFI_VFR_VARSTORE_INVALID; - return VFR_RETURN_UNDEFINED; + return VarStoreType; } -EFI_VFR_VARSTORE_TYPE -CVfrDataStorage::GetVarStoreType ( +EFI_GUID * +CVfrDataStorage::GetVarStoreGuid ( IN EFI_VARSTORE_ID VarStoreId ) { SVfrVarStorageNode *pNode; - EFI_VFR_VARSTORE_TYPE VarStoreType; + EFI_GUID *VarGuid; - VarStoreType = EFI_VFR_VARSTORE_INVALID; + VarGuid = NULL; if (VarStoreId == EFI_VARSTORE_ID_INVALID) { - return VarStoreType; + return VarGuid; } for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { if (pNode->mVarStoreId == VarStoreId) { - VarStoreType = pNode->mVarStoreType; - return VarStoreType; + VarGuid = &pNode->mGuid; + return VarGuid; } } for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { if (pNode->mVarStoreId == VarStoreId) { - VarStoreType = pNode->mVarStoreType; - return VarStoreType; + VarGuid = &pNode->mGuid; + return VarGuid; } } for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { if (pNode->mVarStoreId == VarStoreId) { - VarStoreType = pNode->mVarStoreType; - return VarStoreType; + VarGuid = &pNode->mGuid; + return VarGuid; } } - return VarStoreType; + return VarGuid; } EFI_VFR_RETURN_CODE @@ -1803,6 +2230,48 @@ CVfrDataStorage::GetEfiVarStoreInfo ( return VFR_RETURN_SUCCESS; } +EFI_VFR_RETURN_CODE +CVfrDataStorage::AddBufferVarStoreFieldInfo ( + IN EFI_VARSTORE_INFO *Info + ) +{ + BufferVarStoreFieldInfoNode *pNew; + + if ((pNew = new BufferVarStoreFieldInfoNode(Info)) == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (mBufferFieldInfoListHead == NULL) { + mBufferFieldInfoListHead = pNew; + mBufferFieldInfoListTail= pNew; + } else { + mBufferFieldInfoListTail->mNext = pNew; + mBufferFieldInfoListTail = pNew; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetBufferVarStoreFieldInfo ( + IN OUT EFI_VARSTORE_INFO *Info + ) +{ + BufferVarStoreFieldInfoNode *pNode; + + pNode = mBufferFieldInfoListHead; + while (pNode != NULL) { + if (Info->mVarStoreId == pNode->mVarStoreInfo.mVarStoreId && + Info->mInfo.mVarOffset == pNode->mVarStoreInfo.mInfo.mVarOffset) { + Info->mVarTotalSize = pNode->mVarStoreInfo.mVarTotalSize; + Info->mVarType = pNode->mVarStoreInfo.mVarType; + return VFR_RETURN_SUCCESS; + } + pNode = pNode->mNext; + } + return VFR_RETURN_FATAL_ERROR; +} + EFI_VFR_RETURN_CODE CVfrDataStorage::GetNameVarStoreInfo ( OUT EFI_VARSTORE_INFO *Info, @@ -1832,37 +2301,6 @@ CVfrDataStorage::GetNameVarStoreInfo ( return VFR_RETURN_SUCCESS; } -EFI_VFR_RETURN_CODE -CVfrDataStorage::BufferVarStoreRequestElementAdd ( - IN CHAR8 *StoreName, - IN EFI_VARSTORE_INFO &Info - ) -{ - CHAR8 NewReqElt[128] = {'\0',}; - CHAR8 *OldReqElt = NULL; - SVfrVarStorageNode *pNode = NULL; - EFI_IFR_TYPE_VALUE Value = gZeroEfiIfrTypeValue; - - for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == NULL) { - break; - } - } - - if (pNode == NULL) { - return VFR_RETURN_UNDEFINED; - } - - gCVfrBufferConfig.Open (); - Value.u8 = 0; - if (gCVfrBufferConfig.Write ('a', StoreName, NULL, EFI_IFR_TYPE_NUM_SIZE_8, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value) != 0) { - return VFR_RETURN_FATAL_ERROR; - } - gCVfrBufferConfig.Close (); - - return VFR_RETURN_SUCCESS; -} - SVfrDefaultStoreNode::SVfrDefaultStoreNode ( IN EFI_IFR_DEFAULTSTORE *ObjBinAddr, IN CHAR8 *RefName, @@ -1889,7 +2327,7 @@ SVfrDefaultStoreNode::~SVfrDefaultStoreNode ( ) { if (mRefName != NULL) { - delete mRefName; + delete[] mRefName; } } @@ -2024,90 +2462,12 @@ CVfrDefaultStore::GetDefaultId ( return VFR_RETURN_UNDEFINED; } -STATIC -EFI_VFR_RETURN_CODE -AltCfgItemPrintToBuffer ( - IN CHAR8 *NewAltCfg, - IN EFI_VARSTORE_INFO Info, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE Value - ) -{ - UINT32 Index; - UINT8 *BufChar = NULL; - UINT32 Count = 0; - - if (NewAltCfg != NULL) { - Count = sprintf ( - NewAltCfg, - "&OFFSET=%x&WIDTH=%x&VALUE=", - Info.mInfo.mVarOffset, - Info.mVarTotalSize - ); - NewAltCfg += Count; - - switch (Type) { - case EFI_IFR_TYPE_NUM_SIZE_8 : - Count = sprintf (NewAltCfg, "%x", Value.u8); - NewAltCfg += Count; - break; - case EFI_IFR_TYPE_NUM_SIZE_16 : - Count = sprintf (NewAltCfg, "%x", Value.u16); - NewAltCfg += Count; - break; - case EFI_IFR_TYPE_NUM_SIZE_32 : - Count = sprintf (NewAltCfg, "%x", Value.u32); - NewAltCfg += Count; - break; - case EFI_IFR_TYPE_NUM_SIZE_64 : - Count = sprintf (NewAltCfg, "%x", Value.u64); - NewAltCfg += Count; - break; - case EFI_IFR_TYPE_BOOLEAN : - Count = sprintf (NewAltCfg, "%x", Value.b); - NewAltCfg += Count; - break; - case EFI_IFR_TYPE_TIME : -#if 1 - Count = sprintf (NewAltCfg, "%x", *((UINT32 *)(&Value.time))); - NewAltCfg += Count; -#else - BufChar = (UINT8 *)&Value.time; - for (Index = 0; Index < sizeof(EFI_HII_TIME); Index++) { - Count = sprintf (NewAltCfg, "%02x", (UINT8)BufChar[Index]); - NewAltCfg += Count; - } -#endif - break; - case EFI_IFR_TYPE_DATE : -#if 1 - Count = sprintf (NewAltCfg, "%x", *((UINT32 *)(&Value.date))); - NewAltCfg += Count; -#else - BufChar = (UINT8 *)&Value.date; - for (Index = 0; Index < sizeof(EFI_HII_DATE); Index++) { - Count = sprintf (NewAltCfg, "%02x", (UINT8)BufChar[Index]); - NewAltCfg += Count; - } -#endif - break; - case EFI_IFR_TYPE_STRING : - Count = sprintf (NewAltCfg, "%x", Value.string); - NewAltCfg += Count; - break; - case EFI_IFR_TYPE_OTHER : - return VFR_RETURN_UNSUPPORTED; - } - } - - return VFR_RETURN_FATAL_ERROR; -} - EFI_VFR_RETURN_CODE CVfrDefaultStore::BufferVarStoreAltConfigAdd ( IN EFI_VARSTORE_ID DefaultId, IN EFI_VARSTORE_INFO &Info, IN CHAR8 *VarStoreName, + IN EFI_GUID *VarStoreGuid, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE Value ) @@ -2133,8 +2493,8 @@ CVfrDefaultStore::BufferVarStoreAltConfigAdd ( gCVfrBufferConfig.Open (); sprintf (NewAltCfg, "%04x", pNode->mDefaultId); - if ((Returnvalue = gCVfrBufferConfig.Select(VarStoreName)) == 0) { - if ((Returnvalue = gCVfrBufferConfig.Write ('a', VarStoreName, NewAltCfg, Type, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value)) != 0) { + if ((Returnvalue = gCVfrBufferConfig.Select(VarStoreName, VarStoreGuid)) == 0) { + if ((Returnvalue = gCVfrBufferConfig.Write ('a', VarStoreName, VarStoreGuid, NewAltCfg, Type, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value)) != 0) { goto WriteError; } } @@ -2169,7 +2529,7 @@ SVfrRuleNode::~SVfrRuleNode ( ) { if (mRuleName != NULL) { - delete mRuleName; + delete[] mRuleName; } } @@ -2242,6 +2602,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 ( @@ -2253,6 +2614,24 @@ EFI_VARSTORE_INFO::EFI_VARSTORE_INFO ( mInfo.mVarOffset = Info.mInfo.mVarOffset; mVarType = Info.mVarType; mVarTotalSize = Info.mVarTotalSize; + mIsBitVar = Info.mIsBitVar; +} + +EFI_VARSTORE_INFO& +EFI_VARSTORE_INFO::operator= ( + IN CONST EFI_VARSTORE_INFO &Info + ) +{ + if (this != &Info) { + mVarStoreId = Info.mVarStoreId; + mInfo.mVarName = Info.mInfo.mVarName; + mInfo.mVarOffset = Info.mInfo.mVarOffset; + mVarType = Info.mVarType; + mVarTotalSize = Info.mVarTotalSize; + mIsBitVar = Info.mIsBitVar; + } + + return *this; } BOOLEAN @@ -2264,13 +2643,34 @@ 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; } return FALSE; } +BufferVarStoreFieldInfoNode::BufferVarStoreFieldInfoNode( + IN EFI_VARSTORE_INFO *Info + ) +{ + mVarStoreInfo.mVarType = Info->mVarType; + mVarStoreInfo.mVarTotalSize = Info->mVarTotalSize; + mVarStoreInfo.mInfo.mVarOffset = Info->mInfo.mVarOffset; + mVarStoreInfo.mVarStoreId = Info->mVarStoreId; + mNext = NULL; +} + +BufferVarStoreFieldInfoNode::~BufferVarStoreFieldInfoNode () +{ + mVarStoreInfo.mVarType = EFI_IFR_TYPE_OTHER; + mVarStoreInfo.mVarTotalSize = 0; + mVarStoreInfo.mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + mVarStoreInfo.mVarStoreId = EFI_VARSTORE_ID_INVALID; + mNext = NULL; +} + static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo; EFI_QUESTION_ID @@ -2286,6 +2686,10 @@ CVfrQuestionDB::GetFreeQuestionId ( } } + if (Index == EFI_FREE_QUESTION_ID_BITMAP_SIZE) { + return EFI_QUESTION_ID_INVALID; + } + for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { if ((mFreeQIdBitMap[Index] & Mask) == 0) { mFreeQIdBitMap[Index] |= Mask; @@ -2340,6 +2744,7 @@ SVfrQuestionNode::SVfrQuestionNode ( mQuestionId = EFI_QUESTION_ID_INVALID; mBitMask = BitMask; mNext = NULL; + mQtype = QUESTION_NORMAL; if (Name == NULL) { mName = new CHAR8[strlen ("$DEFAULT") + 1]; @@ -2363,11 +2768,11 @@ SVfrQuestionNode::~SVfrQuestionNode ( ) { if (mName != NULL) { - delete mName; + delete[] mName; } if (mVarIdStr != NULL) { - delete mVarIdStr; + delete[] mVarIdStr; } } @@ -2509,6 +2914,9 @@ CVfrQuestionDB::RegisterOldDateQuestion ( pNode[0]->mQuestionId = QuestionId; pNode[1]->mQuestionId = QuestionId; pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_DATE; + pNode[1]->mQtype = QUESTION_DATE; + pNode[2]->mQtype = QUESTION_DATE; pNode[0]->mNext = pNode[1]; pNode[1]->mNext = pNode[2]; pNode[2]->mNext = mQuestionList; @@ -2541,26 +2949,54 @@ CVfrQuestionDB::RegisterNewDateQuestion ( CHAR8 *VarIdStr[3] = {NULL, }; CHAR8 Index; - if (BaseVarId == NULL) { + if (BaseVarId == NULL && Name == NULL) { + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } return; } - Len = strlen (BaseVarId); + if (BaseVarId != NULL) { + Len = strlen (BaseVarId); - VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1]; - if (VarIdStr[0] != NULL) { - strcpy (VarIdStr[0], BaseVarId); - strcat (VarIdStr[0], ".Year"); - } - VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1]; - if (VarIdStr[1] != NULL) { - strcpy (VarIdStr[1], BaseVarId); - strcat (VarIdStr[1], ".Month"); - } - VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1]; - if (VarIdStr[2] != NULL) { - strcpy (VarIdStr[2], BaseVarId); - strcat (VarIdStr[2], ".Day"); + VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".Year"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".Month"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".Day"); + } + } else { + Len = strlen (Name); + + VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], Name); + strcat (VarIdStr[0], ".Year"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], Name); + strcat (VarIdStr[1], ".Month"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], Name); + strcat (VarIdStr[2], ".Day"); + } } if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], DATE_YEAR_BITMASK)) == NULL) { @@ -2585,6 +3021,9 @@ CVfrQuestionDB::RegisterNewDateQuestion ( pNode[0]->mQuestionId = QuestionId; pNode[1]->mQuestionId = QuestionId; pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_DATE; + pNode[1]->mQtype = QUESTION_DATE; + pNode[2]->mQtype = QUESTION_DATE; pNode[0]->mNext = pNode[1]; pNode[1]->mNext = pNode[2]; pNode[2]->mNext = mQuestionList; @@ -2651,6 +3090,9 @@ CVfrQuestionDB::RegisterOldTimeQuestion ( pNode[0]->mQuestionId = QuestionId; pNode[1]->mQuestionId = QuestionId; pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_TIME; + pNode[1]->mQtype = QUESTION_TIME; + pNode[2]->mQtype = QUESTION_TIME; pNode[0]->mNext = pNode[1]; pNode[1]->mNext = pNode[2]; pNode[2]->mNext = mQuestionList; @@ -2683,26 +3125,54 @@ CVfrQuestionDB::RegisterNewTimeQuestion ( CHAR8 *VarIdStr[3] = {NULL, }; CHAR8 Index; - if (BaseVarId == NULL) { + if (BaseVarId == NULL && Name == NULL) { + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } return; } - Len = strlen (BaseVarId); + if (BaseVarId != NULL) { + Len = strlen (BaseVarId); - VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1]; - if (VarIdStr[0] != NULL) { - strcpy (VarIdStr[0], BaseVarId); - strcat (VarIdStr[0], ".Hour"); - } - VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1]; - if (VarIdStr[1] != NULL) { - strcpy (VarIdStr[1], BaseVarId); - strcat (VarIdStr[1], ".Minute"); - } - VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1]; - if (VarIdStr[2] != NULL) { - strcpy (VarIdStr[2], BaseVarId); - strcat (VarIdStr[2], ".Second"); + VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".Hour"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".Minute"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".Second"); + } + } else { + Len = strlen (Name); + + VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], Name); + strcat (VarIdStr[0], ".Hour"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], Name); + strcat (VarIdStr[1], ".Minute"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], Name); + strcat (VarIdStr[2], ".Second"); + } } if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], TIME_HOUR_BITMASK)) == NULL) { @@ -2727,6 +3197,9 @@ CVfrQuestionDB::RegisterNewTimeQuestion ( pNode[0]->mQuestionId = QuestionId; pNode[1]->mQuestionId = QuestionId; pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_TIME; + pNode[1]->mQtype = QUESTION_TIME; + pNode[2]->mQtype = QUESTION_TIME; pNode[0]->mNext = pNode[1]; pNode[1]->mNext = pNode[2]; pNode[2]->mNext = mQuestionList; @@ -2756,6 +3229,125 @@ Err: } } +VOID +CVfrQuestionDB::RegisterRefQuestion ( + IN CHAR8 *Name, + IN CHAR8 *BaseVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[4] = {NULL, }; + UINT32 Len; + CHAR8 *VarIdStr[4] = {NULL, }; + CHAR8 Index; + + if (BaseVarId == NULL && Name == NULL) { + return; + } + + if (BaseVarId != NULL) { + Len = strlen (BaseVarId); + + VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".QuestionId"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".FormId"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".FormSetGuid"); + } + VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1]; + if (VarIdStr[3] != NULL) { + strcpy (VarIdStr[3], BaseVarId); + strcat (VarIdStr[3], ".DevicePath"); + } + } else { + Len = strlen (Name); + + VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], Name); + strcat (VarIdStr[0], ".QuestionId"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], Name); + strcat (VarIdStr[1], ".FormId"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], Name); + strcat (VarIdStr[2], ".FormSetGuid"); + } + VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1]; + if (VarIdStr[3] != NULL) { + strcpy (VarIdStr[3], Name); + strcat (VarIdStr[3], ".DevicePath"); + } + } + + if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0])) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1])) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2])) == NULL) { + goto Err; + } + if ((pNode[3] = new SVfrQuestionNode (Name, VarIdStr[3])) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[3]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_REF; + pNode[1]->mQtype = QUESTION_REF; + pNode[2]->mQtype = QUESTION_REF; + pNode[3]->mQtype = QUESTION_REF; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = pNode[3]; + pNode[3]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[3], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + + Err: + for (Index = 0; Index < 4; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + + if (VarIdStr[Index] != NULL) { + delete VarIdStr[Index]; + } + } +} + EFI_VFR_RETURN_CODE CVfrQuestionDB::UpdateQuestionId ( IN EFI_QUESTION_ID QId, @@ -2800,13 +3392,17 @@ CVfrQuestionDB::GetQuestionId ( IN CHAR8 *Name, IN CHAR8 *VarIdStr, OUT EFI_QUESTION_ID &QuestionId, - OUT UINT32 &BitMask + OUT UINT32 &BitMask, + OUT EFI_QUESION_TYPE *QType ) { SVfrQuestionNode *pNode; QuestionId = EFI_QUESTION_ID_INVALID; BitMask = 0x00000000; + if (QType != NULL) { + *QType = QUESTION_NORMAL; + } if ((Name == NULL) && (VarIdStr == NULL)) { return ; @@ -2827,6 +3423,9 @@ CVfrQuestionDB::GetQuestionId ( QuestionId = pNode->mQuestionId; BitMask = pNode->mBitMask; + if (QType != NULL) { + *QType = pNode->mQtype; + } break; } @@ -2873,7 +3472,484 @@ CVfrQuestionDB::FindQuestion ( return VFR_RETURN_UNDEFINED; } +CVfrStringDB::CVfrStringDB () +{ + mStringFileName = NULL; +} + +CVfrStringDB::~CVfrStringDB () +{ + if (mStringFileName != NULL) { + delete mStringFileName; + } + mStringFileName = NULL; +} + + +VOID +CVfrStringDB::SetStringFileName(IN CHAR8 *StringFileName) +{ + UINT32 FileLen = 0; + + if (StringFileName == NULL) { + return; + } + + FileLen = strlen (StringFileName) + 1; + mStringFileName = new CHAR8[FileLen]; + if (mStringFileName == NULL) { + return; + } + + strcpy (mStringFileName, StringFileName); + mStringFileName[FileLen - 1] = '\0'; +} + + +/** + Returns TRUE or FALSE whether SupportedLanguages contains the best matching language + from a set of supported languages. + + @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that + contains a set of language codes. + @param[in] Language A variable that contains pointers to Null-terminated + ASCII strings that contain one language codes. + + @retval FALSE The best matching language could not be found in SupportedLanguages. + @retval TRUE The best matching language could be found in SupportedLanguages. + +**/ +BOOLEAN +CVfrStringDB::GetBestLanguage ( + IN CONST CHAR8 *SupportedLanguages, + IN CHAR8 *Language + ) +{ + UINTN CompareLength; + UINTN LanguageLength; + CONST CHAR8 *Supported; + + if (SupportedLanguages == NULL || Language == NULL){ + return FALSE; + } + + // + // Determine the length of the first RFC 4646 language code in Language + // + for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++); + + // + // Trim back the length of Language used until it is empty + // + while (LanguageLength > 0) { + // + // Loop through all language codes in SupportedLanguages + // + for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) { + // + // Skip ';' characters in Supported + // + for (; *Supported != '\0' && *Supported == ';'; Supported++); + // + // Determine the length of the next language code in Supported + // + for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++); + // + // If Language is longer than the Supported, then skip to the next language + // + if (LanguageLength > CompareLength) { + continue; + } + + // + // See if the first LanguageLength characters in Supported match Language + // + if (strncmp (Supported, Language, LanguageLength) == 0) { + return TRUE; + } + } + + // + // Trim Language from the right to the next '-' character + // + for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--); + } + + // + // No matches were found + // + return FALSE; +} + + +CHAR8 * +CVfrStringDB::GetVarStoreNameFormStringId ( + IN EFI_STRING_ID StringId + ) +{ + FILE *pInFile = NULL; + UINT32 NameOffset; + UINT32 Length; + UINT8 *StringPtr; + CHAR8 *StringName; + CHAR16 *UnicodeString; + CHAR8 *VarStoreName = NULL; + CHAR8 *DestTmp; + UINT8 *Current; + EFI_STATUS Status; + CHAR8 LineBuf[EFI_IFR_MAX_LENGTH]; + UINT8 BlockType; + EFI_HII_STRING_PACKAGE_HDR *PkgHeader; + + if (mStringFileName == NULL) { + return NULL; + } + + if ((pInFile = fopen (LongFilePath (mStringFileName), "rb")) == NULL) { + return NULL; + } + + // + // Get file length. + // + fseek (pInFile, 0, SEEK_END); + Length = ftell (pInFile); + fseek (pInFile, 0, SEEK_SET); + + // + // Get file data. + // + StringPtr = new UINT8[Length]; + if (StringPtr == NULL) { + fclose (pInFile); + return NULL; + } + fread ((char *)StringPtr, sizeof (UINT8), Length, pInFile); + fclose (pInFile); + + PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr; + // + // Check the String package. + // + if (PkgHeader->Header.Type != EFI_HII_PACKAGE_STRINGS) { + delete[] StringPtr; + return NULL; + } + + // + // Search the language, get best language base on RFC 4647 matching algorithm. + // + Current = StringPtr; + while (!GetBestLanguage ("en", PkgHeader->Language)) { + Current += PkgHeader->Header.Length; + PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current; + // + // If can't find string package base on language, just return the first string package. + // + if (Current - StringPtr >= Length) { + Current = StringPtr; + PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr; + break; + } + } + + Current += PkgHeader->HdrSize; + // + // Find the string block according the stringId. + // + Status = FindStringBlock(Current, StringId, &NameOffset, &BlockType); + if (Status != EFI_SUCCESS) { + delete[] StringPtr; + return NULL; + } + + // + // Get varstore name according the string type. + // + switch (BlockType) { + case EFI_HII_SIBT_STRING_SCSU: + case EFI_HII_SIBT_STRING_SCSU_FONT: + case EFI_HII_SIBT_STRINGS_SCSU: + case EFI_HII_SIBT_STRINGS_SCSU_FONT: + StringName = (CHAR8*)(Current + NameOffset); + VarStoreName = new CHAR8[strlen(StringName) + 1]; + strcpy (VarStoreName, StringName); + break; + case EFI_HII_SIBT_STRING_UCS2: + case EFI_HII_SIBT_STRING_UCS2_FONT: + case EFI_HII_SIBT_STRINGS_UCS2: + case EFI_HII_SIBT_STRINGS_UCS2_FONT: + UnicodeString = (CHAR16*)(Current + NameOffset); + Length = GetUnicodeStringTextSize ((UINT8*)UnicodeString) ; + DestTmp = new CHAR8[Length / 2 + 1]; + VarStoreName = DestTmp; + while (*UnicodeString != '\0') { + *(DestTmp++) = (CHAR8) *(UnicodeString++); + } + *DestTmp = '\0'; + break; + default: + break; + } + + delete[] StringPtr; + + return VarStoreName; +} + +EFI_STATUS +CVfrStringDB::FindStringBlock ( + IN UINT8 *StringData, + IN EFI_STRING_ID StringId, + OUT UINT32 *StringTextOffset, + OUT UINT8 *BlockType + ) +{ + UINT8 *BlockHdr; + EFI_STRING_ID CurrentStringId; + UINT32 BlockSize; + UINT32 Index; + UINT8 *StringTextPtr; + UINT32 Offset; + UINT16 StringCount; + UINT16 SkipCount; + UINT8 Length8; + EFI_HII_SIBT_EXT2_BLOCK Ext2; + UINT32 Length32; + UINT32 StringSize; + + CurrentStringId = 1; + + // + // Parse the string blocks to get the string text and font. + // + BlockHdr = StringData; + BlockSize = 0; + Offset = 0; + while (*BlockHdr != EFI_HII_SIBT_END) { + switch (*BlockHdr) { + case EFI_HII_SIBT_STRING_SCSU: + Offset = sizeof (EFI_HII_STRING_BLOCK); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRING_SCSU_FONT: + Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRINGS_SCSU: + memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); + StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8); + BlockSize += StringTextPtr - BlockHdr; + + for (Index = 0; Index < StringCount; Index++) { + BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_STRINGS_SCSU_FONT: + memcpy ( + &StringCount, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT16) + ); + StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8); + BlockSize += StringTextPtr - BlockHdr; + + for (Index = 0; Index < StringCount; Index++) { + BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_STRING_UCS2: + Offset = sizeof (EFI_HII_STRING_BLOCK); + StringTextPtr = BlockHdr + Offset; + // + // Use StringSize to store the size of the specified string, including the NULL + // terminator. + // + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += Offset + StringSize; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRING_UCS2_FONT: + Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16); + StringTextPtr = BlockHdr + Offset; + // + // Use StrSize to store the size of the specified string, including the NULL + // terminator. + // + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += Offset + StringSize; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRINGS_UCS2: + Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset; + memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); + for (Index = 0; Index < StringCount; Index++) { + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += StringSize; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + StringSize; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_STRINGS_UCS2_FONT: + Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset; + memcpy ( + &StringCount, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT16) + ); + for (Index = 0; Index < StringCount; Index++) { + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += StringSize; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + StringSize; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_DUPLICATE: + if (CurrentStringId == StringId) { + // + // Incoming StringId is an id of a duplicate string block. + // Update the StringId to be the previous string block. + // Go back to the header of string block to search. + // + memcpy ( + &StringId, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK), + sizeof (EFI_STRING_ID) + ); + CurrentStringId = 1; + BlockSize = 0; + } else { + BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK); + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_SKIP1: + SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK))); + CurrentStringId = (UINT16) (CurrentStringId + SkipCount); + BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK); + break; + + case EFI_HII_SIBT_SKIP2: + memcpy (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); + CurrentStringId = (UINT16) (CurrentStringId + SkipCount); + BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK); + break; + + case EFI_HII_SIBT_EXT1: + memcpy ( + &Length8, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT8) + ); + BlockSize += Length8; + break; + + case EFI_HII_SIBT_EXT2: + memcpy (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); + BlockSize += Ext2.Length; + break; + + case EFI_HII_SIBT_EXT4: + memcpy ( + &Length32, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT32) + ); + + BlockSize += Length32; + break; + + default: + break; + } + + if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) { + *StringTextOffset = BlockHdr - StringData + Offset; + *BlockType = *BlockHdr; + + if (StringId == CurrentStringId - 1) { + // + // if only one skip item, return EFI_NOT_FOUND. + // + if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } + } + + if (StringId < CurrentStringId - 1) { + return EFI_NOT_FOUND; + } + } + BlockHdr = StringData + BlockSize; + } + + return EFI_NOT_FOUND; +} + +UINT32 +CVfrStringDB::GetUnicodeStringTextSize ( + IN UINT8 *StringSrc + ) +{ + UINT32 StringSize; + CHAR16 *StringPtr; + + StringSize = sizeof (CHAR16); + StringPtr = (UINT16*)StringSrc; + while (*StringPtr++ != L'\0') { + StringSize += sizeof (CHAR16); + } + + return StringSize; +} + BOOLEAN VfrCompatibleMode = FALSE; CVfrVarDataTypeDB gCVfrVarDataTypeDB; +CVfrDefaultStore gCVfrDefaultStore; +CVfrDataStorage gCVfrDataStorage; +