| /** @file | |
| Vfr common library functions. | |
| Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| 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. | |
| **/ | |
| #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 CONST CHAR8 *LineHeader, | |
| IN CHAR8 *BlkBuf, | |
| IN UINT32 BlkSize | |
| ) | |
| { | |
| UINT32 Index; | |
| if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { | |
| return; | |
| } | |
| for (Index = 0; Index < BlkSize; Index++) { | |
| if ((Index % LineBytes) == 0) { | |
| fprintf (pFile, "\n%s", LineHeader); | |
| } | |
| fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); | |
| } | |
| } | |
| VOID | |
| CVfrBinaryOutput::WriteEnd ( | |
| IN FILE *pFile, | |
| IN UINT32 LineBytes, | |
| IN CONST CHAR8 *LineHeader, | |
| IN CHAR8 *BlkBuf, | |
| IN UINT32 BlkSize | |
| ) | |
| { | |
| UINT32 Index; | |
| if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { | |
| return; | |
| } | |
| for (Index = 0; Index < BlkSize - 1; Index++) { | |
| if ((Index % LineBytes) == 0) { | |
| fprintf (pFile, "\n%s", LineHeader); | |
| } | |
| fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); | |
| } | |
| if ((Index % LineBytes) == 0) { | |
| fprintf (pFile, "\n%s", LineHeader); | |
| } | |
| fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]); | |
| } | |
| SConfigInfo::SConfigInfo ( | |
| IN UINT8 Type, | |
| IN UINT16 Offset, | |
| IN UINT32 Width, | |
| IN EFI_IFR_TYPE_VALUE Value | |
| ) | |
| { | |
| mNext = NULL; | |
| mOffset = Offset; | |
| mWidth = (UINT16)Width; | |
| mValue = new UINT8[mWidth]; | |
| if (mValue == NULL) { | |
| return; | |
| } | |
| switch (Type) { | |
| case EFI_IFR_TYPE_NUM_SIZE_8 : | |
| memcpy (mValue, &Value.u8, mWidth); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_16 : | |
| memcpy (mValue, &Value.u16, mWidth); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_32 : | |
| memcpy (mValue, &Value.u32, mWidth); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_64 : | |
| memcpy (mValue, &Value.u64, mWidth); | |
| break; | |
| case EFI_IFR_TYPE_BOOLEAN : | |
| memcpy (mValue, &Value.b, mWidth); | |
| break; | |
| case EFI_IFR_TYPE_TIME : | |
| memcpy (mValue, &Value.time, mWidth); | |
| break; | |
| case EFI_IFR_TYPE_DATE : | |
| memcpy (mValue, &Value.date, mWidth); | |
| break; | |
| 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; | |
| } | |
| } | |
| SConfigInfo::~SConfigInfo ( | |
| VOID | |
| ) | |
| { | |
| BUFFER_SAFE_FREE (mValue); | |
| } | |
| SConfigItem::SConfigItem ( | |
| IN CHAR8 *Name, | |
| IN EFI_GUID *Guid, | |
| IN CHAR8 *Id | |
| ) | |
| { | |
| mName = NULL; | |
| mGuid = NULL; | |
| mId = NULL; | |
| mInfoStrList = NULL; | |
| mNext = NULL; | |
| if (Name != NULL) { | |
| if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) { | |
| strcpy (mName, Name); | |
| } | |
| } | |
| 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); | |
| } | |
| } | |
| } | |
| SConfigItem::SConfigItem ( | |
| IN CHAR8 *Name, | |
| IN EFI_GUID *Guid, | |
| IN CHAR8 *Id, | |
| IN UINT8 Type, | |
| IN UINT16 Offset, | |
| IN UINT16 Width, | |
| IN EFI_IFR_TYPE_VALUE Value | |
| ) | |
| { | |
| mName = NULL; | |
| mGuid = NULL; | |
| mId = NULL; | |
| mInfoStrList = NULL; | |
| mNext = NULL; | |
| if (Name != NULL) { | |
| if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) { | |
| strcpy (mName, Name); | |
| } | |
| } | |
| 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); | |
| } | |
| } | |
| mInfoStrList = new SConfigInfo(Type, Offset, Width, Value); | |
| } | |
| SConfigItem::~SConfigItem ( | |
| VOID | |
| ) | |
| { | |
| SConfigInfo *Info; | |
| BUFFER_SAFE_FREE (mName); | |
| BUFFER_SAFE_FREE (mGuid); | |
| BUFFER_SAFE_FREE (mId); | |
| while (mInfoStrList != NULL) { | |
| Info = mInfoStrList; | |
| mInfoStrList = mInfoStrList->mNext; | |
| BUFFER_SAFE_FREE (Info); | |
| } | |
| } | |
| UINT8 | |
| CVfrBufferConfig::Register ( | |
| IN CHAR8 *Name, | |
| IN EFI_GUID *Guid, | |
| IN CHAR8 *Id | |
| ) | |
| { | |
| SConfigItem *pNew; | |
| if (Select (Name, Guid) == 0) { | |
| return 1; | |
| } | |
| if ((pNew = new SConfigItem (Name, Guid, Id)) == NULL) { | |
| return 2; | |
| } | |
| if (mItemListHead == NULL) { | |
| mItemListHead = pNew; | |
| mItemListTail = pNew; | |
| } else { | |
| mItemListTail->mNext = pNew; | |
| mItemListTail = pNew; | |
| } | |
| mItemListPos = pNew; | |
| return 0; | |
| } | |
| VOID | |
| CVfrBufferConfig::Open ( | |
| VOID | |
| ) | |
| { | |
| mItemListPos = mItemListHead; | |
| } | |
| BOOLEAN | |
| CVfrBufferConfig::Eof( | |
| VOID | |
| ) | |
| { | |
| return (mItemListPos == NULL) ? TRUE : FALSE; | |
| } | |
| UINT8 | |
| CVfrBufferConfig::Select ( | |
| IN CHAR8 *Name, | |
| IN EFI_GUID *Guid, | |
| IN CHAR8 *Id | |
| ) | |
| { | |
| SConfigItem *p; | |
| if (Name == NULL || Guid == NULL) { | |
| mItemListPos = mItemListHead; | |
| return 0; | |
| } else { | |
| for (p = mItemListHead; p != NULL; p = p->mNext) { | |
| if ((strcmp (p->mName, Name) != 0) || (memcmp (p->mGuid, Guid, sizeof (EFI_GUID)) != 0)) { | |
| continue; | |
| } | |
| if (Id != NULL) { | |
| if (p->mId == NULL || strcmp (p->mId, Id) != 0) { | |
| continue; | |
| } | |
| } else if (p->mId != NULL) { | |
| continue; | |
| } | |
| mItemListPos = p; | |
| return 0; | |
| } | |
| } | |
| return 1; | |
| } | |
| UINT8 | |
| CVfrBufferConfig::Write ( | |
| IN CONST CHAR8 Mode, | |
| IN CHAR8 *Name, | |
| IN EFI_GUID *Guid, | |
| IN CHAR8 *Id, | |
| IN UINT8 Type, | |
| IN UINT16 Offset, | |
| IN UINT32 Width, | |
| IN EFI_IFR_TYPE_VALUE Value | |
| ) | |
| { | |
| UINT8 Ret; | |
| SConfigItem *pItem; | |
| SConfigInfo *pInfo; | |
| if ((Ret = Select (Name, Guid)) != 0) { | |
| return Ret; | |
| } | |
| switch (Mode) { | |
| case 'a' : // add | |
| if (Select (Name, Guid, Id) != 0) { | |
| if ((pItem = new SConfigItem (Name, Guid, Id, Type, Offset, (UINT16) Width, Value)) == NULL) { | |
| return 2; | |
| } | |
| if (mItemListHead == NULL) { | |
| mItemListHead = pItem; | |
| mItemListTail = pItem; | |
| } else { | |
| mItemListTail->mNext = pItem; | |
| mItemListTail = pItem; | |
| } | |
| mItemListPos = pItem; | |
| } else { | |
| // 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) { | |
| return 0; | |
| } | |
| } | |
| if((pInfo = new SConfigInfo (Type, Offset, Width, Value)) == NULL) { | |
| return 2; | |
| } | |
| pInfo->mNext = mItemListPos->mInfoStrList; | |
| mItemListPos->mInfoStrList = pInfo; | |
| } | |
| break; | |
| case 'd' : // delete | |
| if (mItemListHead == mItemListPos) { | |
| mItemListHead = mItemListPos->mNext; | |
| delete mItemListPos; | |
| break; | |
| } | |
| for (pItem = mItemListHead; pItem->mNext != mItemListPos; pItem = pItem->mNext) | |
| ; | |
| pItem->mNext = mItemListPos->mNext; | |
| if (mItemListTail == mItemListPos) { | |
| mItemListTail = pItem; | |
| } | |
| delete mItemListPos; | |
| mItemListPos = pItem->mNext; | |
| break; | |
| case 'i' : // set info | |
| if (mItemListPos->mId != NULL) { | |
| delete mItemListPos->mId; | |
| } | |
| mItemListPos->mId = NULL; | |
| if (Id != NULL) { | |
| if ((mItemListPos->mId = new CHAR8[strlen (Id) + 1]) == NULL) { | |
| return 2; | |
| } | |
| strcpy (mItemListPos->mId, Id); | |
| } | |
| break; | |
| default : | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| VOID | |
| CVfrBufferConfig::Close ( | |
| VOID | |
| ) | |
| { | |
| mItemListPos = NULL; | |
| } | |
| #define BYTES_PRE_LINE 0x10 | |
| VOID | |
| CVfrBufferConfig::OutputCFile ( | |
| IN FILE *pFile, | |
| IN CHAR8 *BaseName | |
| ) | |
| { | |
| CVfrBinaryOutput Output; | |
| SConfigItem *Item; | |
| SConfigInfo *Info; | |
| UINT32 TotalLen; | |
| if (pFile == NULL) { | |
| return; | |
| } | |
| for (Item = mItemListHead; Item != NULL; Item = Item->mNext) { | |
| if (Item->mId != NULL || Item->mInfoStrList == NULL) { | |
| continue; | |
| } | |
| fprintf (pFile, "\nunsigned char %s%sBlockName[] = {", BaseName, Item->mName); | |
| TotalLen = sizeof (UINT32); | |
| for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { | |
| TotalLen += sizeof (UINT16) * 2; | |
| } | |
| Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32)); | |
| for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { | |
| fprintf (pFile, "\n"); | |
| Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16)); | |
| Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16)); | |
| } | |
| fprintf (pFile, "\n};\n"); | |
| } | |
| for (Item = mItemListHead; Item != NULL; Item = Item->mNext) { | |
| if (Item->mId != NULL && Item->mInfoStrList != NULL) { | |
| fprintf (pFile, "\nunsigned char %s%sDefault%s[] = {", BaseName, Item->mName, Item->mId); | |
| TotalLen = sizeof (UINT32); | |
| for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { | |
| TotalLen += Info->mWidth + sizeof (UINT16) * 2; | |
| } | |
| Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32)); | |
| for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { | |
| fprintf (pFile, "\n"); | |
| Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16)); | |
| Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16)); | |
| if (Info->mNext == NULL) { | |
| Output.WriteEnd (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth); | |
| } else { | |
| Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth); | |
| } | |
| } | |
| fprintf (pFile, "\n};\n"); | |
| } | |
| } | |
| } | |
| CVfrBufferConfig::CVfrBufferConfig ( | |
| VOID | |
| ) | |
| { | |
| mItemListHead = NULL; | |
| mItemListTail = NULL; | |
| mItemListPos = NULL; | |
| } | |
| CVfrBufferConfig::~CVfrBufferConfig ( | |
| VOID | |
| ) | |
| { | |
| SConfigItem *p; | |
| while (mItemListHead != NULL) { | |
| p = mItemListHead; | |
| mItemListHead = mItemListHead->mNext; | |
| delete p; | |
| } | |
| mItemListHead = NULL; | |
| mItemListTail = NULL; | |
| mItemListPos = NULL; | |
| } | |
| CVfrBufferConfig gCVfrBufferConfig; | |
| static struct { | |
| CONST CHAR8 *mTypeName; | |
| UINT8 mType; | |
| UINT32 mSize; | |
| UINT32 mAlign; | |
| } gInternalTypesTable [] = { | |
| {"UINT64", EFI_IFR_TYPE_NUM_SIZE_64, sizeof (UINT64), sizeof (UINT64)}, | |
| {"UINT32", EFI_IFR_TYPE_NUM_SIZE_32, sizeof (UINT32), sizeof (UINT32)}, | |
| {"UINT16", EFI_IFR_TYPE_NUM_SIZE_16, sizeof (UINT16), sizeof (UINT16)}, | |
| {"UINT8", EFI_IFR_TYPE_NUM_SIZE_8, sizeof (UINT8), sizeof (UINT8)}, | |
| {"BOOLEAN", EFI_IFR_TYPE_BOOLEAN, sizeof (BOOLEAN), sizeof (BOOLEAN)}, | |
| {"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} | |
| }; | |
| STATIC | |
| BOOLEAN | |
| _IS_INTERNAL_TYPE ( | |
| IN CHAR8 *TypeName | |
| ) | |
| { | |
| UINT32 Index; | |
| if (TypeName == NULL) { | |
| return FALSE; | |
| } | |
| for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) { | |
| if (strcmp (TypeName, gInternalTypesTable[Index].mTypeName) == 0) { | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| STATIC | |
| CHAR8 * | |
| TrimHex ( | |
| IN CHAR8 *Str, | |
| OUT bool *IsHex | |
| ) | |
| { | |
| *IsHex = FALSE; | |
| while (*Str && *Str == ' ') { | |
| Str++; | |
| } | |
| while (*Str && *Str == '0') { | |
| Str++; | |
| } | |
| if (*Str && (*Str == 'x' || *Str == 'X')) { | |
| Str++; | |
| *IsHex = TRUE; | |
| } | |
| return Str; | |
| } | |
| UINT32 | |
| _STR2U32 ( | |
| IN CHAR8 *Str | |
| ) | |
| { | |
| bool IsHex; | |
| UINT32 Value; | |
| CHAR8 c; | |
| Str = TrimHex (Str, &IsHex); | |
| for (Value = 0; (c = *Str) != '\0'; Str++) { | |
| // | |
| // BUG: does not handle overflow here | |
| // | |
| (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); | |
| if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { | |
| Value += (c - 'a' + 10); | |
| } | |
| if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { | |
| Value += (c - 'A' + 10); | |
| } | |
| if (c >= '0' && c <= '9') { | |
| Value += (c - '0'); | |
| } | |
| } | |
| return Value; | |
| } | |
| VOID | |
| CVfrVarDataTypeDB::RegisterNewType ( | |
| IN SVfrDataType *New | |
| ) | |
| { | |
| New->mNext = mDataTypeList; | |
| mDataTypeList = New; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::ExtractStructTypeName ( | |
| IN CHAR8 *&VarStr, | |
| OUT CHAR8 *TName | |
| ) | |
| { | |
| if (TName == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| while((*VarStr != '\0') && (*VarStr != '.')) { | |
| *TName = *VarStr; | |
| VarStr++; | |
| TName++; | |
| } | |
| *TName = '\0'; | |
| if (*VarStr == '.') { | |
| VarStr++; | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::ExtractFieldNameAndArrary ( | |
| IN CHAR8 *&VarStr, | |
| IN CHAR8 *FName, | |
| OUT UINT32 &ArrayIdx | |
| ) | |
| { | |
| UINT32 Idx; | |
| CHAR8 ArrayStr[MAX_NAME_LEN + 1]; | |
| ArrayIdx = INVALID_ARRAY_INDEX; | |
| if (FName == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| while((*VarStr != '\0') && | |
| (*VarStr != '.') && | |
| (*VarStr != '[') && | |
| (*VarStr != ']')) { | |
| *FName = *VarStr; | |
| VarStr++; | |
| FName++; | |
| } | |
| *FName = '\0'; | |
| switch (*VarStr) { | |
| case '.' : | |
| VarStr++; | |
| case '\0': | |
| return VFR_RETURN_SUCCESS; | |
| case '[' : | |
| VarStr++; | |
| for (Idx = 0; (Idx < MAX_NAME_LEN) && (*VarStr != '\0') && (*VarStr != ']'); VarStr++, Idx++) { | |
| ArrayStr[Idx] = *VarStr; | |
| } | |
| ArrayStr[Idx] = '\0'; | |
| if ((*VarStr != ']') && (ArrayStr[0] == '\0')) { | |
| return VFR_RETURN_DATA_STRING_ERROR; | |
| } | |
| ArrayIdx = _STR2U32 (ArrayStr); | |
| if (*VarStr == ']') { | |
| VarStr++; | |
| } | |
| if (*VarStr == '.') { | |
| VarStr++; | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| case ']': | |
| return VFR_RETURN_DATA_STRING_ERROR; | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::GetTypeField ( | |
| IN CONST CHAR8 *FName, | |
| IN SVfrDataType *Type, | |
| OUT SVfrDataField *&Field | |
| ) | |
| { | |
| SVfrDataField *pField = 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; | |
| } | |
| } | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::GetFieldOffset ( | |
| IN SVfrDataField *Field, | |
| IN UINT32 ArrayIdx, | |
| OUT UINT32 &Offset | |
| ) | |
| { | |
| 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. | |
| // | |
| if (VfrCompatibleMode && ArrayIdx != INVALID_ARRAY_INDEX) { | |
| if (ArrayIdx == 0) { | |
| return VFR_RETURN_ERROR_ARRARY_NUM; | |
| } | |
| ArrayIdx = ArrayIdx - 1; | |
| } | |
| 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. | |
| // | |
| // if ArrayNum is larger than zero, ArraryIdx must be specified. | |
| // | |
| // if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum > 0)) { | |
| // return VFR_RETURN_ERROR_ARRARY_NUM; | |
| // } | |
| // | |
| Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| UINT8 | |
| CVfrVarDataTypeDB::GetFieldWidth ( | |
| IN SVfrDataField *Field | |
| ) | |
| { | |
| if (Field == NULL) { | |
| return 0; | |
| } | |
| return Field->mFieldType->mType; | |
| } | |
| UINT32 | |
| CVfrVarDataTypeDB::GetFieldSize ( | |
| IN SVfrDataField *Field, | |
| IN UINT32 ArrayIdx | |
| ) | |
| { | |
| if (Field == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum != 0)) { | |
| return Field->mFieldType->mTotalSize * Field->mArrayNum; | |
| } else { | |
| return Field->mFieldType->mTotalSize; | |
| } | |
| } | |
| VOID | |
| CVfrVarDataTypeDB::InternalTypesListInit ( | |
| VOID | |
| ) | |
| { | |
| SVfrDataType *New = NULL; | |
| UINT32 Index; | |
| for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) { | |
| New = new SVfrDataType; | |
| if (New != NULL) { | |
| strcpy (New->mTypeName, gInternalTypesTable[Index].mTypeName); | |
| New->mType = gInternalTypesTable[Index].mType; | |
| New->mAlign = gInternalTypesTable[Index].mAlign; | |
| New->mTotalSize = gInternalTypesTable[Index].mSize; | |
| if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_DATE") == 0) { | |
| SVfrDataField *pYearField = new SVfrDataField; | |
| SVfrDataField *pMonthField = new SVfrDataField; | |
| SVfrDataField *pDayField = new SVfrDataField; | |
| strcpy (pYearField->mFieldName, "Year"); | |
| GetDataType ((CHAR8 *)"UINT16", &pYearField->mFieldType); | |
| pYearField->mOffset = 0; | |
| pYearField->mNext = pMonthField; | |
| pYearField->mArrayNum = 0; | |
| strcpy (pMonthField->mFieldName, "Month"); | |
| GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType); | |
| pMonthField->mOffset = 2; | |
| pMonthField->mNext = pDayField; | |
| pMonthField->mArrayNum = 0; | |
| strcpy (pDayField->mFieldName, "Day"); | |
| GetDataType ((CHAR8 *)"UINT8", &pDayField->mFieldType); | |
| pDayField->mOffset = 3; | |
| pDayField->mNext = NULL; | |
| pDayField->mArrayNum = 0; | |
| New->mMembers = pYearField; | |
| } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_TIME") == 0) { | |
| SVfrDataField *pHoursField = new SVfrDataField; | |
| SVfrDataField *pMinutesField = new SVfrDataField; | |
| SVfrDataField *pSecondsField = new SVfrDataField; | |
| strcpy (pHoursField->mFieldName, "Hours"); | |
| GetDataType ((CHAR8 *)"UINT8", &pHoursField->mFieldType); | |
| pHoursField->mOffset = 0; | |
| pHoursField->mNext = pMinutesField; | |
| pHoursField->mArrayNum = 0; | |
| strcpy (pMinutesField->mFieldName, "Minutes"); | |
| GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType); | |
| pMinutesField->mOffset = 1; | |
| pMinutesField->mNext = pSecondsField; | |
| pMinutesField->mArrayNum = 0; | |
| strcpy (pSecondsField->mFieldName, "Seconds"); | |
| GetDataType ((CHAR8 *)"UINT8", &pSecondsField->mFieldType); | |
| pSecondsField->mOffset = 2; | |
| pSecondsField->mNext = NULL; | |
| pSecondsField->mArrayNum = 0; | |
| 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; | |
| strcpy (pFormIdField->mFieldName, "FormId"); | |
| GetDataType ((CHAR8 *)"UINT16", &pFormIdField->mFieldType); | |
| pFormIdField->mOffset = 2; | |
| pFormIdField->mNext = pFormSetGuidField; | |
| pFormIdField->mArrayNum = 0; | |
| strcpy (pFormSetGuidField->mFieldName, "FormSetGuid"); | |
| GetDataType ((CHAR8 *)"EFI_GUID", &pFormSetGuidField->mFieldType); | |
| pFormSetGuidField->mOffset = 4; | |
| pFormSetGuidField->mNext = pDevicePathField; | |
| pFormSetGuidField->mArrayNum = 0; | |
| strcpy (pDevicePathField->mFieldName, "DevicePath"); | |
| GetDataType ((CHAR8 *)"EFI_STRING_ID", &pDevicePathField->mFieldType); | |
| pDevicePathField->mOffset = 20; | |
| pDevicePathField->mNext = NULL; | |
| pDevicePathField->mArrayNum = 0; | |
| New->mMembers = pQuestionIdField; | |
| } else { | |
| New->mMembers = NULL; | |
| } | |
| New->mNext = NULL; | |
| RegisterNewType (New); | |
| New = NULL; | |
| } | |
| } | |
| } | |
| CVfrVarDataTypeDB::CVfrVarDataTypeDB ( | |
| VOID | |
| ) | |
| { | |
| mDataTypeList = NULL; | |
| mNewDataType = NULL; | |
| mCurrDataField = NULL; | |
| mPackAlign = DEFAULT_PACK_ALIGN; | |
| mPackStack = NULL; | |
| mFirstNewDataTypeName = NULL; | |
| InternalTypesListInit (); | |
| } | |
| CVfrVarDataTypeDB::~CVfrVarDataTypeDB ( | |
| VOID | |
| ) | |
| { | |
| SVfrDataType *pType; | |
| SVfrDataField *pField; | |
| SVfrPackStackNode *pPack; | |
| if (mNewDataType != NULL) { | |
| delete mNewDataType; | |
| } | |
| while (mDataTypeList != NULL) { | |
| pType = mDataTypeList; | |
| mDataTypeList = mDataTypeList->mNext; | |
| while(pType->mMembers != NULL) { | |
| pField = pType->mMembers; | |
| pType->mMembers = pType->mMembers->mNext; | |
| delete pField; | |
| } | |
| delete pType; | |
| } | |
| while (mPackStack != NULL) { | |
| pPack = mPackStack; | |
| mPackStack = mPackStack->mNext; | |
| delete pPack; | |
| } | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::Pack ( | |
| IN UINT32 LineNum, | |
| IN UINT8 Action, | |
| IN CHAR8 *Identifier, | |
| IN UINT32 Number | |
| ) | |
| { | |
| UINT32 PackAlign; | |
| CHAR8 Msg[MAX_STRING_LEN] = {0, }; | |
| if (Action & VFR_PACK_SHOW) { | |
| sprintf (Msg, "value of pragma pack(show) == %d", mPackAlign); | |
| gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Warning", Msg); | |
| } | |
| if (Action & VFR_PACK_PUSH) { | |
| SVfrPackStackNode *pNew = NULL; | |
| if ((pNew = new SVfrPackStackNode (Identifier, mPackAlign)) == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| pNew->mNext = mPackStack; | |
| mPackStack = pNew; | |
| } | |
| if (Action & VFR_PACK_POP) { | |
| SVfrPackStackNode *pNode = NULL; | |
| if (mPackStack == NULL) { | |
| gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "#pragma pack(pop...) : more pops than pushes"); | |
| } | |
| for (pNode = mPackStack; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->Match (Identifier) == TRUE) { | |
| mPackAlign = pNode->mNumber; | |
| mPackStack = pNode->mNext; | |
| } | |
| } | |
| } | |
| if (Action & VFR_PACK_ASSIGN) { | |
| PackAlign = (Number > 1) ? Number + Number % 2 : Number; | |
| if ((PackAlign == 0) || (PackAlign > 16)) { | |
| gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "expected pragma parameter to be '1', '2', '4', '8', or '16'"); | |
| } else { | |
| mPackAlign = PackAlign; | |
| } | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| VOID | |
| CVfrVarDataTypeDB::DeclareDataTypeBegin ( | |
| VOID | |
| ) | |
| { | |
| SVfrDataType *pNewType = NULL; | |
| pNewType = new SVfrDataType; | |
| pNewType->mTypeName[0] = '\0'; | |
| pNewType->mType = EFI_IFR_TYPE_OTHER; | |
| pNewType->mAlign = DEFAULT_ALIGN; | |
| pNewType->mTotalSize = 0; | |
| pNewType->mMembers = NULL; | |
| pNewType->mNext = NULL; | |
| mNewDataType = pNewType; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::SetNewTypeName ( | |
| IN CHAR8 *TypeName | |
| ) | |
| { | |
| SVfrDataType *pType; | |
| if (mNewDataType == NULL) { | |
| return VFR_RETURN_ERROR_SKIPED; | |
| } | |
| if (TypeName == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| if (strlen(TypeName) >= MAX_NAME_LEN) { | |
| return VFR_RETURN_INVALID_PARAMETER; | |
| } | |
| for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { | |
| if (strcmp(pType->mTypeName, TypeName) == 0) { | |
| return VFR_RETURN_REDEFINED; | |
| } | |
| } | |
| strcpy(mNewDataType->mTypeName, TypeName); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::DataTypeAddField ( | |
| IN CHAR8 *FieldName, | |
| IN CHAR8 *TypeName, | |
| IN UINT32 ArrayNum | |
| ) | |
| { | |
| SVfrDataField *pNewField = NULL; | |
| SVfrDataType *pFieldType = NULL; | |
| SVfrDataField *pTmp; | |
| UINT32 Align; | |
| CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS); | |
| if (strlen (FieldName) >= MAX_NAME_LEN) { | |
| return VFR_RETURN_INVALID_PARAMETER; | |
| } | |
| for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) { | |
| if (strcmp (pTmp->mFieldName, FieldName) == 0) { | |
| return VFR_RETURN_REDEFINED; | |
| } | |
| } | |
| Align = MIN (mPackAlign, pFieldType->mAlign); | |
| if ((pNewField = new SVfrDataField) == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| strcpy (pNewField->mFieldName, FieldName); | |
| pNewField->mFieldType = pFieldType; | |
| pNewField->mArrayNum = ArrayNum; | |
| if ((mNewDataType->mTotalSize % Align) == 0) { | |
| pNewField->mOffset = mNewDataType->mTotalSize; | |
| } else { | |
| pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align); | |
| } | |
| 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; | |
| } | |
| mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign)); | |
| mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| VOID | |
| CVfrVarDataTypeDB::DeclareDataTypeEnd ( | |
| VOID | |
| ) | |
| { | |
| if (mNewDataType->mTypeName[0] == '\0') { | |
| return; | |
| } | |
| if ((mNewDataType->mTotalSize % mNewDataType->mAlign) !=0) { | |
| mNewDataType->mTotalSize += ALIGN_STUFF (mNewDataType->mTotalSize, mNewDataType->mAlign); | |
| } | |
| RegisterNewType (mNewDataType); | |
| if (mFirstNewDataTypeName == NULL) { | |
| mFirstNewDataTypeName = mNewDataType->mTypeName; | |
| } | |
| mNewDataType = NULL; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::GetDataType ( | |
| IN CHAR8 *TypeName, | |
| OUT SVfrDataType **DataType | |
| ) | |
| { | |
| SVfrDataType *pDataType = NULL; | |
| if (TypeName == NULL) { | |
| return VFR_RETURN_ERROR_SKIPED; | |
| } | |
| if (DataType == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| *DataType = NULL; | |
| for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { | |
| if (strcmp (TypeName, pDataType->mTypeName) == 0) { | |
| *DataType = pDataType; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::GetDataTypeSize ( | |
| IN UINT8 DataType, | |
| OUT UINT32 *Size | |
| ) | |
| { | |
| SVfrDataType *pDataType = NULL; | |
| if (Size == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| *Size = 0; | |
| DataType = DataType & 0x0F; | |
| // | |
| // For user defined data type, the size can't be got by this function. | |
| // | |
| if (DataType == EFI_IFR_TYPE_OTHER) { | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { | |
| if (DataType == pDataType->mType) { | |
| *Size = pDataType->mTotalSize; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::GetDataTypeSize ( | |
| IN CHAR8 *TypeName, | |
| OUT UINT32 *Size | |
| ) | |
| { | |
| SVfrDataType *pDataType = NULL; | |
| if (Size == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| *Size = 0; | |
| for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { | |
| if (strcmp (TypeName, pDataType->mTypeName) == 0) { | |
| *Size = pDataType->mTotalSize; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::GetDataFieldInfo ( | |
| IN CHAR8 *VarStr, | |
| OUT UINT16 &Offset, | |
| OUT UINT8 &Type, | |
| OUT UINT32 &Size | |
| ) | |
| { | |
| CHAR8 TName[MAX_NAME_LEN], FName[MAX_NAME_LEN]; | |
| UINT32 ArrayIdx, Tmp; | |
| SVfrDataType *pType = NULL; | |
| SVfrDataField *pField = NULL; | |
| Offset = 0; | |
| Type = EFI_IFR_TYPE_OTHER; | |
| Size = 0; | |
| CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS); | |
| CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS); | |
| // | |
| // if it is not struct data type | |
| // | |
| Type = pType->mType; | |
| Size = pType->mTotalSize; | |
| 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; | |
| CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp), VFR_RETURN_SUCCESS); | |
| Offset = (UINT16) (Offset + Tmp); | |
| Type = GetFieldWidth (pField); | |
| Size = GetFieldSize (pField, ArrayIdx); | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrVarDataTypeDB::GetUserDefinedTypeNameList ( | |
| OUT CHAR8 ***NameList, | |
| OUT UINT32 *ListSize | |
| ) | |
| { | |
| UINT32 Index; | |
| SVfrDataType *pType; | |
| if ((NameList == NULL) || (ListSize == NULL)) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| *NameList = NULL; | |
| *ListSize = 0; | |
| for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { | |
| if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) { | |
| (*ListSize)++; | |
| } | |
| } | |
| if (*ListSize == 0) { | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| if ((*NameList = new CHAR8*[*ListSize]) == NULL) { | |
| *ListSize = 0; | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| for (Index = 0, pType = mDataTypeList; pType != NULL; pType = pType->mNext, Index++) { | |
| if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) { | |
| (*NameList)[Index] = pType->mTypeName; | |
| } | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| BOOLEAN | |
| CVfrVarDataTypeDB::IsTypeNameDefined ( | |
| IN CHAR8 *TypeName | |
| ) | |
| { | |
| SVfrDataType *pType; | |
| if (TypeName == NULL) { | |
| return FALSE; | |
| } | |
| for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { | |
| if (strcmp (pType->mTypeName, TypeName) == 0) { | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| VOID | |
| CVfrVarDataTypeDB::Dump ( | |
| IN FILE *File | |
| ) | |
| { | |
| SVfrDataType *pTNode; | |
| SVfrDataField *pFNode; | |
| fprintf (File, "\n\n***************************************************************\n"); | |
| fprintf (File, "\t\tmPackAlign = %x\n", mPackAlign); | |
| for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) { | |
| fprintf (File, "\t\tstruct %s : mAlign [%d] mTotalSize [0x%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize); | |
| 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, | |
| pFNode->mFieldName, pFNode->mArrayNum, pFNode->mFieldType->mTypeName); | |
| } else { | |
| fprintf (File, "\t\t\t+%08d[%08x] %s <%s>\n", pFNode->mOffset, pFNode->mOffset, | |
| pFNode->mFieldName, pFNode->mFieldType->mTypeName); | |
| } | |
| } | |
| fprintf (File, "\t\t};\n"); | |
| fprintf (File, "---------------------------------------------------------------\n"); | |
| } | |
| fprintf (File, "***************************************************************\n"); | |
| } | |
| #ifdef CVFR_VARDATATYPEDB_DEBUG | |
| VOID | |
| CVfrVarDataTypeDB::ParserDB ( | |
| VOID | |
| ) | |
| { | |
| SVfrDataType *pTNode; | |
| SVfrDataField *pFNode; | |
| printf ("***************************************************************\n"); | |
| printf ("\t\tmPackAlign = %x\n", mPackAlign); | |
| for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) { | |
| printf ("\t\tstruct %s : mAlign [%x] mTotalSize [%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize); | |
| printf ("\t\tstruct %s {\n", pTNode->mTypeName); | |
| for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) { | |
| printf ("\t\t\t%s\t%s\n", pFNode->mFieldType->mTypeName, pFNode->mFieldName); | |
| } | |
| printf ("\t\t};\n"); | |
| printf ("---------------------------------------------------------------\n"); | |
| } | |
| printf ("***************************************************************\n"); | |
| } | |
| #endif | |
| SVfrVarStorageNode::SVfrVarStorageNode ( | |
| IN EFI_GUID *Guid, | |
| IN CHAR8 *StoreName, | |
| IN EFI_VARSTORE_ID VarStoreId, | |
| IN EFI_STRING_ID VarName, | |
| IN UINT32 VarSize, | |
| IN BOOLEAN Flag | |
| ) | |
| { | |
| if (Guid != NULL) { | |
| mGuid = *Guid; | |
| } else { | |
| memset (&Guid, 0, sizeof (EFI_GUID)); | |
| } | |
| if (StoreName != NULL) { | |
| mVarStoreName = new CHAR8[strlen(StoreName) + 1]; | |
| strcpy (mVarStoreName, StoreName); | |
| } else { | |
| mVarStoreName = NULL; | |
| } | |
| mNext = NULL; | |
| mVarStoreId = VarStoreId; | |
| mVarStoreType = EFI_VFR_VARSTORE_EFI; | |
| mStorageInfo.mEfiVar.mEfiVarName = VarName; | |
| mStorageInfo.mEfiVar.mEfiVarSize = VarSize; | |
| mAssignedFlag = Flag; | |
| } | |
| SVfrVarStorageNode::SVfrVarStorageNode ( | |
| IN EFI_GUID *Guid, | |
| IN CHAR8 *StoreName, | |
| IN EFI_VARSTORE_ID VarStoreId, | |
| IN SVfrDataType *DataType, | |
| IN BOOLEAN Flag | |
| ) | |
| { | |
| if (Guid != NULL) { | |
| mGuid = *Guid; | |
| } else { | |
| memset (&Guid, 0, sizeof (EFI_GUID)); | |
| } | |
| if (StoreName != NULL) { | |
| mVarStoreName = new CHAR8[strlen(StoreName) + 1]; | |
| strcpy (mVarStoreName, StoreName); | |
| } else { | |
| mVarStoreName = NULL; | |
| } | |
| mNext = NULL; | |
| mVarStoreId = VarStoreId; | |
| mVarStoreType = EFI_VFR_VARSTORE_BUFFER; | |
| mStorageInfo.mDataType = DataType; | |
| mAssignedFlag = Flag; | |
| } | |
| SVfrVarStorageNode::SVfrVarStorageNode ( | |
| IN CHAR8 *StoreName, | |
| IN EFI_VARSTORE_ID VarStoreId | |
| ) | |
| { | |
| if (StoreName != NULL) { | |
| mVarStoreName = new CHAR8[strlen(StoreName) + 1]; | |
| strcpy (mVarStoreName, StoreName); | |
| } else { | |
| mVarStoreName = NULL; | |
| } | |
| mNext = NULL; | |
| mVarStoreId = VarStoreId; | |
| mVarStoreType = EFI_VFR_VARSTORE_NAME; | |
| mStorageInfo.mNameSpace.mNameTable = new EFI_VARSTORE_ID[DEFAULT_NAME_TABLE_ITEMS]; | |
| mStorageInfo.mNameSpace.mTableSize = 0; | |
| } | |
| SVfrVarStorageNode::~SVfrVarStorageNode ( | |
| VOID | |
| ) | |
| { | |
| if (mVarStoreName != NULL) { | |
| delete mVarStoreName; | |
| } | |
| if (mVarStoreType == EFI_VFR_VARSTORE_NAME) { | |
| delete mStorageInfo.mNameSpace.mNameTable; | |
| } | |
| } | |
| CVfrDataStorage::CVfrDataStorage ( | |
| VOID | |
| ) | |
| { | |
| UINT32 Index; | |
| for (Index = 0; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) { | |
| mFreeVarStoreIdBitMap[Index] = 0; | |
| } | |
| // Question ID 0 is reserved. | |
| mFreeVarStoreIdBitMap[0] = 0x80000000; | |
| mBufferVarStoreList = NULL; | |
| mEfiVarStoreList = NULL; | |
| mNameVarStoreList = NULL; | |
| mCurrVarStorageNode = NULL; | |
| mNewVarStorageNode = NULL; | |
| mBufferFieldInfoListHead = NULL; | |
| mBufferFieldInfoListTail = NULL; | |
| } | |
| CVfrDataStorage::~CVfrDataStorage ( | |
| VOID | |
| ) | |
| { | |
| SVfrVarStorageNode *pNode; | |
| while (mBufferVarStoreList != NULL) { | |
| pNode = mBufferVarStoreList; | |
| mBufferVarStoreList = mBufferVarStoreList->mNext; | |
| delete pNode; | |
| } | |
| while (mEfiVarStoreList != NULL) { | |
| pNode = mEfiVarStoreList; | |
| mEfiVarStoreList = mEfiVarStoreList->mNext; | |
| delete pNode; | |
| } | |
| while (mNameVarStoreList != NULL) { | |
| pNode = mNameVarStoreList; | |
| mNameVarStoreList = mNameVarStoreList->mNext; | |
| delete pNode; | |
| } | |
| if (mNewVarStorageNode != NULL) { | |
| delete mNewVarStorageNode; | |
| } | |
| } | |
| EFI_VARSTORE_ID | |
| CVfrDataStorage::GetFreeVarStoreId ( | |
| EFI_VFR_VARSTORE_TYPE VarType | |
| ) | |
| { | |
| UINT32 Index, Mask, Offset; | |
| // | |
| // 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) { | |
| Index = 1; | |
| } else if (VarType == EFI_VFR_VARSTORE_NAME) { | |
| Index = 2; | |
| } | |
| for (; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) { | |
| if (mFreeVarStoreIdBitMap[Index] != 0xFFFFFFFF) { | |
| break; | |
| } | |
| } | |
| for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { | |
| if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) { | |
| mFreeVarStoreIdBitMap[Index] |= Mask; | |
| return (EFI_VARSTORE_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset); | |
| } | |
| } | |
| return EFI_VARSTORE_ID_INVALID; | |
| } | |
| BOOLEAN | |
| CVfrDataStorage::ChekVarStoreIdFree ( | |
| IN EFI_VARSTORE_ID VarStoreId | |
| ) | |
| { | |
| UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); | |
| UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); | |
| return (mFreeVarStoreIdBitMap[Index] & (0x80000000 >> Offset)) == 0; | |
| } | |
| VOID | |
| CVfrDataStorage::MarkVarStoreIdUsed ( | |
| IN EFI_VARSTORE_ID VarStoreId | |
| ) | |
| { | |
| UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); | |
| UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); | |
| mFreeVarStoreIdBitMap[Index] |= (0x80000000 >> Offset); | |
| } | |
| VOID | |
| CVfrDataStorage::MarkVarStoreIdUnused ( | |
| IN EFI_VARSTORE_ID VarStoreId | |
| ) | |
| { | |
| UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); | |
| UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); | |
| mFreeVarStoreIdBitMap[Index] &= ~(0x80000000 >> Offset); | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDataStorage::DeclareNameVarStoreBegin ( | |
| IN CHAR8 *StoreName, | |
| IN EFI_VARSTORE_ID VarStoreId | |
| ) | |
| { | |
| SVfrVarStorageNode *pNode = NULL; | |
| EFI_VARSTORE_ID TmpVarStoreId; | |
| if (StoreName == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| 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); | |
| } | |
| if ((pNode = new SVfrVarStorageNode (StoreName, VarStoreId)) == NULL) { | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| mNewVarStorageNode = pNode; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDataStorage::NameTableAddItem ( | |
| IN EFI_STRING_ID Item | |
| ) | |
| { | |
| EFI_VARSTORE_ID *NewTable, *OldTable; | |
| UINT32 TableSize; | |
| OldTable = mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable; | |
| TableSize = mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize; | |
| if ((TableSize != 0) && ((TableSize % DEFAULT_NAME_TABLE_ITEMS) == 0)) { | |
| if ((NewTable = new EFI_VARSTORE_ID[TableSize + DEFAULT_NAME_TABLE_ITEMS]) == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| memcpy (NewTable, OldTable, TableSize); | |
| mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable = NewTable; | |
| } | |
| mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable[TableSize++] = Item; | |
| mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize = TableSize; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDataStorage::DeclareNameVarStoreEnd ( | |
| IN EFI_GUID *Guid | |
| ) | |
| { | |
| mNewVarStorageNode->mGuid = *Guid; | |
| mNewVarStorageNode->mNext = mNameVarStoreList; | |
| mNameVarStoreList = mNewVarStorageNode; | |
| mNewVarStorageNode = NULL; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDataStorage::DeclareEfiVarStore ( | |
| IN CHAR8 *StoreName, | |
| IN EFI_GUID *Guid, | |
| IN EFI_STRING_ID NameStrId, | |
| IN UINT32 VarSize, | |
| IN BOOLEAN Flag | |
| ) | |
| { | |
| SVfrVarStorageNode *pNode; | |
| EFI_VARSTORE_ID VarStoreId; | |
| if ((StoreName == NULL) || (Guid == NULL)) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| if (VarSize > sizeof (UINT64)) { | |
| return VFR_RETURN_EFIVARSTORE_SIZE_ERROR; | |
| } | |
| if (GetVarStoreId (StoreName, &VarStoreId, Guid) == VFR_RETURN_SUCCESS) { | |
| return VFR_RETURN_REDEFINED; | |
| } | |
| VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI); | |
| if ((pNode = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, NameStrId, VarSize, Flag)) == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| pNode->mNext = mEfiVarStoreList; | |
| mEfiVarStoreList = pNode; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDataStorage::DeclareBufferVarStore ( | |
| IN CHAR8 *StoreName, | |
| IN EFI_GUID *Guid, | |
| IN CVfrVarDataTypeDB *DataTypeDB, | |
| IN CHAR8 *TypeName, | |
| IN EFI_VARSTORE_ID VarStoreId, | |
| 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) { | |
| VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_BUFFER); | |
| } else { | |
| if (ChekVarStoreIdFree (VarStoreId) == FALSE) { | |
| return VFR_RETURN_VARSTOREID_REDEFINED; | |
| } | |
| MarkVarStoreIdUsed (VarStoreId); | |
| } | |
| if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, Flag)) == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| pNew->mNext = mBufferVarStoreList; | |
| mBufferVarStoreList = pNew; | |
| 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, | |
| 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) { | |
| 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) { | |
| 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) { | |
| if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { | |
| *VarStoreId = mCurrVarStorageNode->mVarStoreId; | |
| return ReturnCode; | |
| } | |
| } | |
| } | |
| 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 EFI_VARSTORE_ID VarStoreId, | |
| OUT CHAR8 **DataTypeName | |
| ) | |
| { | |
| SVfrVarStorageNode *pNode; | |
| if (VarStoreId == EFI_VARSTORE_ID_INVALID) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mVarStoreId == VarStoreId) { | |
| *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| EFI_VFR_VARSTORE_TYPE | |
| CVfrDataStorage::GetVarStoreType ( | |
| IN EFI_VARSTORE_ID VarStoreId | |
| ) | |
| { | |
| SVfrVarStorageNode *pNode; | |
| EFI_VFR_VARSTORE_TYPE VarStoreType; | |
| VarStoreType = EFI_VFR_VARSTORE_INVALID; | |
| if (VarStoreId == EFI_VARSTORE_ID_INVALID) { | |
| return VarStoreType; | |
| } | |
| for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mVarStoreId == VarStoreId) { | |
| VarStoreType = pNode->mVarStoreType; | |
| return VarStoreType; | |
| } | |
| } | |
| for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mVarStoreId == VarStoreId) { | |
| VarStoreType = pNode->mVarStoreType; | |
| return VarStoreType; | |
| } | |
| } | |
| for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mVarStoreId == VarStoreId) { | |
| VarStoreType = pNode->mVarStoreType; | |
| return VarStoreType; | |
| } | |
| } | |
| 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, | |
| OUT CHAR8 **VarStoreName | |
| ) | |
| { | |
| SVfrVarStorageNode *pNode; | |
| if (VarStoreName == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mVarStoreId == VarStoreId) { | |
| *VarStoreName = pNode->mVarStoreName; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mVarStoreId == VarStoreId) { | |
| *VarStoreName = pNode->mVarStoreName; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mVarStoreId == VarStoreId) { | |
| *VarStoreName = pNode->mVarStoreName; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| *VarStoreName = NULL; | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDataStorage::GetEfiVarStoreInfo ( | |
| IN OUT EFI_VARSTORE_INFO *Info | |
| ) | |
| { | |
| if (Info == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| if (mCurrVarStorageNode == NULL) { | |
| return VFR_RETURN_GET_EFIVARSTORE_ERROR; | |
| } | |
| Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarName; | |
| Info->mVarTotalSize = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarSize; | |
| switch (Info->mVarTotalSize) { | |
| case 1: | |
| Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_8; | |
| break; | |
| case 2: | |
| Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_16; | |
| break; | |
| case 4: | |
| Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_32; | |
| break; | |
| case 8: | |
| Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_64; | |
| break; | |
| default : | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| 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, | |
| IN UINT32 Index | |
| ) | |
| { | |
| if (Info == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| if (mCurrVarStorageNode == NULL) { | |
| return VFR_RETURN_GET_NVVARSTORE_ERROR; | |
| } | |
| // | |
| // Framework Vfr file Index is from 1, but Uefi Vfr file Index is from 0. | |
| // | |
| if (VfrCompatibleMode) { | |
| if (Index == 0) { | |
| return VFR_RETURN_ERROR_ARRARY_NUM; | |
| } | |
| Index --; | |
| } | |
| Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mNameSpace.mNameTable[Index]; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| SVfrDefaultStoreNode::SVfrDefaultStoreNode ( | |
| IN EFI_IFR_DEFAULTSTORE *ObjBinAddr, | |
| IN CHAR8 *RefName, | |
| IN EFI_STRING_ID DefaultStoreNameId, | |
| IN UINT16 DefaultId | |
| ) | |
| { | |
| mObjBinAddr = ObjBinAddr; | |
| if (RefName != NULL) { | |
| mRefName = new CHAR8[strlen (RefName) + 1]; | |
| strcpy (mRefName, RefName); | |
| } else { | |
| mRefName = NULL; | |
| } | |
| mNext = NULL; | |
| mDefaultId = DefaultId; | |
| mDefaultStoreNameId = DefaultStoreNameId; | |
| } | |
| SVfrDefaultStoreNode::~SVfrDefaultStoreNode ( | |
| VOID | |
| ) | |
| { | |
| if (mRefName != NULL) { | |
| delete mRefName; | |
| } | |
| } | |
| CVfrDefaultStore::CVfrDefaultStore ( | |
| VOID | |
| ) | |
| { | |
| mDefaultStoreList = NULL; | |
| } | |
| CVfrDefaultStore::~CVfrDefaultStore ( | |
| VOID | |
| ) | |
| { | |
| SVfrDefaultStoreNode *pTmp = NULL; | |
| while (mDefaultStoreList != NULL) { | |
| pTmp = mDefaultStoreList; | |
| mDefaultStoreList = mDefaultStoreList->mNext; | |
| delete pTmp; | |
| } | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDefaultStore::RegisterDefaultStore ( | |
| IN CHAR8 *ObjBinAddr, | |
| IN CHAR8 *RefName, | |
| IN EFI_STRING_ID DefaultStoreNameId, | |
| IN UINT16 DefaultId | |
| ) | |
| { | |
| SVfrDefaultStoreNode *pNode = NULL; | |
| if (RefName == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (strcmp (pNode->mRefName, RefName) == 0) { | |
| return VFR_RETURN_REDEFINED; | |
| } | |
| } | |
| if ((pNode = new SVfrDefaultStoreNode ((EFI_IFR_DEFAULTSTORE *)ObjBinAddr, RefName, DefaultStoreNameId, DefaultId)) == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| pNode->mNext = mDefaultStoreList; | |
| mDefaultStoreList = pNode; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| /* | |
| * assign new reference name or new default store name id only if | |
| * the original is invalid | |
| */ | |
| EFI_VFR_RETURN_CODE | |
| CVfrDefaultStore::ReRegisterDefaultStoreById ( | |
| IN UINT16 DefaultId, | |
| IN CHAR8 *RefName, | |
| IN EFI_STRING_ID DefaultStoreNameId | |
| ) | |
| { | |
| SVfrDefaultStoreNode *pNode = NULL; | |
| for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mDefaultId == DefaultId) { | |
| break; | |
| } | |
| } | |
| if (pNode == NULL) { | |
| return VFR_RETURN_UNDEFINED; | |
| } else { | |
| if (pNode->mDefaultStoreNameId == EFI_STRING_ID_INVALID) { | |
| pNode->mDefaultStoreNameId = DefaultStoreNameId; | |
| if (pNode->mObjBinAddr != NULL) { | |
| pNode->mObjBinAddr->DefaultName = DefaultStoreNameId; | |
| } | |
| } else { | |
| return VFR_RETURN_REDEFINED; | |
| } | |
| if (RefName != NULL) { | |
| delete pNode->mRefName; | |
| pNode->mRefName = new CHAR8[strlen (RefName) + 1]; | |
| if (pNode->mRefName != NULL) { | |
| strcpy (pNode->mRefName, RefName); | |
| } | |
| } | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| BOOLEAN | |
| CVfrDefaultStore::DefaultIdRegistered ( | |
| IN UINT16 DefaultId | |
| ) | |
| { | |
| SVfrDefaultStoreNode *pNode = NULL; | |
| for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mDefaultId == DefaultId) { | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrDefaultStore::GetDefaultId ( | |
| IN CHAR8 *RefName, | |
| OUT UINT16 *DefaultId | |
| ) | |
| { | |
| SVfrDefaultStoreNode *pTmp = NULL; | |
| if (DefaultId == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| for (pTmp = mDefaultStoreList; pTmp != NULL; pTmp = pTmp->mNext) { | |
| if (strcmp (pTmp->mRefName, RefName) == 0) { | |
| *DefaultId = pTmp->mDefaultId; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| 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 | |
| ) | |
| { | |
| SVfrDefaultStoreNode *pNode = NULL; | |
| CHAR8 NewAltCfg[2 * 2 * sizeof (UINT16) + 1] = {0,}; | |
| INTN Returnvalue = 0; | |
| if (VarStoreName == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mDefaultId == DefaultId) { | |
| break; | |
| } | |
| } | |
| if (pNode == NULL) { | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| gCVfrBufferConfig.Open (); | |
| sprintf (NewAltCfg, "%04x", pNode->mDefaultId); | |
| 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; | |
| WriteError: | |
| gCVfrBufferConfig.Close (); | |
| return (EFI_VFR_RETURN_CODE)Returnvalue; | |
| } | |
| SVfrRuleNode::SVfrRuleNode ( | |
| IN CHAR8 *RuleName, | |
| IN UINT8 RuleId | |
| ) | |
| { | |
| if (RuleName != NULL) { | |
| mRuleName = new CHAR8[strlen (RuleName) + 1]; | |
| strcpy (mRuleName, RuleName); | |
| } else { | |
| mRuleName = NULL; | |
| } | |
| mNext = NULL; | |
| mRuleId = RuleId; | |
| } | |
| SVfrRuleNode::~SVfrRuleNode ( | |
| VOID | |
| ) | |
| { | |
| if (mRuleName != NULL) { | |
| delete mRuleName; | |
| } | |
| } | |
| CVfrRulesDB::CVfrRulesDB () | |
| { | |
| mRuleList = NULL; | |
| mFreeRuleId = EFI_VARSTORE_ID_START; | |
| } | |
| CVfrRulesDB::~CVfrRulesDB () | |
| { | |
| SVfrRuleNode *pNode; | |
| while(mRuleList != NULL) { | |
| pNode = mRuleList; | |
| mRuleList = mRuleList->mNext; | |
| delete pNode; | |
| } | |
| } | |
| VOID | |
| CVfrRulesDB::RegisterRule ( | |
| IN CHAR8 *RuleName | |
| ) | |
| { | |
| SVfrRuleNode *pNew; | |
| if (RuleName == NULL) { | |
| return ; | |
| } | |
| if ((pNew = new SVfrRuleNode (RuleName, mFreeRuleId)) == NULL) { | |
| return ; | |
| } | |
| mFreeRuleId++; | |
| pNew->mNext = mRuleList; | |
| mRuleList = pNew; | |
| } | |
| UINT8 | |
| CVfrRulesDB::GetRuleId ( | |
| IN CHAR8 *RuleName | |
| ) | |
| { | |
| SVfrRuleNode *pNode; | |
| if (RuleName == NULL) { | |
| return EFI_RULE_ID_INVALID; | |
| } | |
| for (pNode = mRuleList; pNode != NULL; pNode = pNode->mNext) { | |
| if (strcmp (pNode->mRuleName, RuleName) == 0) { | |
| return pNode->mRuleId; | |
| } | |
| } | |
| return EFI_RULE_ID_INVALID; | |
| } | |
| CVfrRulesDB gCVfrRulesDB; | |
| EFI_VARSTORE_INFO::EFI_VARSTORE_INFO ( | |
| VOID | |
| ) | |
| { | |
| mVarStoreId = EFI_VARSTORE_ID_INVALID; | |
| mInfo.mVarName = EFI_STRING_ID_INVALID; | |
| mInfo.mVarOffset = EFI_VAROFFSET_INVALID; | |
| mVarType = EFI_IFR_TYPE_OTHER; | |
| mVarTotalSize = 0; | |
| } | |
| EFI_VARSTORE_INFO::EFI_VARSTORE_INFO ( | |
| IN EFI_VARSTORE_INFO &Info | |
| ) | |
| { | |
| mVarStoreId = Info.mVarStoreId; | |
| mInfo.mVarName = Info.mInfo.mVarName; | |
| mInfo.mVarOffset = Info.mInfo.mVarOffset; | |
| mVarType = Info.mVarType; | |
| mVarTotalSize = Info.mVarTotalSize; | |
| } | |
| BOOLEAN | |
| EFI_VARSTORE_INFO::operator == ( | |
| IN EFI_VARSTORE_INFO *Info | |
| ) | |
| { | |
| if ((mVarStoreId == Info->mVarStoreId) && | |
| (mInfo.mVarName == Info->mInfo.mVarName) && | |
| (mInfo.mVarOffset == Info->mInfo.mVarOffset) && | |
| (mVarType == Info->mVarType) && | |
| (mVarTotalSize == Info->mVarTotalSize)) { | |
| 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 | |
| CVfrQuestionDB::GetFreeQuestionId ( | |
| VOID | |
| ) | |
| { | |
| UINT32 Index, Mask, Offset; | |
| for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { | |
| if (mFreeQIdBitMap[Index] != 0xFFFFFFFF) { | |
| break; | |
| } | |
| } | |
| for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { | |
| if ((mFreeQIdBitMap[Index] & Mask) == 0) { | |
| mFreeQIdBitMap[Index] |= Mask; | |
| return (EFI_QUESTION_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset); | |
| } | |
| } | |
| return EFI_QUESTION_ID_INVALID; | |
| } | |
| BOOLEAN | |
| CVfrQuestionDB::ChekQuestionIdFree ( | |
| IN EFI_QUESTION_ID QId | |
| ) | |
| { | |
| UINT32 Index = (QId / EFI_BITS_PER_UINT32); | |
| UINT32 Offset = (QId % EFI_BITS_PER_UINT32); | |
| return (mFreeQIdBitMap[Index] & (0x80000000 >> Offset)) == 0; | |
| } | |
| VOID | |
| CVfrQuestionDB::MarkQuestionIdUsed ( | |
| IN EFI_QUESTION_ID QId | |
| ) | |
| { | |
| UINT32 Index = (QId / EFI_BITS_PER_UINT32); | |
| UINT32 Offset = (QId % EFI_BITS_PER_UINT32); | |
| mFreeQIdBitMap[Index] |= (0x80000000 >> Offset); | |
| } | |
| VOID | |
| CVfrQuestionDB::MarkQuestionIdUnused ( | |
| IN EFI_QUESTION_ID QId | |
| ) | |
| { | |
| UINT32 Index = (QId / EFI_BITS_PER_UINT32); | |
| UINT32 Offset = (QId % EFI_BITS_PER_UINT32); | |
| mFreeQIdBitMap[Index] &= ~(0x80000000 >> Offset); | |
| } | |
| SVfrQuestionNode::SVfrQuestionNode ( | |
| IN CHAR8 *Name, | |
| IN CHAR8 *VarIdStr, | |
| IN UINT32 BitMask | |
| ) | |
| { | |
| mName = NULL; | |
| mVarIdStr = NULL; | |
| mQuestionId = EFI_QUESTION_ID_INVALID; | |
| mBitMask = BitMask; | |
| mNext = NULL; | |
| mQtype = QUESTION_NORMAL; | |
| if (Name == NULL) { | |
| mName = new CHAR8[strlen ("$DEFAULT") + 1]; | |
| strcpy (mName, "$DEFAULT"); | |
| } else { | |
| mName = new CHAR8[strlen (Name) + 1]; | |
| strcpy (mName, Name); | |
| } | |
| if (VarIdStr != NULL) { | |
| mVarIdStr = new CHAR8[strlen (VarIdStr) + 1]; | |
| strcpy (mVarIdStr, VarIdStr); | |
| } else { | |
| mVarIdStr = new CHAR8[strlen ("$") + 1]; | |
| strcpy (mVarIdStr, "$"); | |
| } | |
| } | |
| SVfrQuestionNode::~SVfrQuestionNode ( | |
| VOID | |
| ) | |
| { | |
| if (mName != NULL) { | |
| delete mName; | |
| } | |
| if (mVarIdStr != NULL) { | |
| delete mVarIdStr; | |
| } | |
| } | |
| CVfrQuestionDB::CVfrQuestionDB () | |
| { | |
| UINT32 Index; | |
| for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { | |
| mFreeQIdBitMap[Index] = 0; | |
| } | |
| // Question ID 0 is reserved. | |
| mFreeQIdBitMap[0] = 0x80000000; | |
| mQuestionList = NULL; | |
| } | |
| CVfrQuestionDB::~CVfrQuestionDB () | |
| { | |
| SVfrQuestionNode *pNode; | |
| while (mQuestionList != NULL) { | |
| pNode = mQuestionList; | |
| mQuestionList = mQuestionList->mNext; | |
| delete pNode; | |
| } | |
| } | |
| // | |
| // Reset to init state | |
| // | |
| VOID | |
| CVfrQuestionDB::ResetInit( | |
| IN VOID | |
| ) | |
| { | |
| UINT32 Index; | |
| SVfrQuestionNode *pNode; | |
| while (mQuestionList != NULL) { | |
| pNode = mQuestionList; | |
| mQuestionList = mQuestionList->mNext; | |
| delete pNode; | |
| } | |
| for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { | |
| mFreeQIdBitMap[Index] = 0; | |
| } | |
| // Question ID 0 is reserved. | |
| mFreeQIdBitMap[0] = 0x80000000; | |
| mQuestionList = NULL; | |
| } | |
| VOID | |
| CVfrQuestionDB::PrintAllQuestion ( | |
| VOID | |
| ) | |
| { | |
| 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); | |
| } | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrQuestionDB::RegisterQuestion ( | |
| IN CHAR8 *Name, | |
| IN CHAR8 *VarIdStr, | |
| IN OUT EFI_QUESTION_ID &QuestionId | |
| ) | |
| { | |
| SVfrQuestionNode *pNode = NULL; | |
| if ((Name != NULL) && (FindQuestion(Name) == VFR_RETURN_SUCCESS)) { | |
| return VFR_RETURN_REDEFINED; | |
| } | |
| if ((pNode = new SVfrQuestionNode (Name, VarIdStr)) == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| if (QuestionId == EFI_QUESTION_ID_INVALID) { | |
| QuestionId = GetFreeQuestionId (); | |
| } else { | |
| // | |
| // For Framework Vfr, don't check question ID conflict. | |
| // | |
| if (!VfrCompatibleMode && ChekQuestionIdFree (QuestionId) == FALSE) { | |
| delete pNode; | |
| return VFR_RETURN_QUESTIONID_REDEFINED; | |
| } | |
| MarkQuestionIdUsed (QuestionId); | |
| } | |
| pNode->mQuestionId = QuestionId; | |
| pNode->mNext = mQuestionList; | |
| mQuestionList = pNode; | |
| gCFormPkg.DoPendingAssign (VarIdStr, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| VOID | |
| CVfrQuestionDB::RegisterOldDateQuestion ( | |
| IN CHAR8 *YearVarId, | |
| IN CHAR8 *MonthVarId, | |
| IN CHAR8 *DayVarId, | |
| IN OUT EFI_QUESTION_ID &QuestionId | |
| ) | |
| { | |
| SVfrQuestionNode *pNode[3] = {NULL, }; | |
| UINT32 Index; | |
| if ((YearVarId == NULL) || (MonthVarId == NULL) || (DayVarId == NULL)) { | |
| return; | |
| } | |
| if ((pNode[0] = new SVfrQuestionNode (NULL, YearVarId, DATE_YEAR_BITMASK)) == NULL) { | |
| goto Err; | |
| } | |
| if ((pNode[1] = new SVfrQuestionNode (NULL, MonthVarId, DATE_MONTH_BITMASK)) == NULL) { | |
| goto Err; | |
| } | |
| if ((pNode[2] = new SVfrQuestionNode (NULL, DayVarId, DATE_DAY_BITMASK)) == 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[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; | |
| mQuestionList = pNode[0]; | |
| gCFormPkg.DoPendingAssign (YearVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); | |
| gCFormPkg.DoPendingAssign (MonthVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); | |
| gCFormPkg.DoPendingAssign (DayVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); | |
| return; | |
| Err: | |
| for (Index = 0; Index < 3; Index++) { | |
| if (pNode[Index] != NULL) { | |
| delete pNode[Index]; | |
| } | |
| } | |
| QuestionId = EFI_QUESTION_ID_INVALID; | |
| } | |
| VOID | |
| CVfrQuestionDB::RegisterNewDateQuestion ( | |
| IN CHAR8 *Name, | |
| IN CHAR8 *BaseVarId, | |
| IN OUT EFI_QUESTION_ID &QuestionId | |
| ) | |
| { | |
| SVfrQuestionNode *pNode[3] = {NULL, }; | |
| UINT32 Len; | |
| CHAR8 *VarIdStr[3] = {NULL, }; | |
| CHAR8 Index; | |
| if (BaseVarId == NULL && Name == NULL) { | |
| if (QuestionId == EFI_QUESTION_ID_INVALID) { | |
| QuestionId = GetFreeQuestionId (); | |
| } else { | |
| if (ChekQuestionIdFree (QuestionId) == FALSE) { | |
| goto Err; | |
| } | |
| MarkQuestionIdUsed (QuestionId); | |
| } | |
| return; | |
| } | |
| 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"); | |
| } | |
| } 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) { | |
| goto Err; | |
| } | |
| if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], DATE_MONTH_BITMASK)) == NULL) { | |
| goto Err; | |
| } | |
| if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], DATE_DAY_BITMASK)) == 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[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; | |
| mQuestionList = pNode[0]; | |
| for (Index = 0; Index < 3; Index++) { | |
| if (VarIdStr[Index] != NULL) { | |
| delete VarIdStr[Index]; | |
| } | |
| } | |
| 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)); | |
| return; | |
| Err: | |
| for (Index = 0; Index < 3; Index++) { | |
| if (pNode[Index] != NULL) { | |
| delete pNode[Index]; | |
| } | |
| if (VarIdStr[Index] != NULL) { | |
| delete VarIdStr[Index]; | |
| } | |
| } | |
| } | |
| VOID | |
| CVfrQuestionDB::RegisterOldTimeQuestion ( | |
| IN CHAR8 *HourVarId, | |
| IN CHAR8 *MinuteVarId, | |
| IN CHAR8 *SecondVarId, | |
| IN OUT EFI_QUESTION_ID &QuestionId | |
| ) | |
| { | |
| SVfrQuestionNode *pNode[3] = {NULL, }; | |
| UINT32 Index; | |
| if ((HourVarId == NULL) || (MinuteVarId == NULL) || (SecondVarId == NULL)) { | |
| return; | |
| } | |
| if ((pNode[0] = new SVfrQuestionNode (NULL, HourVarId, TIME_HOUR_BITMASK)) == NULL) { | |
| goto Err; | |
| } | |
| if ((pNode[1] = new SVfrQuestionNode (NULL, MinuteVarId, TIME_MINUTE_BITMASK)) == NULL) { | |
| goto Err; | |
| } | |
| if ((pNode[2] = new SVfrQuestionNode (NULL, SecondVarId, TIME_SECOND_BITMASK)) == 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[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; | |
| mQuestionList = pNode[0]; | |
| gCFormPkg.DoPendingAssign (HourVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); | |
| gCFormPkg.DoPendingAssign (MinuteVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); | |
| gCFormPkg.DoPendingAssign (SecondVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); | |
| return; | |
| Err: | |
| for (Index = 0; Index < 3; Index++) { | |
| if (pNode[Index] != NULL) { | |
| delete pNode[Index]; | |
| } | |
| } | |
| QuestionId = EFI_QUESTION_ID_INVALID; | |
| } | |
| VOID | |
| CVfrQuestionDB::RegisterNewTimeQuestion ( | |
| IN CHAR8 *Name, | |
| IN CHAR8 *BaseVarId, | |
| IN OUT EFI_QUESTION_ID &QuestionId | |
| ) | |
| { | |
| SVfrQuestionNode *pNode[3] = {NULL, }; | |
| UINT32 Len; | |
| CHAR8 *VarIdStr[3] = {NULL, }; | |
| CHAR8 Index; | |
| if (BaseVarId == NULL && Name == NULL) { | |
| if (QuestionId == EFI_QUESTION_ID_INVALID) { | |
| QuestionId = GetFreeQuestionId (); | |
| } else { | |
| if (ChekQuestionIdFree (QuestionId) == FALSE) { | |
| goto Err; | |
| } | |
| MarkQuestionIdUsed (QuestionId); | |
| } | |
| return; | |
| } | |
| 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"); | |
| } | |
| } 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) { | |
| goto Err; | |
| } | |
| if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], TIME_MINUTE_BITMASK)) == NULL) { | |
| goto Err; | |
| } | |
| if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], TIME_SECOND_BITMASK)) == 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[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; | |
| mQuestionList = pNode[0]; | |
| for (Index = 0; Index < 3; Index++) { | |
| if (VarIdStr[Index] != NULL) { | |
| delete VarIdStr[Index]; | |
| } | |
| } | |
| 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)); | |
| return; | |
| Err: | |
| for (Index = 0; Index < 3; Index++) { | |
| if (pNode[Index] != NULL) { | |
| delete pNode[Index]; | |
| } | |
| if (VarIdStr[Index] != NULL) { | |
| delete VarIdStr[Index]; | |
| } | |
| } | |
| } | |
| 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, | |
| IN EFI_QUESTION_ID NewQId | |
| ) | |
| { | |
| 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; | |
| } | |
| for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mQuestionId == QId) { | |
| break; | |
| } | |
| } | |
| if (pNode == NULL) { | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| MarkQuestionIdUnused (QId); | |
| pNode->mQuestionId = NewQId; | |
| MarkQuestionIdUsed (NewQId); | |
| gCFormPkg.DoPendingAssign (pNode->mVarIdStr, (VOID *)&NewQId, sizeof(EFI_QUESTION_ID)); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| VOID | |
| CVfrQuestionDB::GetQuestionId ( | |
| IN CHAR8 *Name, | |
| IN CHAR8 *VarIdStr, | |
| OUT EFI_QUESTION_ID &QuestionId, | |
| 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 ; | |
| } | |
| for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { | |
| if (Name != NULL) { | |
| if (strcmp (pNode->mName, Name) != 0) { | |
| continue; | |
| } | |
| } | |
| if (VarIdStr != NULL) { | |
| if (strcmp (pNode->mVarIdStr, VarIdStr) != 0) { | |
| continue; | |
| } | |
| } | |
| QuestionId = pNode->mQuestionId; | |
| BitMask = pNode->mBitMask; | |
| if (QType != NULL) { | |
| *QType = pNode->mQtype; | |
| } | |
| break; | |
| } | |
| return ; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrQuestionDB::FindQuestion ( | |
| IN EFI_QUESTION_ID QuestionId | |
| ) | |
| { | |
| SVfrQuestionNode *pNode; | |
| if (QuestionId == EFI_QUESTION_ID_INVALID) { | |
| return VFR_RETURN_INVALID_PARAMETER; | |
| } | |
| for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mQuestionId == QuestionId) { | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| return VFR_RETURN_UNDEFINED; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CVfrQuestionDB::FindQuestion ( | |
| IN CHAR8 *Name | |
| ) | |
| { | |
| SVfrQuestionNode *pNode; | |
| if (Name == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { | |
| if (strcmp (pNode->mName, Name) == 0) { | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| } | |
| 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 == '\0' ) { | |
| 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; | |