summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp')
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp3921
1 files changed, 3921 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
new file mode 100644
index 00000000..899f7123
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
@@ -0,0 +1,3921 @@
+/** @file
+
+ Vfr common library functions.
+
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "assert.h"
+#include "CommonLib.h"
+#include "VfrUtilityLib.h"
+#include "VfrFormPkg.h"
+
+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
+ )
+{
+ ARRAY_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;
+
+ ARRAY_SAFE_FREE (mName);
+ ARRAY_SAFE_FREE (mGuid);
+ ARRAY_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;
+}
+
+/**
+ Check whether the DataType contain bit field.
+
+ @param TypeName The name of the type.
+
+**/
+BOOLEAN
+CVfrVarDataTypeDB::DataTypeHasBitField (
+ IN CHAR8 *TypeName
+ )
+{
+ SVfrDataType *pType = NULL;
+ SVfrDataField *pTmp;
+
+ GetDataType (TypeName, &pType);
+
+ if (pType == NULL){
+ return FALSE;
+ }
+ for (pTmp = pType->mMembers; pTmp!= NULL; pTmp = pTmp->mNext) {
+ if (pTmp->mIsBitField) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Check whether the field is bit field or not.
+
+ @param VarStr Point to the field name which may contain the structure name.
+
+**/
+BOOLEAN
+CVfrVarDataTypeDB::IsThisBitField (
+ IN CHAR8 *VarStr
+ )
+{
+ CHAR8 FName[MAX_NAME_LEN];
+ CHAR8 TName[MAX_NAME_LEN];
+ UINT32 ArrayIdx;
+ SVfrDataType *pType = NULL;
+ SVfrDataField *pField = NULL;
+
+ CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS);
+ CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS);
+
+ while (*VarStr != '\0') {
+ CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS);
+ CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS);
+ pType = pField->mFieldType;
+ }
+ if (pField != NULL && pField->mIsBitField) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+EFI_VFR_RETURN_CODE
+CVfrVarDataTypeDB::ExtractFieldNameAndArrary (
+ IN CHAR8 *&VarStr,
+ 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++;
+ /* fall through */
+ 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,
+ IN BOOLEAN IsBitField
+ )
+{
+ if (Field == NULL) {
+ return VFR_RETURN_FATAL_ERROR;
+ }
+
+ 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;
+ // }
+ //
+ if (IsBitField) {
+ Offset = Field->mBitOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx) * 8;
+ } else {
+ Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx);
+ }
+ return VFR_RETURN_SUCCESS;
+}
+
+UINT8
+CVfrVarDataTypeDB::GetFieldWidth (
+ IN SVfrDataField *Field
+ )
+{
+ if (Field == NULL) {
+ return 0;
+ }
+
+ return Field->mFieldType->mType;
+}
+
+UINT32
+CVfrVarDataTypeDB::GetFieldSize (
+ IN SVfrDataField *Field,
+ IN UINT32 ArrayIdx,
+ IN BOOLEAN BitField
+ )
+{
+ if (Field == NULL) {
+ return VFR_RETURN_FATAL_ERROR;
+ }
+
+ if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum != 0)) {
+ return Field->mFieldType->mTotalSize * Field->mArrayNum;
+ } else {
+ if (BitField) {
+ return Field->mBitWidth;
+ } 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) {
+ assert (strlen (gInternalTypesTable[Index].mTypeName) < MAX_NAME_LEN);
+ strncpy (New->mTypeName, gInternalTypesTable[Index].mTypeName, MAX_NAME_LEN - 1);
+ New->mTypeName[MAX_NAME_LEN - 1] = 0;
+ New->mType = gInternalTypesTable[Index].mType;
+ New->mAlign = gInternalTypesTable[Index].mAlign;
+ New->mTotalSize = gInternalTypesTable[Index].mSize;
+ 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;
+ pYearField->mIsBitField = FALSE;
+
+ strcpy (pMonthField->mFieldName, "Month");
+ GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType);
+ pMonthField->mOffset = 2;
+ pMonthField->mNext = pDayField;
+ pMonthField->mArrayNum = 0;
+ pMonthField->mIsBitField = FALSE;
+
+ strcpy (pDayField->mFieldName, "Day");
+ GetDataType ((CHAR8 *)"UINT8", &pDayField->mFieldType);
+ pDayField->mOffset = 3;
+ pDayField->mNext = NULL;
+ pDayField->mArrayNum = 0;
+ pDayField->mIsBitField = FALSE;
+
+ New->mMembers = pYearField;
+ } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_TIME") == 0) {
+ 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;
+ pHoursField->mIsBitField = FALSE;
+
+ strcpy (pMinutesField->mFieldName, "Minutes");
+ GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType);
+ pMinutesField->mOffset = 1;
+ pMinutesField->mNext = pSecondsField;
+ pMinutesField->mArrayNum = 0;
+ pMinutesField->mIsBitField = FALSE;
+
+ strcpy (pSecondsField->mFieldName, "Seconds");
+ GetDataType ((CHAR8 *)"UINT8", &pSecondsField->mFieldType);
+ pSecondsField->mOffset = 2;
+ pSecondsField->mNext = NULL;
+ pSecondsField->mArrayNum = 0;
+ pSecondsField->mIsBitField = FALSE;
+
+ New->mMembers = pHoursField;
+ } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_REF") == 0) {
+ SVfrDataField *pQuestionIdField = new SVfrDataField;
+ SVfrDataField *pFormIdField = new SVfrDataField;
+ SVfrDataField *pFormSetGuidField = new SVfrDataField;
+ SVfrDataField *pDevicePathField = new SVfrDataField;
+
+ strcpy (pQuestionIdField->mFieldName, "QuestionId");
+ GetDataType ((CHAR8 *)"UINT16", &pQuestionIdField->mFieldType);
+ pQuestionIdField->mOffset = 0;
+ pQuestionIdField->mNext = pFormIdField;
+ pQuestionIdField->mArrayNum = 0;
+ pQuestionIdField->mIsBitField = FALSE;
+
+ strcpy (pFormIdField->mFieldName, "FormId");
+ GetDataType ((CHAR8 *)"UINT16", &pFormIdField->mFieldType);
+ pFormIdField->mOffset = 2;
+ pFormIdField->mNext = pFormSetGuidField;
+ pFormIdField->mArrayNum = 0;
+ pFormIdField->mIsBitField = FALSE;
+
+ strcpy (pFormSetGuidField->mFieldName, "FormSetGuid");
+ GetDataType ((CHAR8 *)"EFI_GUID", &pFormSetGuidField->mFieldType);
+ pFormSetGuidField->mOffset = 4;
+ pFormSetGuidField->mNext = pDevicePathField;
+ pFormSetGuidField->mArrayNum = 0;
+ pFormSetGuidField->mIsBitField = FALSE;
+
+ strcpy (pDevicePathField->mFieldName, "DevicePath");
+ GetDataType ((CHAR8 *)"EFI_STRING_ID", &pDevicePathField->mFieldType);
+ pDevicePathField->mOffset = 20;
+ pDevicePathField->mNext = NULL;
+ pDevicePathField->mArrayNum = 0;
+ pDevicePathField->mIsBitField = FALSE;
+
+ New->mMembers = pQuestionIdField;
+ } else {
+ New->mMembers = NULL;
+ }
+ New->mNext = NULL;
+ RegisterNewType (New);
+ New = NULL;
+ }
+ }
+}
+
+CVfrVarDataTypeDB::CVfrVarDataTypeDB (
+ VOID
+ )
+{
+ mDataTypeList = NULL;
+ mNewDataType = NULL;
+ mCurrDataField = NULL;
+ mPackAlign = DEFAULT_PACK_ALIGN;
+ mPackStack = NULL;
+ mFirstNewDataTypeName = NULL;
+ mCurrDataType = 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;
+ pNewType->mHasBitField = FALSE;
+
+ 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;
+ }
+ }
+
+ strncpy(mNewDataType->mTypeName, TypeName, MAX_NAME_LEN - 1);
+ mNewDataType->mTypeName[MAX_NAME_LEN - 1] = 0;
+ return VFR_RETURN_SUCCESS;
+}
+
+/**
+ Record the bit field info in the data type.
+
+ @param FieldName Point to the field name.
+ @param TypeName Point to the type name.
+ @param Width The bit width.
+ @param FieldInUnion The filed is in Union type or Structure type.
+
+**/
+EFI_VFR_RETURN_CODE
+CVfrVarDataTypeDB::DataTypeAddBitField (
+ IN CHAR8 *FieldName,
+ IN CHAR8 *TypeName,
+ IN UINT32 Width,
+ IN BOOLEAN FieldInUnion
+ )
+{
+ SVfrDataField *pNewField = NULL;
+ SVfrDataType *pFieldType = NULL;
+ SVfrDataField *pTmp;
+ UINT32 Align;
+ UINT32 MaxDataTypeSize;
+ BOOLEAN UpdateTotalSize;
+
+ CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS);
+
+ if (Width > MAX_BIT_WIDTH) {
+ return VFR_RETURN_BIT_WIDTH_ERROR;
+ }
+
+ if (Width > pFieldType->mTotalSize * 8) {
+ return VFR_RETURN_BIT_WIDTH_ERROR;
+ }
+
+ if (FieldName != NULL && strlen (FieldName) >= MAX_NAME_LEN) {
+ return VFR_RETURN_INVALID_PARAMETER;
+ }
+
+ if (Width == 0 && FieldName != NULL) {
+ return VFR_RETURN_INVALID_PARAMETER;
+ }
+
+ for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) {
+ if (FieldName != NULL && strcmp (pTmp->mFieldName, FieldName) == 0) {
+ return VFR_RETURN_REDEFINED;
+ }
+ }
+
+ Align = MIN (mPackAlign, pFieldType->mAlign);
+ UpdateTotalSize = FALSE;
+
+ if ((pNewField = new SVfrDataField) == NULL) {
+ return VFR_RETURN_OUT_FOR_RESOURCES;
+ }
+
+ MaxDataTypeSize = mNewDataType->mTotalSize;
+ if (FieldName != NULL) {
+ strncpy (pNewField->mFieldName, FieldName, MAX_NAME_LEN - 1);
+ pNewField->mFieldName[MAX_NAME_LEN - 1] = 0;
+ }
+ pNewField->mFieldType = pFieldType;
+ pNewField->mIsBitField = TRUE;
+ pNewField->mBitWidth = Width;
+ pNewField->mArrayNum = 0;
+ pNewField->mBitOffset = 0;
+ pNewField->mOffset = 0;
+
+ if (mNewDataType->mMembers == NULL) {
+ mNewDataType->mMembers = pNewField;
+ pNewField->mNext = NULL;
+ } else {
+ for (pTmp = mNewDataType->mMembers; pTmp->mNext != NULL; pTmp = pTmp->mNext)
+ ;
+ pTmp->mNext = pNewField;
+ pNewField->mNext = NULL;
+ }
+
+ if (FieldInUnion) {
+ pNewField->mOffset = 0;
+ if (MaxDataTypeSize < pNewField->mFieldType->mTotalSize) {
+ mNewDataType->mTotalSize = pNewField->mFieldType->mTotalSize;
+ }
+ } else {
+ //
+ // Check whether the bit fields can be contained within one FieldType.
+ //
+ if (pTmp != NULL && pTmp->mIsBitField && strcmp (pTmp->mFieldType->mTypeName, pNewField->mFieldType->mTypeName) == 0 &&
+ (pTmp->mBitOffset - pTmp->mOffset * 8) + pTmp->mBitWidth + pNewField->mBitWidth <= pNewField->mFieldType->mTotalSize * 8) {
+ pNewField->mBitOffset = pTmp->mBitOffset + pTmp->mBitWidth;
+ pNewField->mOffset = pTmp->mOffset;
+ //
+ // If BitWidth=0,used to force alignment at the next word boundary.
+ // So make this bit field occupy the remaing bit width of current field type.
+ //
+ if (pNewField->mBitWidth == 0) {
+ pNewField->mBitWidth = pNewField->mFieldType->mTotalSize * 8 - (pNewField->mBitOffset - pTmp->mOffset * 8);
+ }
+ } else {
+ //
+ // The bit filed start a new memory
+ //
+ pNewField->mBitOffset = mNewDataType->mTotalSize * 8;
+ UpdateTotalSize = TRUE;
+ }
+ }
+
+ if (UpdateTotalSize){
+ if ((mNewDataType->mTotalSize % Align) == 0) {
+ pNewField->mOffset = mNewDataType->mTotalSize;
+ } else {
+ pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align);
+ }
+ mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize);
+ }
+
+ mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign));
+ mNewDataType->mHasBitField = TRUE;
+ return VFR_RETURN_SUCCESS;
+}
+
+EFI_VFR_RETURN_CODE
+CVfrVarDataTypeDB::DataTypeAddField (
+ IN CHAR8 *FieldName,
+ IN CHAR8 *TypeName,
+ IN UINT32 ArrayNum,
+ IN BOOLEAN FieldInUnion
+ )
+{
+ SVfrDataField *pNewField = NULL;
+ SVfrDataType *pFieldType = NULL;
+ SVfrDataField *pTmp;
+ UINT32 Align;
+ UINT32 MaxDataTypeSize;
+
+ CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS);
+ MaxDataTypeSize = mNewDataType->mTotalSize;
+
+ if (strlen (FieldName) >= MAX_NAME_LEN) {
+ return VFR_RETURN_INVALID_PARAMETER;
+ }
+
+ 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;
+ }
+ strncpy (pNewField->mFieldName, FieldName, MAX_NAME_LEN - 1);
+ pNewField->mFieldName[MAX_NAME_LEN - 1] = 0;
+ pNewField->mFieldType = pFieldType;
+ pNewField->mArrayNum = ArrayNum;
+ pNewField->mIsBitField = FALSE;
+ if ((mNewDataType->mTotalSize % Align) == 0) {
+ pNewField->mOffset = mNewDataType->mTotalSize;
+ } else {
+ 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));
+
+ if (FieldInUnion) {
+ if (MaxDataTypeSize < pNewField->mFieldType->mTotalSize) {
+ mNewDataType->mTotalSize = pNewField->mFieldType->mTotalSize;
+ }
+ pNewField->mOffset = 0;
+ } else {
+ mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum);
+ }
+
+ return VFR_RETURN_SUCCESS;
+}
+
+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,
+ OUT BOOLEAN &BitField
+ )
+{
+ CHAR8 TName[MAX_NAME_LEN], FName[MAX_NAME_LEN];
+ UINT32 ArrayIdx, Tmp;
+ SVfrDataType *pType = NULL;
+ SVfrDataField *pField = NULL;
+ CHAR8 *VarStrName;
+
+ Offset = 0;
+ Type = EFI_IFR_TYPE_OTHER;
+ Size = 0;
+ VarStrName = VarStr;
+
+ CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS);
+ CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS);
+
+ BitField = IsThisBitField (VarStrName);
+
+ //
+ // if it is not struct data type
+ //
+ 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, pField->mIsBitField), VFR_RETURN_SUCCESS);
+ if (BitField && !pField->mIsBitField) {
+ Offset = (UINT16) (Offset + Tmp * 8);
+ } else {
+ Offset = (UINT16) (Offset + Tmp);
+ }
+ Type = GetFieldWidth (pField);
+ Size = GetFieldSize (pField, ArrayIdx, BitField);
+ }
+ 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 (&mGuid, 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 BitsVarstore,
+ IN BOOLEAN Flag
+ )
+{
+ if (Guid != NULL) {
+ mGuid = *Guid;
+ } else {
+ memset (&mGuid, 0, sizeof (EFI_GUID));
+ }
+ if (StoreName != NULL) {
+ mVarStoreName = new CHAR8[strlen(StoreName) + 1];
+ strcpy (mVarStoreName, StoreName);
+ } else {
+ mVarStoreName = NULL;
+ }
+ mNext = NULL;
+ mVarStoreId = VarStoreId;
+ if (BitsVarstore) {
+ mVarStoreType = EFI_VFR_VARSTORE_BUFFER_BITS;
+ } else {
+ mVarStoreType = EFI_VFR_VARSTORE_BUFFER;
+ }
+ mStorageInfo.mDataType = DataType;
+ mAssignedFlag = Flag;
+}
+
+SVfrVarStorageNode::SVfrVarStorageNode (
+ IN CHAR8 *StoreName,
+ IN EFI_VARSTORE_ID VarStoreId
+ )
+{
+ memset (&mGuid, 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_NAME;
+ mStorageInfo.mNameSpace.mNameTable = new EFI_VARSTORE_ID[DEFAULT_NAME_TABLE_ITEMS];
+ mStorageInfo.mNameSpace.mTableSize = 0;
+ mAssignedFlag = FALSE;
+}
+
+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;
+
+ Index = 0;
+
+ for (; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) {
+ if (mFreeVarStoreIdBitMap[Index] != 0xFFFFFFFF) {
+ break;
+ }
+ }
+
+ if (Index == EFI_FREE_VARSTORE_ID_BITMAP_SIZE) {
+ return EFI_VARSTORE_ID_INVALID;
+ }
+
+ for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
+ if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) {
+ mFreeVarStoreIdBitMap[Index] |= Mask;
+ 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 IsBitVarStore,
+ IN BOOLEAN Flag
+ )
+{
+ SVfrVarStorageNode *pNew = NULL;
+ SVfrDataType *pDataType = NULL;
+ EFI_VARSTORE_ID TempVarStoreId;
+
+ if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) {
+ return VFR_RETURN_FATAL_ERROR;
+ }
+
+ if (GetVarStoreId (StoreName, &TempVarStoreId, Guid) == VFR_RETURN_SUCCESS) {
+ return VFR_RETURN_REDEFINED;
+ }
+
+ CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS);
+
+ if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
+ 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, IsBitVarStore, 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;
+
+ 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 structure name is used as StoreName, and check again.
+ //
+ ReturnCode = GetVarStoreByDataType (StoreName, &pNode, StoreGuid);
+ if (pNode != NULL) {
+ mCurrVarStorageNode = pNode;
+ *VarStoreId = pNode->mVarStoreId;
+ }
+
+ return ReturnCode;
+}
+
+EFI_VFR_RETURN_CODE
+CVfrDataStorage::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;
+ }
+
+ 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;
+ mIsBitVar = FALSE;
+}
+
+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;
+ mIsBitVar = Info.mIsBitVar;
+}
+
+EFI_VARSTORE_INFO&
+EFI_VARSTORE_INFO::operator= (
+ IN CONST EFI_VARSTORE_INFO &Info
+ )
+{
+ if (this != &Info) {
+ mVarStoreId = Info.mVarStoreId;
+ mInfo.mVarName = Info.mInfo.mVarName;
+ mInfo.mVarOffset = Info.mInfo.mVarOffset;
+ mVarType = Info.mVarType;
+ mVarTotalSize = Info.mVarTotalSize;
+ mIsBitVar = Info.mIsBitVar;
+ }
+
+ return *this;
+}
+
+BOOLEAN
+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) &&
+ (mIsBitVar == Info->mIsBitVar)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BufferVarStoreFieldInfoNode::BufferVarStoreFieldInfoNode(
+ IN EFI_VARSTORE_INFO *Info
+ )
+{
+ mVarStoreInfo.mVarType = Info->mVarType;
+ mVarStoreInfo.mVarTotalSize = Info->mVarTotalSize;
+ mVarStoreInfo.mInfo.mVarOffset = Info->mInfo.mVarOffset;
+ mVarStoreInfo.mVarStoreId = Info->mVarStoreId;
+ mNext = NULL;
+}
+
+BufferVarStoreFieldInfoNode::~BufferVarStoreFieldInfoNode ()
+{
+ mVarStoreInfo.mVarType = EFI_IFR_TYPE_OTHER;
+ mVarStoreInfo.mVarTotalSize = 0;
+ mVarStoreInfo.mInfo.mVarOffset = EFI_VAROFFSET_INVALID;
+ mVarStoreInfo.mVarStoreId = EFI_VARSTORE_ID_INVALID;
+ mNext = NULL;
+}
+
+static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo;
+
+EFI_QUESTION_ID
+CVfrQuestionDB::GetFreeQuestionId (
+ VOID
+ )
+{
+ UINT32 Index, Mask, Offset;
+
+ for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
+ if (mFreeQIdBitMap[Index] != 0xFFFFFFFF) {
+ break;
+ }
+ }
+
+ if (Index == EFI_FREE_QUESTION_ID_BITMAP_SIZE) {
+ return EFI_QUESTION_ID_INVALID;
+ }
+
+ for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
+ if ((mFreeQIdBitMap[Index] & Mask) == 0) {
+ mFreeQIdBitMap[Index] |= Mask;
+ 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 QuestionId 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 {
+ if (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];
+ VarIdStr[Index] = NULL;
+ }
+ }
+
+ 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];
+ VarIdStr [Index] = NULL;
+ }
+ }
+}
+
+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];
+ VarIdStr[Index] = NULL;
+ }
+ }
+
+ 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];
+ VarIdStr[Index] = NULL;
+ }
+ }
+}
+
+VOID
+CVfrQuestionDB::RegisterRefQuestion (
+ IN CHAR8 *Name,
+ IN CHAR8 *BaseVarId,
+ IN OUT EFI_QUESTION_ID &QuestionId
+ )
+{
+ SVfrQuestionNode *pNode[4] = {NULL, };
+ UINT32 Len;
+ CHAR8 *VarIdStr[4] = {NULL, };
+ CHAR8 Index;
+
+ if (BaseVarId == NULL && Name == NULL) {
+ return;
+ }
+
+ if (BaseVarId != NULL) {
+ Len = strlen (BaseVarId);
+
+ VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
+ if (VarIdStr[0] != NULL) {
+ strcpy (VarIdStr[0], BaseVarId);
+ strcat (VarIdStr[0], ".QuestionId");
+ }
+ VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
+ if (VarIdStr[1] != NULL) {
+ strcpy (VarIdStr[1], BaseVarId);
+ strcat (VarIdStr[1], ".FormId");
+ }
+ VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
+ if (VarIdStr[2] != NULL) {
+ strcpy (VarIdStr[2], BaseVarId);
+ strcat (VarIdStr[2], ".FormSetGuid");
+ }
+ VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
+ if (VarIdStr[3] != NULL) {
+ strcpy (VarIdStr[3], BaseVarId);
+ strcat (VarIdStr[3], ".DevicePath");
+ }
+ } else {
+ Len = strlen (Name);
+
+ VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
+ if (VarIdStr[0] != NULL) {
+ strcpy (VarIdStr[0], Name);
+ strcat (VarIdStr[0], ".QuestionId");
+ }
+ VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
+ if (VarIdStr[1] != NULL) {
+ strcpy (VarIdStr[1], Name);
+ strcat (VarIdStr[1], ".FormId");
+ }
+ VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
+ if (VarIdStr[2] != NULL) {
+ strcpy (VarIdStr[2], Name);
+ strcat (VarIdStr[2], ".FormSetGuid");
+ }
+ VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
+ if (VarIdStr[3] != NULL) {
+ strcpy (VarIdStr[3], Name);
+ strcat (VarIdStr[3], ".DevicePath");
+ }
+ }
+
+ if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0])) == NULL) {
+ goto Err;
+ }
+ if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1])) == NULL) {
+ goto Err;
+ }
+ if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2])) == NULL) {
+ goto Err;
+ }
+ if ((pNode[3] = new SVfrQuestionNode (Name, VarIdStr[3])) == NULL) {
+ goto Err;
+ }
+
+ if (QuestionId == EFI_QUESTION_ID_INVALID) {
+ QuestionId = GetFreeQuestionId ();
+ } else {
+ if (ChekQuestionIdFree (QuestionId) == FALSE) {
+ goto Err;
+ }
+ MarkQuestionIdUsed (QuestionId);
+ }
+
+ pNode[0]->mQuestionId = QuestionId;
+ pNode[1]->mQuestionId = QuestionId;
+ pNode[2]->mQuestionId = QuestionId;
+ pNode[3]->mQuestionId = QuestionId;
+ pNode[0]->mQtype = QUESTION_REF;
+ pNode[1]->mQtype = QUESTION_REF;
+ pNode[2]->mQtype = QUESTION_REF;
+ pNode[3]->mQtype = QUESTION_REF;
+ pNode[0]->mNext = pNode[1];
+ pNode[1]->mNext = pNode[2];
+ pNode[2]->mNext = pNode[3];
+ pNode[3]->mNext = mQuestionList;
+ mQuestionList = pNode[0];
+
+ gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
+ gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
+ gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
+ gCFormPkg.DoPendingAssign (VarIdStr[3], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
+
+ return;
+
+ Err:
+ for (Index = 0; Index < 4; Index++) {
+ if (pNode[Index] != NULL) {
+ delete pNode[Index];
+ }
+
+ if (VarIdStr[Index] != NULL) {
+ delete VarIdStr[Index];
+ }
+ }
+}
+
+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;
+ }
+
+ if (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;
+ }
+
+ if (mStringFileName != NULL) {
+ delete[] mStringFileName;
+ }
+
+ FileLen = strlen (StringFileName) + 1;
+ mStringFileName = new CHAR8[FileLen];
+ if (mStringFileName == NULL) {
+ return;
+ }
+
+ strcpy (mStringFileName, StringFileName);
+ mStringFileName[FileLen - 1] = '\0';
+}
+
+
+/**
+ Returns TRUE or FALSE whether SupportedLanguages contains the best matching language
+ from a set of supported languages.
+
+ @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that
+ contains a set of language codes.
+ @param[in] Language A variable that contains pointers to Null-terminated
+ ASCII strings that contain one language codes.
+
+ @retval FALSE The best matching language could not be found in SupportedLanguages.
+ @retval TRUE The best matching language could be found in SupportedLanguages.
+
+**/
+BOOLEAN
+CVfrStringDB::GetBestLanguage (
+ IN CONST CHAR8 *SupportedLanguages,
+ IN CHAR8 *Language
+ )
+{
+ UINTN CompareLength;
+ UINTN LanguageLength;
+ CONST CHAR8 *Supported;
+
+ if (SupportedLanguages == NULL || Language == NULL){
+ return FALSE;
+ }
+
+ //
+ // Determine the length of the first RFC 4646 language code in Language
+ //
+ for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
+
+ //
+ // Trim back the length of Language used until it is empty
+ //
+ while (LanguageLength > 0) {
+ //
+ // Loop through all language codes in SupportedLanguages
+ //
+ for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
+ //
+ // Skip ';' characters in Supported
+ //
+ for (; *Supported != '\0' && *Supported == ';'; Supported++);
+ //
+ // Determine the length of the next language code in Supported
+ //
+ for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
+ //
+ // If Language is longer than the Supported, then skip to the next language
+ //
+ if (LanguageLength > CompareLength) {
+ continue;
+ }
+
+ //
+ // See if the first LanguageLength characters in Supported match Language
+ //
+ if (strncmp (Supported, Language, LanguageLength) == 0) {
+ return TRUE;
+ }
+ }
+
+ //
+ // Trim Language from the right to the next '-' character
+ //
+ for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
+ }
+
+ //
+ // No matches were found
+ //
+ return FALSE;
+}
+
+
+CHAR8 *
+CVfrStringDB::GetVarStoreNameFormStringId (
+ IN EFI_STRING_ID StringId
+ )
+{
+ FILE *pInFile = NULL;
+ UINT32 NameOffset;
+ INT32 Length;
+ UINT8 *StringPtr;
+ CHAR8 *StringName;
+ CHAR16 *UnicodeString;
+ CHAR8 *VarStoreName = NULL;
+ CHAR8 *DestTmp;
+ UINT8 *Current;
+ EFI_STATUS Status;
+ CHAR8 LineBuf[EFI_IFR_MAX_LENGTH];
+ UINT8 BlockType;
+ EFI_HII_STRING_PACKAGE_HDR *PkgHeader;
+
+ if (mStringFileName == NULL) {
+ return NULL;
+ }
+
+ if ((pInFile = fopen (LongFilePath (mStringFileName), "rb")) == NULL) {
+ return NULL;
+ }
+
+ //
+ // Get file length.
+ //
+ fseek (pInFile, 0, SEEK_END);
+ Length = ftell (pInFile);
+ fseek (pInFile, 0, SEEK_SET);
+
+ //
+ // Get file data.
+ //
+ StringPtr = new UINT8[Length];
+ if (StringPtr == NULL) {
+ fclose (pInFile);
+ return NULL;
+ }
+ fread ((char *)StringPtr, sizeof (UINT8), Length, pInFile);
+ fclose (pInFile);
+
+ PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
+ //
+ // Check the String package.
+ //
+ if (PkgHeader->Header.Type != EFI_HII_PACKAGE_STRINGS) {
+ delete[] StringPtr;
+ return NULL;
+ }
+
+ //
+ // Search the language, get best language base on RFC 4647 matching algorithm.
+ //
+ Current = StringPtr;
+ while (!GetBestLanguage ("en", PkgHeader->Language)) {
+ Current += PkgHeader->Header.Length;
+ PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current;
+ //
+ // If can't find string package base on language, just return the first string package.
+ //
+ if (Current - StringPtr >= Length) {
+ Current = StringPtr;
+ PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
+ break;
+ }
+ }
+
+ Current += PkgHeader->HdrSize;
+ //
+ // Find the string block according the stringId.
+ //
+ Status = FindStringBlock(Current, StringId, &NameOffset, &BlockType);
+ if (Status != EFI_SUCCESS) {
+ delete[] StringPtr;
+ return NULL;
+ }
+
+ //
+ // Get varstore name according the string type.
+ //
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ StringName = (CHAR8*)(Current + NameOffset);
+ VarStoreName = new CHAR8[strlen(StringName) + 1];
+ strcpy (VarStoreName, StringName);
+ break;
+ case EFI_HII_SIBT_STRING_UCS2:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ UnicodeString = (CHAR16*)(Current + NameOffset);
+ Length = GetUnicodeStringTextSize ((UINT8*)UnicodeString) ;
+ DestTmp = new CHAR8[Length / 2 + 1];
+ VarStoreName = DestTmp;
+ while (*UnicodeString != '\0') {
+ *(DestTmp++) = (CHAR8) *(UnicodeString++);
+ }
+ *DestTmp = '\0';
+ break;
+ default:
+ break;
+ }
+
+ delete[] StringPtr;
+
+ return VarStoreName;
+}
+
+EFI_STATUS
+CVfrStringDB::FindStringBlock (
+ IN UINT8 *StringData,
+ IN EFI_STRING_ID StringId,
+ OUT UINT32 *StringTextOffset,
+ OUT UINT8 *BlockType
+ )
+{
+ UINT8 *BlockHdr;
+ EFI_STRING_ID CurrentStringId;
+ UINT32 BlockSize;
+ UINT32 Index;
+ UINT8 *StringTextPtr;
+ UINT32 Offset;
+ UINT16 StringCount;
+ UINT16 SkipCount;
+ UINT8 Length8;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ UINT32 Length32;
+ UINT32 StringSize;
+
+ CurrentStringId = 1;
+
+ //
+ // Parse the string blocks to get the string text and font.
+ //
+ BlockHdr = StringData;
+ BlockSize = 0;
+ Offset = 0;
+ while (*BlockHdr != EFI_HII_SIBT_END) {
+ switch (*BlockHdr) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringTextOffset = StringTextPtr - StringData;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ memcpy (
+ &StringCount,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringTextOffset = StringTextPtr - StringData;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StringSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StrSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ for (Index = 0; Index < StringCount; Index++) {
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);
+ BlockSize += StringSize;
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringTextOffset = StringTextPtr - StringData;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ memcpy (
+ &StringCount,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ for (Index = 0; Index < StringCount; Index++) {
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);
+ BlockSize += StringSize;
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringTextOffset = StringTextPtr - StringData;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_DUPLICATE:
+ if (CurrentStringId == StringId) {
+ //
+ // Incoming StringId is an id of a duplicate string block.
+ // Update the StringId to be the previous string block.
+ // Go back to the header of string block to search.
+ //
+ memcpy (
+ &StringId,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
+ sizeof (EFI_STRING_ID)
+ );
+ CurrentStringId = 1;
+ BlockSize = 0;
+ } else {
+ BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_SKIP1:
+ SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_SKIP2:
+ memcpy (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_EXT1:
+ memcpy (
+ &Length8,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT8)
+ );
+ BlockSize += Length8;
+ break;
+
+ case EFI_HII_SIBT_EXT2:
+ memcpy (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ BlockSize += Ext2.Length;
+ break;
+
+ case EFI_HII_SIBT_EXT4:
+ memcpy (
+ &Length32,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT32)
+ );
+
+ BlockSize += Length32;
+ break;
+
+ default:
+ break;
+ }
+
+ if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) {
+ *StringTextOffset = BlockHdr - StringData + Offset;
+ *BlockType = *BlockHdr;
+
+ if (StringId == CurrentStringId - 1) {
+ //
+ // if only one skip item, return EFI_NOT_FOUND.
+ //
+ if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (StringId < CurrentStringId - 1) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ BlockHdr = StringData + BlockSize;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+UINT32
+CVfrStringDB::GetUnicodeStringTextSize (
+ IN UINT8 *StringSrc
+ )
+{
+ UINT32 StringSize;
+ CHAR16 *StringPtr;
+
+ StringSize = sizeof (CHAR16);
+ StringPtr = (UINT16*)StringSrc;
+ while (*StringPtr++ != L'\0') {
+ StringSize += sizeof (CHAR16);
+ }
+
+ return StringSize;
+}
+
+CVfrVarDataTypeDB gCVfrVarDataTypeDB;
+CVfrDefaultStore gCVfrDefaultStore;
+CVfrDataStorage gCVfrDataStorage;
+
+