X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FC%2FVfrCompile%2FVfrUtilityLib.cpp;h=9c9c4d40540f85de7583dbc1a6dd3edefd17cce5;hb=2e351cbe8e190271b3716284fc1076551d005472;hp=3797cd822841d2f5eaa4c78fecdeef6428539be4;hpb=40d841f6a8f84e75409178e19e69b95e01bada0f;p=mirror_edk2.git diff --git a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp index 3797cd8228..9c9c4d4054 100644 --- a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp +++ b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp @@ -1,20 +1,16 @@ /** @file - + Vfr common library functions. -Copyright (c) 2004 - 2008, 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 - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "stdio.h" #include "stdlib.h" +#include "assert.h" +#include "CommonLib.h" #include "VfrUtilityLib.h" #include "VfrFormPkg.h" @@ -70,9 +66,9 @@ CVfrBinaryOutput::WriteEnd ( } SConfigInfo::SConfigInfo ( - IN UINT8 Type, - IN UINT16 Offset, - IN UINT32 Width, + IN UINT8 Type, + IN UINT16 Offset, + IN UINT32 Width, IN EFI_IFR_TYPE_VALUE Value ) { @@ -109,6 +105,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 +118,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 +139,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 +154,7 @@ SConfigItem::SConfigItem ( SConfigItem::SConfigItem ( IN CHAR8 *Name, + IN EFI_GUID *Guid, IN CHAR8 *Id, IN UINT8 Type, IN UINT16 Offset, @@ -154,6 +163,7 @@ SConfigItem::SConfigItem ( ) { mName = NULL; + mGuid = NULL; mId = NULL; mInfoStrList = NULL; mNext = NULL; @@ -164,6 +174,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 +195,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 +209,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 +253,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 +289,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 +301,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, (UINT16) 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 +323,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; } } @@ -337,7 +354,7 @@ CVfrBufferConfig::Write ( case 'i' : // set info if (mItemListPos->mId != NULL) { - delete mItemListPos->mId; + delete[] mItemListPos->mId; } mItemListPos->mId = NULL; if (Id != NULL) { @@ -468,6 +485,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} }; @@ -529,7 +547,7 @@ _STR2U32 ( // // BUG: does not handle overflow here // - (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { Value += (c - 'a' + 10); @@ -577,6 +595,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 +699,9 @@ CVfrVarDataTypeDB::ExtractFieldNameAndArrary ( if (*VarStr == ']') { VarStr++; } + if (*VarStr == '.') { + VarStr++; + } return VFR_RETURN_SUCCESS; case ']': return VFR_RETURN_DATA_STRING_ERROR; @@ -632,18 +712,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,13 +751,14 @@ EFI_VFR_RETURN_CODE CVfrVarDataTypeDB::GetFieldOffset ( IN SVfrDataField *Field, IN UINT32 ArrayIdx, - OUT UINT32 &Offset + OUT UINT32 &Offset, + IN BOOLEAN IsBitField ) { if (Field == NULL) { return VFR_RETURN_FATAL_ERROR; } - + // // Framework Vfr file Array Index is from 1. // But Uefi Vfr file Array Index is from 0. @@ -678,7 +773,7 @@ CVfrVarDataTypeDB::GetFieldOffset ( if ((ArrayIdx != INVALID_ARRAY_INDEX) && ((Field->mArrayNum == 0) || (Field->mArrayNum <= ArrayIdx))) { return VFR_RETURN_ERROR_ARRARY_NUM; } - + // // Be compatible with the current usage // If ArraryIdx is not specified, the first one is used. @@ -689,8 +784,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 +807,8 @@ CVfrVarDataTypeDB::GetFieldWidth ( UINT32 CVfrVarDataTypeDB::GetFieldSize ( IN SVfrDataField *Field, - IN UINT32 ArrayIdx + IN UINT32 ArrayIdx, + IN BOOLEAN BitField ) { if (Field == NULL) { @@ -717,9 +816,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; + } } } @@ -734,7 +837,9 @@ CVfrVarDataTypeDB::InternalTypesListInit ( for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) { New = new SVfrDataType; if (New != NULL) { - strcpy (New->mTypeName, gInternalTypesTable[Index].mTypeName); + assert (strlen (gInternalTypesTable[Index].mTypeName) < MAX_NAME_LEN); + strncpy (New->mTypeName, gInternalTypesTable[Index].mTypeName, MAX_NAME_LEN - 1); + New->mTypeName[MAX_NAME_LEN - 1] = 0; New->mType = gInternalTypesTable[Index].mType; New->mAlign = gInternalTypesTable[Index].mAlign; New->mTotalSize = gInternalTypesTable[Index].mSize; @@ -748,18 +853,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) { @@ -772,20 +880,58 @@ 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) { + 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; } @@ -806,6 +952,7 @@ CVfrVarDataTypeDB::CVfrVarDataTypeDB ( mPackAlign = DEFAULT_PACK_ALIGN; mPackStack = NULL; mFirstNewDataTypeName = NULL; + mCurrDataType = NULL; InternalTypesListInit (); } @@ -830,7 +977,7 @@ CVfrVarDataTypeDB::~CVfrVarDataTypeDB ( pType->mMembers = pType->mMembers->mNext; delete pField; } - delete pType; + delete pType; } while (mPackStack != NULL) { @@ -907,6 +1054,7 @@ CVfrVarDataTypeDB::DeclareDataTypeBegin ( pNewType->mTotalSize = 0; pNewType->mMembers = NULL; pNewType->mNext = NULL; + pNewType->mHasBitField = FALSE; mNewDataType = pNewType; } @@ -934,7 +1082,128 @@ CVfrVarDataTypeDB::SetNewTypeName ( } } - strcpy(mNewDataType->mTypeName, TypeName); + strncpy(mNewDataType->mTypeName, TypeName, MAX_NAME_LEN - 1); + mNewDataType->mTypeName[MAX_NAME_LEN - 1] = 0; + 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) { + strncpy (pNewField->mFieldName, FieldName, MAX_NAME_LEN - 1); + pNewField->mFieldName[MAX_NAME_LEN - 1] = 0; + } + 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 fields 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; } @@ -942,15 +1211,18 @@ 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; @@ -967,9 +1239,11 @@ CVfrVarDataTypeDB::DataTypeAddField ( if ((pNewField = new SVfrDataField) == NULL) { return VFR_RETURN_OUT_FOR_RESOURCES; } - strcpy (pNewField->mFieldName, FieldName); + strncpy (pNewField->mFieldName, FieldName, MAX_NAME_LEN - 1); + pNewField->mFieldName[MAX_NAME_LEN - 1] = 0; pNewField->mFieldType = pFieldType; pNewField->mArrayNum = ArrayNum; + pNewField->mIsBitField = FALSE; if ((mNewDataType->mTotalSize % Align) == 0) { pNewField->mOffset = mNewDataType->mTotalSize; } else { @@ -986,7 +1260,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 +1383,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 +1410,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; } @@ -1208,10 +1499,10 @@ CVfrVarDataTypeDB::Dump ( fprintf (File, "\t\tstruct %s {\n", pTNode->mTypeName); for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) { if (pFNode->mArrayNum > 0) { - fprintf (File, "\t\t\t+%08d[%08x] %s[%d] <%s>\n", pFNode->mOffset, pFNode->mOffset, + fprintf (File, "\t\t\t+%08d[%08x] %s[%d] <%s>\n", pFNode->mOffset, pFNode->mOffset, pFNode->mFieldName, pFNode->mArrayNum, pFNode->mFieldType->mTypeName); } else { - fprintf (File, "\t\t\t+%08d[%08x] %s <%s>\n", pFNode->mOffset, pFNode->mOffset, + fprintf (File, "\t\t\t+%08d[%08x] %s <%s>\n", pFNode->mOffset, pFNode->mOffset, pFNode->mFieldName, pFNode->mFieldType->mTypeName); } } @@ -1239,7 +1530,7 @@ CVfrVarDataTypeDB::ParserDB ( printf ("\t\t\t%s\t%s\n", pFNode->mFieldType->mTypeName, pFNode->mFieldName); } printf ("\t\t};\n"); - printf ("---------------------------------------------------------------\n"); + printf ("---------------------------------------------------------------\n"); } printf ("***************************************************************\n"); } @@ -1257,7 +1548,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 +1569,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 +1586,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; } @@ -1304,6 +1600,7 @@ SVfrVarStorageNode::SVfrVarStorageNode ( IN EFI_VARSTORE_ID VarStoreId ) { + memset (&mGuid, 0, sizeof (EFI_GUID)); if (StoreName != NULL) { mVarStoreName = new CHAR8[strlen(StoreName) + 1]; strcpy (mVarStoreName, StoreName); @@ -1315,6 +1612,7 @@ SVfrVarStorageNode::SVfrVarStorageNode ( mVarStoreType = EFI_VFR_VARSTORE_NAME; mStorageInfo.mNameSpace.mNameTable = new EFI_VARSTORE_ID[DEFAULT_NAME_TABLE_ITEMS]; mStorageInfo.mNameSpace.mTableSize = 0; + mAssignedFlag = FALSE; } SVfrVarStorageNode::~SVfrVarStorageNode ( @@ -1322,11 +1620,11 @@ SVfrVarStorageNode::~SVfrVarStorageNode ( ) { if (mVarStoreName != NULL) { - delete mVarStoreName; + delete[] mVarStoreName; } if (mVarStoreType == EFI_VFR_VARSTORE_NAME) { - delete mStorageInfo.mNameSpace.mNameTable; + delete[] mStorageInfo.mNameSpace.mNameTable; } } @@ -1348,6 +1646,8 @@ CVfrDataStorage::CVfrDataStorage ( mNameVarStoreList = NULL; mCurrVarStorageNode = NULL; mNewVarStorageNode = NULL; + mBufferFieldInfoListHead = NULL; + mBufferFieldInfoListTail = NULL; } CVfrDataStorage::~CVfrDataStorage ( @@ -1382,7 +1682,7 @@ CVfrDataStorage::GetFreeVarStoreId ( ) { UINT32 Index, Mask, Offset; - + // // Assign the different ID range for the different type VarStore to support Framework Vfr // @@ -1401,6 +1701,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; @@ -1446,23 +1750,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; } @@ -1511,10 +1822,10 @@ CVfrDataStorage::DeclareNameVarStoreEnd ( return VFR_RETURN_SUCCESS; } -EFI_VFR_RETURN_CODE +EFI_VFR_RETURN_CODE CVfrDataStorage::DeclareEfiVarStore ( - IN CHAR8 *StoreName, - IN EFI_GUID *Guid, + IN CHAR8 *StoreName, + IN EFI_GUID *Guid, IN EFI_STRING_ID NameStrId, IN UINT32 VarSize, IN BOOLEAN Flag @@ -1531,10 +1842,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); @@ -1548,23 +1857,29 @@ CVfrDataStorage::DeclareEfiVarStore ( return VFR_RETURN_SUCCESS; } -EFI_VFR_RETURN_CODE +EFI_VFR_RETURN_CODE CVfrDataStorage::DeclareBufferVarStore ( - IN CHAR8 *StoreName, - IN EFI_GUID *Guid, + IN CHAR8 *StoreName, + IN EFI_GUID *Guid, 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) { @@ -1576,121 +1891,197 @@ 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::GetVarStoreId ( - IN CHAR8 *StoreName, - OUT EFI_VARSTORE_ID *VarStoreId +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->mVarStoreName, StoreName) == 0) { - mCurrVarStorageNode = pNode; - *VarStoreId = pNode->mVarStoreId; - return VFR_RETURN_SUCCESS; + if (strcmp (pNode->mStorageInfo.mDataType->mTypeName, DataTypeName) != 0) { + continue; } - } - for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - mCurrVarStorageNode = pNode; - *VarStoreId = pNode->mVarStoreId; - return VFR_RETURN_SUCCESS; + 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; + } } } - for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + 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; - *VarStoreId = pNode->mVarStoreId; - return VFR_RETURN_SUCCESS; + *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; } - mCurrVarStorageNode = NULL; - *VarStoreId = EFI_VARSTORE_ID_INVALID; - return VFR_RETURN_UNDEFINED; + 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::GetBufferVarStoreDataTypeName ( - IN CHAR8 *StoreName, - OUT CHAR8 **DataTypeName +CVfrDataStorage::GetVarStoreId ( + IN CHAR8 *StoreName, + OUT EFI_VARSTORE_ID *VarStoreId, + IN EFI_GUID *StoreGuid ) { + EFI_VFR_RETURN_CODE ReturnCode; SVfrVarStorageNode *pNode; + BOOLEAN HasFoundOne = FALSE; - if ((StoreName == NULL) || (DataTypeName == NULL)) { - return VFR_RETURN_FATAL_ERROR; - } + mCurrVarStorageNode = NULL; for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - break; + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } } } - if (pNode == NULL) { - return VFR_RETURN_UNDEFINED; + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } + } } - if (pNode->mStorageInfo.mDataType == NULL) { - return VFR_RETURN_FATAL_ERROR; + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } + } } - *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName; - return VFR_RETURN_SUCCESS; + if (HasFoundOne) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return VFR_RETURN_SUCCESS; + } + + *VarStoreId = EFI_VARSTORE_ID_INVALID; + + // + // Assume that Data structure 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::GetVarStoreType ( - IN CHAR8 *StoreName, - OUT EFI_VFR_VARSTORE_TYPE &VarStoreType +CVfrDataStorage::GetBufferVarStoreDataTypeName ( + IN EFI_VARSTORE_ID VarStoreId, + OUT CHAR8 **DataTypeName ) { SVfrVarStorageNode *pNode; - if (StoreName == 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) { - VarStoreType = pNode->mVarStoreType; + if (pNode->mVarStoreId == VarStoreId) { + *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName; return VFR_RETURN_SUCCESS; } } - for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - VarStoreType = pNode->mVarStoreType; - return VFR_RETURN_SUCCESS; - } - } - - for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - VarStoreType = pNode->mVarStoreType; - return VFR_RETURN_SUCCESS; - } - } - - VarStoreType = EFI_VFR_VARSTORE_INVALID; return VFR_RETURN_UNDEFINED; } @@ -1732,9 +2123,47 @@ CVfrDataStorage::GetVarStoreType ( return VarStoreType; } +EFI_GUID * +CVfrDataStorage::GetVarStoreGuid ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + SVfrVarStorageNode *pNode; + EFI_GUID *VarGuid; + + VarGuid = NULL; + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + return VarGuid; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarGuid = &pNode->mGuid; + return VarGuid; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarGuid = &pNode->mGuid; + return VarGuid; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarGuid = &pNode->mGuid; + return VarGuid; + } + } + + return VarGuid; +} + EFI_VFR_RETURN_CODE CVfrDataStorage::GetVarStoreName ( - IN EFI_VARSTORE_ID VarStoreId, + IN EFI_VARSTORE_ID VarStoreId, OUT CHAR8 **VarStoreName ) { @@ -1804,6 +2233,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, @@ -1817,7 +2288,7 @@ CVfrDataStorage::GetNameVarStoreInfo ( if (mCurrVarStorageNode == NULL) { return VFR_RETURN_GET_NVVARSTORE_ERROR; } - + // // Framework Vfr file Index is from 1, but Uefi Vfr file Index is from 0. // @@ -1833,39 +2304,10 @@ CVfrDataStorage::GetNameVarStoreInfo ( return VFR_RETURN_SUCCESS; } -EFI_VFR_RETURN_CODE -CVfrDataStorage::BufferVarStoreRequestElementAdd ( - IN CHAR8 *StoreName, - IN EFI_VARSTORE_INFO &Info - ) -{ - SVfrVarStorageNode *pNode = NULL; - EFI_IFR_TYPE_VALUE Value = gZeroEfiIfrTypeValue; - - for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { - if (strcmp (pNode->mVarStoreName, StoreName) == 0) { - 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, - IN EFI_STRING_ID DefaultStoreNameId, + IN CHAR8 *RefName, + IN EFI_STRING_ID DefaultStoreNameId, IN UINT16 DefaultId ) { @@ -1888,7 +2330,7 @@ SVfrDefaultStoreNode::~SVfrDefaultStoreNode ( ) { if (mRefName != NULL) { - delete mRefName; + delete[] mRefName; } } @@ -1943,7 +2385,7 @@ CVfrDefaultStore::RegisterDefaultStore ( } /* - * assign new reference name or new default store name id only if + * assign new reference name or new default store name id only if * the original is invalid */ EFI_VFR_RETURN_CODE @@ -2028,6 +2470,7 @@ 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 ) @@ -2053,12 +2496,12 @@ 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; } } - + gCVfrBufferConfig.Close (); return VFR_RETURN_SUCCESS; @@ -2089,7 +2532,7 @@ SVfrRuleNode::~SVfrRuleNode ( ) { if (mRuleName != NULL) { - delete mRuleName; + delete[] mRuleName; } } @@ -2162,6 +2605,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 ( @@ -2173,6 +2617,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 @@ -2181,16 +2643,37 @@ EFI_VARSTORE_INFO::operator == ( ) { if ((mVarStoreId == Info->mVarStoreId) && - (mInfo.mVarName == Info->mInfo.mVarName) && + (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 @@ -2206,6 +2689,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; @@ -2284,11 +2771,11 @@ SVfrQuestionNode::~SVfrQuestionNode ( ) { if (mName != NULL) { - delete mName; + delete[] mName; } if (mVarIdStr != NULL) { - delete mVarIdStr; + delete[] mVarIdStr; } } @@ -2339,7 +2826,7 @@ CVfrQuestionDB::ResetInit( // Question ID 0 is reserved. mFreeQIdBitMap[0] = 0x80000000; - mQuestionList = NULL; + mQuestionList = NULL; } VOID @@ -2350,7 +2837,7 @@ CVfrQuestionDB::PrintAllQuestion ( SVfrQuestionNode *pNode = NULL; for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { - printf ("Question VarId is %s and QuesitonId is 0x%x\n", pNode->mVarIdStr, pNode->mQuestionId); + printf ("Question VarId is %s and QuestionId is 0x%x\n", pNode->mVarIdStr, pNode->mQuestionId); } } @@ -2465,26 +2952,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) { @@ -2519,7 +3034,8 @@ CVfrQuestionDB::RegisterNewDateQuestion ( for (Index = 0; Index < 3; Index++) { if (VarIdStr[Index] != NULL) { - delete VarIdStr[Index]; + delete[] VarIdStr[Index]; + VarIdStr[Index] = NULL; } } @@ -2536,7 +3052,8 @@ Err: } if (VarIdStr[Index] != NULL) { - delete VarIdStr[Index]; + delete[] VarIdStr [Index]; + VarIdStr [Index] = NULL; } } } @@ -2613,26 +3130,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) { @@ -2667,7 +3212,8 @@ CVfrQuestionDB::RegisterNewTimeQuestion ( for (Index = 0; Index < 3; Index++) { if (VarIdStr[Index] != NULL) { - delete VarIdStr[Index]; + delete[] VarIdStr[Index]; + VarIdStr[Index] = NULL; } } @@ -2683,6 +3229,126 @@ Err: delete pNode[Index]; } + if (VarIdStr[Index] != NULL) { + delete[] VarIdStr[Index]; + VarIdStr[Index] = NULL; + } + } +} + +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]; } @@ -2696,15 +3362,15 @@ CVfrQuestionDB::UpdateQuestionId ( ) { SVfrQuestionNode *pNode = NULL; - + if (QId == NewQId) { // don't update return VFR_RETURN_SUCCESS; } - + // // For Framework Vfr, don't check question ID conflict. - // + // if (!VfrCompatibleMode && ChekQuestionIdFree (NewQId) == FALSE) { return VFR_RETURN_REDEFINED; } @@ -2760,7 +3426,7 @@ CVfrQuestionDB::GetQuestionId ( if (strcmp (pNode->mVarIdStr, VarIdStr) != 0) { continue; } - } + } QuestionId = pNode->mQuestionId; BitMask = pNode->mBitMask; @@ -2813,8 +3479,488 @@ 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; + } + + if (mStringFileName != NULL) { + delete[] mStringFileName; + } + + 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;