mirror of https://github.com/acidanthera/audk.git
3632 lines
93 KiB
C++
3632 lines
93 KiB
C++
/** @file
|
|
|
|
Vfr common library functions.
|
|
|
|
Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include "stdio.h"
|
|
#include "stdlib.h"
|
|
#include "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_OTHER :
|
|
return;
|
|
}
|
|
}
|
|
|
|
SConfigInfo::~SConfigInfo (
|
|
VOID
|
|
)
|
|
{
|
|
BUFFER_SAFE_FREE (mValue);
|
|
}
|
|
|
|
SConfigItem::SConfigItem (
|
|
IN CHAR8 *Name,
|
|
IN EFI_GUID *Guid,
|
|
IN CHAR8 *Id
|
|
)
|
|
{
|
|
mName = NULL;
|
|
mGuid = NULL;
|
|
mId = NULL;
|
|
mInfoStrList = NULL;
|
|
mNext = NULL;
|
|
|
|
if (Name != NULL) {
|
|
if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) {
|
|
strcpy (mName, Name);
|
|
}
|
|
}
|
|
|
|
if (Guid != NULL) {
|
|
if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) {
|
|
memcpy (mGuid, Guid, sizeof (EFI_GUID));
|
|
}
|
|
}
|
|
|
|
if (Id != NULL) {
|
|
if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) {
|
|
strcpy (mId, Id);
|
|
}
|
|
}
|
|
}
|
|
|
|
SConfigItem::SConfigItem (
|
|
IN CHAR8 *Name,
|
|
IN EFI_GUID *Guid,
|
|
IN CHAR8 *Id,
|
|
IN UINT8 Type,
|
|
IN UINT16 Offset,
|
|
IN UINT16 Width,
|
|
IN EFI_IFR_TYPE_VALUE Value
|
|
)
|
|
{
|
|
mName = NULL;
|
|
mGuid = NULL;
|
|
mId = NULL;
|
|
mInfoStrList = NULL;
|
|
mNext = NULL;
|
|
|
|
if (Name != NULL) {
|
|
if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) {
|
|
strcpy (mName, Name);
|
|
}
|
|
}
|
|
|
|
if (Guid != NULL) {
|
|
if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) {
|
|
memcpy (mGuid, Guid, sizeof (EFI_GUID));
|
|
}
|
|
}
|
|
|
|
if (Id != NULL) {
|
|
if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) {
|
|
strcpy (mId, Id);
|
|
}
|
|
}
|
|
|
|
mInfoStrList = new SConfigInfo(Type, Offset, Width, Value);
|
|
}
|
|
|
|
SConfigItem::~SConfigItem (
|
|
VOID
|
|
)
|
|
{
|
|
SConfigInfo *Info;
|
|
|
|
BUFFER_SAFE_FREE (mName);
|
|
BUFFER_SAFE_FREE (mGuid);
|
|
BUFFER_SAFE_FREE (mId);
|
|
while (mInfoStrList != NULL) {
|
|
Info = mInfoStrList;
|
|
mInfoStrList = mInfoStrList->mNext;
|
|
|
|
BUFFER_SAFE_FREE (Info);
|
|
}
|
|
}
|
|
|
|
UINT8
|
|
CVfrBufferConfig::Register (
|
|
IN CHAR8 *Name,
|
|
IN EFI_GUID *Guid,
|
|
IN CHAR8 *Id
|
|
)
|
|
{
|
|
SConfigItem *pNew;
|
|
|
|
if (Select (Name, Guid) == 0) {
|
|
return 1;
|
|
}
|
|
|
|
if ((pNew = new SConfigItem (Name, Guid, Id)) == NULL) {
|
|
return 2;
|
|
}
|
|
|
|
if (mItemListHead == NULL) {
|
|
mItemListHead = pNew;
|
|
mItemListTail = pNew;
|
|
} else {
|
|
mItemListTail->mNext = pNew;
|
|
mItemListTail = pNew;
|
|
}
|
|
mItemListPos = pNew;
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID
|
|
CVfrBufferConfig::Open (
|
|
VOID
|
|
)
|
|
{
|
|
mItemListPos = mItemListHead;
|
|
}
|
|
|
|
BOOLEAN
|
|
CVfrBufferConfig::Eof(
|
|
VOID
|
|
)
|
|
{
|
|
return (mItemListPos == NULL) ? TRUE : FALSE;
|
|
}
|
|
|
|
UINT8
|
|
CVfrBufferConfig::Select (
|
|
IN CHAR8 *Name,
|
|
IN EFI_GUID *Guid,
|
|
IN CHAR8 *Id
|
|
)
|
|
{
|
|
SConfigItem *p;
|
|
|
|
if (Name == NULL || Guid == NULL) {
|
|
mItemListPos = mItemListHead;
|
|
return 0;
|
|
} else {
|
|
for (p = mItemListHead; p != NULL; p = p->mNext) {
|
|
if ((strcmp (p->mName, Name) != 0) || (memcmp (p->mGuid, Guid, sizeof (EFI_GUID)) != 0)) {
|
|
continue;
|
|
}
|
|
|
|
if (Id != NULL) {
|
|
if (p->mId == NULL || strcmp (p->mId, Id) != 0) {
|
|
continue;
|
|
}
|
|
} else if (p->mId != NULL) {
|
|
continue;
|
|
}
|
|
|
|
mItemListPos = p;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
UINT8
|
|
CVfrBufferConfig::Write (
|
|
IN CONST CHAR8 Mode,
|
|
IN CHAR8 *Name,
|
|
IN EFI_GUID *Guid,
|
|
IN CHAR8 *Id,
|
|
IN UINT8 Type,
|
|
IN UINT16 Offset,
|
|
IN UINT32 Width,
|
|
IN EFI_IFR_TYPE_VALUE Value
|
|
)
|
|
{
|
|
UINT8 Ret;
|
|
SConfigItem *pItem;
|
|
SConfigInfo *pInfo;
|
|
|
|
if ((Ret = Select (Name, Guid)) != 0) {
|
|
return Ret;
|
|
}
|
|
|
|
switch (Mode) {
|
|
case 'a' : // add
|
|
if (Select (Name, Guid, Id) != 0) {
|
|
if ((pItem = new SConfigItem (Name, Guid, Id, Type, Offset, (UINT16) Width, Value)) == NULL) {
|
|
return 2;
|
|
}
|
|
if (mItemListHead == NULL) {
|
|
mItemListHead = pItem;
|
|
mItemListTail = pItem;
|
|
} else {
|
|
mItemListTail->mNext = pItem;
|
|
mItemListTail = pItem;
|
|
}
|
|
mItemListPos = pItem;
|
|
} else {
|
|
// tranverse the list to find out if there's already the value for the same offset
|
|
for (pInfo = mItemListPos->mInfoStrList; pInfo != NULL; pInfo = pInfo->mNext) {
|
|
if (pInfo->mOffset == Offset) {
|
|
return 0;
|
|
}
|
|
}
|
|
if((pInfo = new SConfigInfo (Type, Offset, Width, Value)) == NULL) {
|
|
return 2;
|
|
}
|
|
pInfo->mNext = mItemListPos->mInfoStrList;
|
|
mItemListPos->mInfoStrList = pInfo;
|
|
}
|
|
break;
|
|
|
|
case 'd' : // delete
|
|
if (mItemListHead == mItemListPos) {
|
|
mItemListHead = mItemListPos->mNext;
|
|
delete mItemListPos;
|
|
break;
|
|
}
|
|
|
|
for (pItem = mItemListHead; pItem->mNext != mItemListPos; pItem = pItem->mNext)
|
|
;
|
|
|
|
pItem->mNext = mItemListPos->mNext;
|
|
if (mItemListTail == mItemListPos) {
|
|
mItemListTail = pItem;
|
|
}
|
|
delete mItemListPos;
|
|
mItemListPos = pItem->mNext;
|
|
break;
|
|
|
|
case 'i' : // set info
|
|
if (mItemListPos->mId != NULL) {
|
|
delete mItemListPos->mId;
|
|
}
|
|
mItemListPos->mId = NULL;
|
|
if (Id != NULL) {
|
|
if ((mItemListPos->mId = new CHAR8[strlen (Id) + 1]) == NULL) {
|
|
return 2;
|
|
}
|
|
strcpy (mItemListPos->mId, Id);
|
|
}
|
|
break;
|
|
|
|
default :
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
CVfrBufferConfig::Close (
|
|
VOID
|
|
)
|
|
{
|
|
mItemListPos = NULL;
|
|
}
|
|
|
|
#define BYTES_PRE_LINE 0x10
|
|
|
|
VOID
|
|
CVfrBufferConfig::OutputCFile (
|
|
IN FILE *pFile,
|
|
IN CHAR8 *BaseName
|
|
)
|
|
{
|
|
CVfrBinaryOutput Output;
|
|
SConfigItem *Item;
|
|
SConfigInfo *Info;
|
|
UINT32 TotalLen;
|
|
|
|
if (pFile == NULL) {
|
|
return;
|
|
}
|
|
|
|
for (Item = mItemListHead; Item != NULL; Item = Item->mNext) {
|
|
if (Item->mId != NULL || Item->mInfoStrList == NULL) {
|
|
continue;
|
|
}
|
|
fprintf (pFile, "\nunsigned char %s%sBlockName[] = {", BaseName, Item->mName);
|
|
|
|
TotalLen = sizeof (UINT32);
|
|
for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
|
|
TotalLen += sizeof (UINT16) * 2;
|
|
}
|
|
Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32));
|
|
|
|
for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
|
|
fprintf (pFile, "\n");
|
|
Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16));
|
|
Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16));
|
|
}
|
|
fprintf (pFile, "\n};\n");
|
|
}
|
|
|
|
for (Item = mItemListHead; Item != NULL; Item = Item->mNext) {
|
|
if (Item->mId != NULL && Item->mInfoStrList != NULL) {
|
|
fprintf (pFile, "\nunsigned char %s%sDefault%s[] = {", BaseName, Item->mName, Item->mId);
|
|
|
|
TotalLen = sizeof (UINT32);
|
|
for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
|
|
TotalLen += Info->mWidth + sizeof (UINT16) * 2;
|
|
}
|
|
Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32));
|
|
|
|
for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
|
|
fprintf (pFile, "\n");
|
|
Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16));
|
|
Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16));
|
|
if (Info->mNext == NULL) {
|
|
Output.WriteEnd (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth);
|
|
} else {
|
|
Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth);
|
|
}
|
|
}
|
|
fprintf (pFile, "\n};\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
CVfrBufferConfig::CVfrBufferConfig (
|
|
VOID
|
|
)
|
|
{
|
|
mItemListHead = NULL;
|
|
mItemListTail = NULL;
|
|
mItemListPos = NULL;
|
|
}
|
|
|
|
CVfrBufferConfig::~CVfrBufferConfig (
|
|
VOID
|
|
)
|
|
{
|
|
SConfigItem *p;
|
|
|
|
while (mItemListHead != NULL) {
|
|
p = mItemListHead;
|
|
mItemListHead = mItemListHead->mNext;
|
|
delete p;
|
|
}
|
|
|
|
mItemListHead = NULL;
|
|
mItemListTail = NULL;
|
|
mItemListPos = NULL;
|
|
}
|
|
|
|
CVfrBufferConfig gCVfrBufferConfig;
|
|
|
|
static struct {
|
|
CONST CHAR8 *mTypeName;
|
|
UINT8 mType;
|
|
UINT32 mSize;
|
|
UINT32 mAlign;
|
|
} gInternalTypesTable [] = {
|
|
{"UINT64", EFI_IFR_TYPE_NUM_SIZE_64, sizeof (UINT64), sizeof (UINT64)},
|
|
{"UINT32", EFI_IFR_TYPE_NUM_SIZE_32, sizeof (UINT32), sizeof (UINT32)},
|
|
{"UINT16", EFI_IFR_TYPE_NUM_SIZE_16, sizeof (UINT16), sizeof (UINT16)},
|
|
{"UINT8", EFI_IFR_TYPE_NUM_SIZE_8, sizeof (UINT8), sizeof (UINT8)},
|
|
{"BOOLEAN", EFI_IFR_TYPE_BOOLEAN, sizeof (BOOLEAN), sizeof (BOOLEAN)},
|
|
{"EFI_HII_DATE", EFI_IFR_TYPE_DATE, sizeof (EFI_HII_DATE), sizeof (UINT16)},
|
|
{"EFI_STRING_ID", EFI_IFR_TYPE_STRING, sizeof (EFI_STRING_ID),sizeof (EFI_STRING_ID)},
|
|
{"EFI_HII_TIME", EFI_IFR_TYPE_TIME, sizeof (EFI_HII_TIME), sizeof (UINT8)},
|
|
{"EFI_HII_REF", EFI_IFR_TYPE_REF, sizeof (EFI_HII_REF), sizeof (EFI_GUID)},
|
|
{NULL, EFI_IFR_TYPE_OTHER, 0, 0}
|
|
};
|
|
|
|
STATIC
|
|
BOOLEAN
|
|
_IS_INTERNAL_TYPE (
|
|
IN CHAR8 *TypeName
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
|
|
if (TypeName == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) {
|
|
if (strcmp (TypeName, gInternalTypesTable[Index].mTypeName) == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
STATIC
|
|
CHAR8 *
|
|
TrimHex (
|
|
IN CHAR8 *Str,
|
|
OUT bool *IsHex
|
|
)
|
|
{
|
|
*IsHex = FALSE;
|
|
|
|
while (*Str && *Str == ' ') {
|
|
Str++;
|
|
}
|
|
while (*Str && *Str == '0') {
|
|
Str++;
|
|
}
|
|
if (*Str && (*Str == 'x' || *Str == 'X')) {
|
|
Str++;
|
|
*IsHex = TRUE;
|
|
}
|
|
|
|
return Str;
|
|
}
|
|
|
|
UINT32
|
|
_STR2U32 (
|
|
IN CHAR8 *Str
|
|
)
|
|
{
|
|
bool IsHex;
|
|
UINT32 Value;
|
|
CHAR8 c;
|
|
|
|
Str = TrimHex (Str, &IsHex);
|
|
for (Value = 0; (c = *Str) != '\0'; Str++) {
|
|
//
|
|
// BUG: does not handle overflow here
|
|
//
|
|
(IsHex == TRUE) ? (Value <<= 4) : (Value *= 10);
|
|
|
|
if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) {
|
|
Value += (c - 'a' + 10);
|
|
}
|
|
if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) {
|
|
Value += (c - 'A' + 10);
|
|
}
|
|
if (c >= '0' && c <= '9') {
|
|
Value += (c - '0');
|
|
}
|
|
}
|
|
|
|
return Value;
|
|
}
|
|
|
|
VOID
|
|
CVfrVarDataTypeDB::RegisterNewType (
|
|
IN SVfrDataType *New
|
|
)
|
|
{
|
|
New->mNext = mDataTypeList;
|
|
mDataTypeList = New;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::ExtractStructTypeName (
|
|
IN CHAR8 *&VarStr,
|
|
OUT CHAR8 *TName
|
|
)
|
|
{
|
|
if (TName == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
while((*VarStr != '\0') && (*VarStr != '.')) {
|
|
*TName = *VarStr;
|
|
VarStr++;
|
|
TName++;
|
|
}
|
|
*TName = '\0';
|
|
if (*VarStr == '.') {
|
|
VarStr++;
|
|
}
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::ExtractFieldNameAndArrary (
|
|
IN CHAR8 *&VarStr,
|
|
IN CHAR8 *FName,
|
|
OUT UINT32 &ArrayIdx
|
|
)
|
|
{
|
|
UINT32 Idx;
|
|
CHAR8 ArrayStr[MAX_NAME_LEN + 1];
|
|
|
|
ArrayIdx = INVALID_ARRAY_INDEX;
|
|
|
|
if (FName == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
while((*VarStr != '\0') &&
|
|
(*VarStr != '.') &&
|
|
(*VarStr != '[') &&
|
|
(*VarStr != ']')) {
|
|
*FName = *VarStr;
|
|
VarStr++;
|
|
FName++;
|
|
}
|
|
*FName = '\0';
|
|
|
|
switch (*VarStr) {
|
|
case '.' :
|
|
VarStr++;
|
|
case '\0':
|
|
return VFR_RETURN_SUCCESS;
|
|
case '[' :
|
|
VarStr++;
|
|
for (Idx = 0; (Idx < MAX_NAME_LEN) && (*VarStr != '\0') && (*VarStr != ']'); VarStr++, Idx++) {
|
|
ArrayStr[Idx] = *VarStr;
|
|
}
|
|
ArrayStr[Idx] = '\0';
|
|
|
|
if ((*VarStr != ']') && (ArrayStr[0] == '\0')) {
|
|
return VFR_RETURN_DATA_STRING_ERROR;
|
|
}
|
|
ArrayIdx = _STR2U32 (ArrayStr);
|
|
if (*VarStr == ']') {
|
|
VarStr++;
|
|
}
|
|
if (*VarStr == '.') {
|
|
VarStr++;
|
|
}
|
|
return VFR_RETURN_SUCCESS;
|
|
case ']':
|
|
return VFR_RETURN_DATA_STRING_ERROR;
|
|
}
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::GetTypeField (
|
|
IN CONST CHAR8 *FName,
|
|
IN SVfrDataType *Type,
|
|
OUT SVfrDataField *&Field
|
|
)
|
|
{
|
|
SVfrDataField *pField = NULL;
|
|
|
|
if ((FName == NULL) && (Type == NULL)) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
for (pField = Type->mMembers; pField != NULL; pField = pField->mNext) {
|
|
//
|
|
// For type EFI_IFR_TYPE_TIME, because field name is not correctly wrote,
|
|
// add code to adjust it.
|
|
//
|
|
if (Type->mType == EFI_IFR_TYPE_TIME) {
|
|
if (strcmp (FName, "Hour") == 0) {
|
|
FName = "Hours";
|
|
} else if (strcmp (FName, "Minute") == 0) {
|
|
FName = "Minuts";
|
|
} else if (strcmp (FName, "Second") == 0) {
|
|
FName = "Seconds";
|
|
}
|
|
}
|
|
|
|
if (strcmp (pField->mFieldName, FName) == 0) {
|
|
Field = pField;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::GetFieldOffset (
|
|
IN SVfrDataField *Field,
|
|
IN UINT32 ArrayIdx,
|
|
OUT UINT32 &Offset
|
|
)
|
|
{
|
|
if (Field == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
//
|
|
// Framework Vfr file Array Index is from 1.
|
|
// But Uefi Vfr file Array Index is from 0.
|
|
//
|
|
if (VfrCompatibleMode && ArrayIdx != INVALID_ARRAY_INDEX) {
|
|
if (ArrayIdx == 0) {
|
|
return VFR_RETURN_ERROR_ARRARY_NUM;
|
|
}
|
|
ArrayIdx = ArrayIdx - 1;
|
|
}
|
|
|
|
if ((ArrayIdx != INVALID_ARRAY_INDEX) && ((Field->mArrayNum == 0) || (Field->mArrayNum <= ArrayIdx))) {
|
|
return VFR_RETURN_ERROR_ARRARY_NUM;
|
|
}
|
|
|
|
//
|
|
// Be compatible with the current usage
|
|
// If ArraryIdx is not specified, the first one is used.
|
|
//
|
|
// if ArrayNum is larger than zero, ArraryIdx must be specified.
|
|
//
|
|
// if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum > 0)) {
|
|
// return VFR_RETURN_ERROR_ARRARY_NUM;
|
|
// }
|
|
//
|
|
|
|
Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx);
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
UINT8
|
|
CVfrVarDataTypeDB::GetFieldWidth (
|
|
IN SVfrDataField *Field
|
|
)
|
|
{
|
|
if (Field == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return Field->mFieldType->mType;
|
|
}
|
|
|
|
UINT32
|
|
CVfrVarDataTypeDB::GetFieldSize (
|
|
IN SVfrDataField *Field,
|
|
IN UINT32 ArrayIdx
|
|
)
|
|
{
|
|
if (Field == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum != 0)) {
|
|
return Field->mFieldType->mTotalSize * Field->mArrayNum;
|
|
} else {
|
|
return Field->mFieldType->mTotalSize;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CVfrVarDataTypeDB::InternalTypesListInit (
|
|
VOID
|
|
)
|
|
{
|
|
SVfrDataType *New = NULL;
|
|
UINT32 Index;
|
|
|
|
for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) {
|
|
New = new SVfrDataType;
|
|
if (New != NULL) {
|
|
strcpy (New->mTypeName, gInternalTypesTable[Index].mTypeName);
|
|
New->mType = gInternalTypesTable[Index].mType;
|
|
New->mAlign = gInternalTypesTable[Index].mAlign;
|
|
New->mTotalSize = gInternalTypesTable[Index].mSize;
|
|
if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_DATE") == 0) {
|
|
SVfrDataField *pYearField = new SVfrDataField;
|
|
SVfrDataField *pMonthField = new SVfrDataField;
|
|
SVfrDataField *pDayField = new SVfrDataField;
|
|
|
|
strcpy (pYearField->mFieldName, "Year");
|
|
GetDataType ((CHAR8 *)"UINT16", &pYearField->mFieldType);
|
|
pYearField->mOffset = 0;
|
|
pYearField->mNext = pMonthField;
|
|
pYearField->mArrayNum = 0;
|
|
|
|
strcpy (pMonthField->mFieldName, "Month");
|
|
GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType);
|
|
pMonthField->mOffset = 2;
|
|
pMonthField->mNext = pDayField;
|
|
pMonthField->mArrayNum = 0;
|
|
|
|
strcpy (pDayField->mFieldName, "Day");
|
|
GetDataType ((CHAR8 *)"UINT8", &pDayField->mFieldType);
|
|
pDayField->mOffset = 3;
|
|
pDayField->mNext = NULL;
|
|
pDayField->mArrayNum = 0;
|
|
|
|
New->mMembers = pYearField;
|
|
} else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_TIME") == 0) {
|
|
SVfrDataField *pHoursField = new SVfrDataField;
|
|
SVfrDataField *pMinutesField = new SVfrDataField;
|
|
SVfrDataField *pSecondsField = new SVfrDataField;
|
|
|
|
strcpy (pHoursField->mFieldName, "Hours");
|
|
GetDataType ((CHAR8 *)"UINT8", &pHoursField->mFieldType);
|
|
pHoursField->mOffset = 0;
|
|
pHoursField->mNext = pMinutesField;
|
|
pHoursField->mArrayNum = 0;
|
|
|
|
strcpy (pMinutesField->mFieldName, "Minutes");
|
|
GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType);
|
|
pMinutesField->mOffset = 1;
|
|
pMinutesField->mNext = pSecondsField;
|
|
pMinutesField->mArrayNum = 0;
|
|
|
|
strcpy (pSecondsField->mFieldName, "Seconds");
|
|
GetDataType ((CHAR8 *)"UINT8", &pSecondsField->mFieldType);
|
|
pSecondsField->mOffset = 2;
|
|
pSecondsField->mNext = NULL;
|
|
pSecondsField->mArrayNum = 0;
|
|
|
|
New->mMembers = pHoursField;
|
|
} else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_REF") == 0) {
|
|
SVfrDataField *pQuestionIdField = new SVfrDataField;
|
|
SVfrDataField *pFormIdField = new SVfrDataField;
|
|
SVfrDataField *pFormSetGuidField = new SVfrDataField;
|
|
SVfrDataField *pDevicePathField = new SVfrDataField;
|
|
|
|
strcpy (pQuestionIdField->mFieldName, "QuestionId");
|
|
GetDataType ((CHAR8 *)"UINT16", &pQuestionIdField->mFieldType);
|
|
pQuestionIdField->mOffset = 0;
|
|
pQuestionIdField->mNext = pFormIdField;
|
|
pQuestionIdField->mArrayNum = 0;
|
|
|
|
strcpy (pFormIdField->mFieldName, "FormId");
|
|
GetDataType ((CHAR8 *)"UINT16", &pFormIdField->mFieldType);
|
|
pFormIdField->mOffset = 2;
|
|
pFormIdField->mNext = pFormSetGuidField;
|
|
pFormIdField->mArrayNum = 0;
|
|
|
|
strcpy (pFormSetGuidField->mFieldName, "FormSetGuid");
|
|
GetDataType ((CHAR8 *)"EFI_GUID", &pFormSetGuidField->mFieldType);
|
|
pFormSetGuidField->mOffset = 4;
|
|
pFormSetGuidField->mNext = pDevicePathField;
|
|
pFormSetGuidField->mArrayNum = 0;
|
|
|
|
strcpy (pDevicePathField->mFieldName, "DevicePath");
|
|
GetDataType ((CHAR8 *)"EFI_STRING_ID", &pDevicePathField->mFieldType);
|
|
pDevicePathField->mOffset = 20;
|
|
pDevicePathField->mNext = NULL;
|
|
pDevicePathField->mArrayNum = 0;
|
|
|
|
New->mMembers = pQuestionIdField;
|
|
} else {
|
|
New->mMembers = NULL;
|
|
}
|
|
New->mNext = NULL;
|
|
RegisterNewType (New);
|
|
New = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
CVfrVarDataTypeDB::CVfrVarDataTypeDB (
|
|
VOID
|
|
)
|
|
{
|
|
mDataTypeList = NULL;
|
|
mNewDataType = NULL;
|
|
mCurrDataField = NULL;
|
|
mPackAlign = DEFAULT_PACK_ALIGN;
|
|
mPackStack = NULL;
|
|
mFirstNewDataTypeName = NULL;
|
|
|
|
InternalTypesListInit ();
|
|
}
|
|
|
|
CVfrVarDataTypeDB::~CVfrVarDataTypeDB (
|
|
VOID
|
|
)
|
|
{
|
|
SVfrDataType *pType;
|
|
SVfrDataField *pField;
|
|
SVfrPackStackNode *pPack;
|
|
|
|
if (mNewDataType != NULL) {
|
|
delete mNewDataType;
|
|
}
|
|
|
|
while (mDataTypeList != NULL) {
|
|
pType = mDataTypeList;
|
|
mDataTypeList = mDataTypeList->mNext;
|
|
while(pType->mMembers != NULL) {
|
|
pField = pType->mMembers;
|
|
pType->mMembers = pType->mMembers->mNext;
|
|
delete pField;
|
|
}
|
|
delete pType;
|
|
}
|
|
|
|
while (mPackStack != NULL) {
|
|
pPack = mPackStack;
|
|
mPackStack = mPackStack->mNext;
|
|
delete pPack;
|
|
}
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::Pack (
|
|
IN UINT32 LineNum,
|
|
IN UINT8 Action,
|
|
IN CHAR8 *Identifier,
|
|
IN UINT32 Number
|
|
)
|
|
{
|
|
UINT32 PackAlign;
|
|
CHAR8 Msg[MAX_STRING_LEN] = {0, };
|
|
|
|
if (Action & VFR_PACK_SHOW) {
|
|
sprintf (Msg, "value of pragma pack(show) == %d", mPackAlign);
|
|
gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Warning", Msg);
|
|
}
|
|
|
|
if (Action & VFR_PACK_PUSH) {
|
|
SVfrPackStackNode *pNew = NULL;
|
|
|
|
if ((pNew = new SVfrPackStackNode (Identifier, mPackAlign)) == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
pNew->mNext = mPackStack;
|
|
mPackStack = pNew;
|
|
}
|
|
|
|
if (Action & VFR_PACK_POP) {
|
|
SVfrPackStackNode *pNode = NULL;
|
|
|
|
if (mPackStack == NULL) {
|
|
gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "#pragma pack(pop...) : more pops than pushes");
|
|
}
|
|
|
|
for (pNode = mPackStack; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->Match (Identifier) == TRUE) {
|
|
mPackAlign = pNode->mNumber;
|
|
mPackStack = pNode->mNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Action & VFR_PACK_ASSIGN) {
|
|
PackAlign = (Number > 1) ? Number + Number % 2 : Number;
|
|
if ((PackAlign == 0) || (PackAlign > 16)) {
|
|
gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "expected pragma parameter to be '1', '2', '4', '8', or '16'");
|
|
} else {
|
|
mPackAlign = PackAlign;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
CVfrVarDataTypeDB::DeclareDataTypeBegin (
|
|
VOID
|
|
)
|
|
{
|
|
SVfrDataType *pNewType = NULL;
|
|
|
|
pNewType = new SVfrDataType;
|
|
pNewType->mTypeName[0] = '\0';
|
|
pNewType->mType = EFI_IFR_TYPE_OTHER;
|
|
pNewType->mAlign = DEFAULT_ALIGN;
|
|
pNewType->mTotalSize = 0;
|
|
pNewType->mMembers = NULL;
|
|
pNewType->mNext = NULL;
|
|
|
|
mNewDataType = pNewType;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::SetNewTypeName (
|
|
IN CHAR8 *TypeName
|
|
)
|
|
{
|
|
SVfrDataType *pType;
|
|
|
|
if (mNewDataType == NULL) {
|
|
return VFR_RETURN_ERROR_SKIPED;
|
|
}
|
|
if (TypeName == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
if (strlen(TypeName) >= MAX_NAME_LEN) {
|
|
return VFR_RETURN_INVALID_PARAMETER;
|
|
}
|
|
|
|
for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) {
|
|
if (strcmp(pType->mTypeName, TypeName) == 0) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
}
|
|
|
|
strcpy(mNewDataType->mTypeName, TypeName);
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::DataTypeAddField (
|
|
IN CHAR8 *FieldName,
|
|
IN CHAR8 *TypeName,
|
|
IN UINT32 ArrayNum
|
|
)
|
|
{
|
|
SVfrDataField *pNewField = NULL;
|
|
SVfrDataType *pFieldType = NULL;
|
|
SVfrDataField *pTmp;
|
|
UINT32 Align;
|
|
|
|
CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS);
|
|
|
|
if (strlen (FieldName) >= MAX_NAME_LEN) {
|
|
return VFR_RETURN_INVALID_PARAMETER;
|
|
}
|
|
|
|
for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) {
|
|
if (strcmp (pTmp->mFieldName, FieldName) == 0) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
}
|
|
|
|
Align = MIN (mPackAlign, pFieldType->mAlign);
|
|
|
|
if ((pNewField = new SVfrDataField) == NULL) {
|
|
return VFR_RETURN_OUT_FOR_RESOURCES;
|
|
}
|
|
strcpy (pNewField->mFieldName, FieldName);
|
|
pNewField->mFieldType = pFieldType;
|
|
pNewField->mArrayNum = ArrayNum;
|
|
if ((mNewDataType->mTotalSize % Align) == 0) {
|
|
pNewField->mOffset = mNewDataType->mTotalSize;
|
|
} else {
|
|
pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align);
|
|
}
|
|
if (mNewDataType->mMembers == NULL) {
|
|
mNewDataType->mMembers = pNewField;
|
|
pNewField->mNext = NULL;
|
|
} else {
|
|
for (pTmp = mNewDataType->mMembers; pTmp->mNext != NULL; pTmp = pTmp->mNext)
|
|
;
|
|
pTmp->mNext = pNewField;
|
|
pNewField->mNext = NULL;
|
|
}
|
|
|
|
mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign));
|
|
mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum);
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
CVfrVarDataTypeDB::DeclareDataTypeEnd (
|
|
VOID
|
|
)
|
|
{
|
|
if (mNewDataType->mTypeName[0] == '\0') {
|
|
return;
|
|
}
|
|
|
|
if ((mNewDataType->mTotalSize % mNewDataType->mAlign) !=0) {
|
|
mNewDataType->mTotalSize += ALIGN_STUFF (mNewDataType->mTotalSize, mNewDataType->mAlign);
|
|
}
|
|
|
|
RegisterNewType (mNewDataType);
|
|
if (mFirstNewDataTypeName == NULL) {
|
|
mFirstNewDataTypeName = mNewDataType->mTypeName;
|
|
}
|
|
|
|
mNewDataType = NULL;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::GetDataType (
|
|
IN CHAR8 *TypeName,
|
|
OUT SVfrDataType **DataType
|
|
)
|
|
{
|
|
SVfrDataType *pDataType = NULL;
|
|
|
|
if (TypeName == NULL) {
|
|
return VFR_RETURN_ERROR_SKIPED;
|
|
}
|
|
|
|
if (DataType == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
*DataType = NULL;
|
|
|
|
for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) {
|
|
if (strcmp (TypeName, pDataType->mTypeName) == 0) {
|
|
*DataType = pDataType;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::GetDataTypeSize (
|
|
IN UINT8 DataType,
|
|
OUT UINT32 *Size
|
|
)
|
|
{
|
|
SVfrDataType *pDataType = NULL;
|
|
|
|
if (Size == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
*Size = 0;
|
|
DataType = DataType & 0x0F;
|
|
|
|
//
|
|
// For user defined data type, the size can't be got by this function.
|
|
//
|
|
if (DataType == EFI_IFR_TYPE_OTHER) {
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) {
|
|
if (DataType == pDataType->mType) {
|
|
*Size = pDataType->mTotalSize;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::GetDataTypeSize (
|
|
IN CHAR8 *TypeName,
|
|
OUT UINT32 *Size
|
|
)
|
|
{
|
|
SVfrDataType *pDataType = NULL;
|
|
|
|
if (Size == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
*Size = 0;
|
|
|
|
for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) {
|
|
if (strcmp (TypeName, pDataType->mTypeName) == 0) {
|
|
*Size = pDataType->mTotalSize;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::GetDataFieldInfo (
|
|
IN CHAR8 *VarStr,
|
|
OUT UINT16 &Offset,
|
|
OUT UINT8 &Type,
|
|
OUT UINT32 &Size
|
|
)
|
|
{
|
|
CHAR8 TName[MAX_NAME_LEN], FName[MAX_NAME_LEN];
|
|
UINT32 ArrayIdx, Tmp;
|
|
SVfrDataType *pType = NULL;
|
|
SVfrDataField *pField = NULL;
|
|
|
|
Offset = 0;
|
|
Type = EFI_IFR_TYPE_OTHER;
|
|
Size = 0;
|
|
|
|
CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS);
|
|
CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS);
|
|
|
|
//
|
|
// if it is not struct data type
|
|
//
|
|
Type = pType->mType;
|
|
Size = pType->mTotalSize;
|
|
|
|
while (*VarStr != '\0') {
|
|
CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS);
|
|
CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS);
|
|
pType = pField->mFieldType;
|
|
CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp), VFR_RETURN_SUCCESS);
|
|
Offset = (UINT16) (Offset + Tmp);
|
|
Type = GetFieldWidth (pField);
|
|
Size = GetFieldSize (pField, ArrayIdx);
|
|
}
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrVarDataTypeDB::GetUserDefinedTypeNameList (
|
|
OUT CHAR8 ***NameList,
|
|
OUT UINT32 *ListSize
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
SVfrDataType *pType;
|
|
|
|
if ((NameList == NULL) || (ListSize == NULL)) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
*NameList = NULL;
|
|
*ListSize = 0;
|
|
|
|
for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) {
|
|
if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) {
|
|
(*ListSize)++;
|
|
}
|
|
}
|
|
|
|
if (*ListSize == 0) {
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
if ((*NameList = new CHAR8*[*ListSize]) == NULL) {
|
|
*ListSize = 0;
|
|
return VFR_RETURN_OUT_FOR_RESOURCES;
|
|
}
|
|
|
|
for (Index = 0, pType = mDataTypeList; pType != NULL; pType = pType->mNext, Index++) {
|
|
if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) {
|
|
(*NameList)[Index] = pType->mTypeName;
|
|
}
|
|
}
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
CVfrVarDataTypeDB::IsTypeNameDefined (
|
|
IN CHAR8 *TypeName
|
|
)
|
|
{
|
|
SVfrDataType *pType;
|
|
|
|
if (TypeName == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) {
|
|
if (strcmp (pType->mTypeName, TypeName) == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
CVfrVarDataTypeDB::Dump (
|
|
IN FILE *File
|
|
)
|
|
{
|
|
SVfrDataType *pTNode;
|
|
SVfrDataField *pFNode;
|
|
|
|
fprintf (File, "\n\n***************************************************************\n");
|
|
fprintf (File, "\t\tmPackAlign = %x\n", mPackAlign);
|
|
for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) {
|
|
fprintf (File, "\t\tstruct %s : mAlign [%d] mTotalSize [0x%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize);
|
|
fprintf (File, "\t\tstruct %s {\n", pTNode->mTypeName);
|
|
for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) {
|
|
if (pFNode->mArrayNum > 0) {
|
|
fprintf (File, "\t\t\t+%08d[%08x] %s[%d] <%s>\n", pFNode->mOffset, pFNode->mOffset,
|
|
pFNode->mFieldName, pFNode->mArrayNum, pFNode->mFieldType->mTypeName);
|
|
} else {
|
|
fprintf (File, "\t\t\t+%08d[%08x] %s <%s>\n", pFNode->mOffset, pFNode->mOffset,
|
|
pFNode->mFieldName, pFNode->mFieldType->mTypeName);
|
|
}
|
|
}
|
|
fprintf (File, "\t\t};\n");
|
|
fprintf (File, "---------------------------------------------------------------\n");
|
|
}
|
|
fprintf (File, "***************************************************************\n");
|
|
}
|
|
|
|
#ifdef CVFR_VARDATATYPEDB_DEBUG
|
|
VOID
|
|
CVfrVarDataTypeDB::ParserDB (
|
|
VOID
|
|
)
|
|
{
|
|
SVfrDataType *pTNode;
|
|
SVfrDataField *pFNode;
|
|
|
|
printf ("***************************************************************\n");
|
|
printf ("\t\tmPackAlign = %x\n", mPackAlign);
|
|
for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) {
|
|
printf ("\t\tstruct %s : mAlign [%x] mTotalSize [%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize);
|
|
printf ("\t\tstruct %s {\n", pTNode->mTypeName);
|
|
for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) {
|
|
printf ("\t\t\t%s\t%s\n", pFNode->mFieldType->mTypeName, pFNode->mFieldName);
|
|
}
|
|
printf ("\t\t};\n");
|
|
printf ("---------------------------------------------------------------\n");
|
|
}
|
|
printf ("***************************************************************\n");
|
|
}
|
|
#endif
|
|
|
|
SVfrVarStorageNode::SVfrVarStorageNode (
|
|
IN EFI_GUID *Guid,
|
|
IN CHAR8 *StoreName,
|
|
IN EFI_VARSTORE_ID VarStoreId,
|
|
IN EFI_STRING_ID VarName,
|
|
IN UINT32 VarSize,
|
|
IN BOOLEAN Flag
|
|
)
|
|
{
|
|
if (Guid != NULL) {
|
|
mGuid = *Guid;
|
|
} else {
|
|
memset (&Guid, 0, sizeof (EFI_GUID));
|
|
}
|
|
if (StoreName != NULL) {
|
|
mVarStoreName = new CHAR8[strlen(StoreName) + 1];
|
|
strcpy (mVarStoreName, StoreName);
|
|
} else {
|
|
mVarStoreName = NULL;
|
|
}
|
|
mNext = NULL;
|
|
mVarStoreId = VarStoreId;
|
|
mVarStoreType = EFI_VFR_VARSTORE_EFI;
|
|
mStorageInfo.mEfiVar.mEfiVarName = VarName;
|
|
mStorageInfo.mEfiVar.mEfiVarSize = VarSize;
|
|
mAssignedFlag = Flag;
|
|
}
|
|
|
|
SVfrVarStorageNode::SVfrVarStorageNode (
|
|
IN EFI_GUID *Guid,
|
|
IN CHAR8 *StoreName,
|
|
IN EFI_VARSTORE_ID VarStoreId,
|
|
IN SVfrDataType *DataType,
|
|
IN BOOLEAN Flag
|
|
)
|
|
{
|
|
if (Guid != NULL) {
|
|
mGuid = *Guid;
|
|
} else {
|
|
memset (&Guid, 0, sizeof (EFI_GUID));
|
|
}
|
|
if (StoreName != NULL) {
|
|
mVarStoreName = new CHAR8[strlen(StoreName) + 1];
|
|
strcpy (mVarStoreName, StoreName);
|
|
} else {
|
|
mVarStoreName = NULL;
|
|
}
|
|
mNext = NULL;
|
|
mVarStoreId = VarStoreId;
|
|
mVarStoreType = EFI_VFR_VARSTORE_BUFFER;
|
|
mStorageInfo.mDataType = DataType;
|
|
mAssignedFlag = Flag;
|
|
}
|
|
|
|
SVfrVarStorageNode::SVfrVarStorageNode (
|
|
IN CHAR8 *StoreName,
|
|
IN EFI_VARSTORE_ID VarStoreId
|
|
)
|
|
{
|
|
if (StoreName != NULL) {
|
|
mVarStoreName = new CHAR8[strlen(StoreName) + 1];
|
|
strcpy (mVarStoreName, StoreName);
|
|
} else {
|
|
mVarStoreName = NULL;
|
|
}
|
|
mNext = NULL;
|
|
mVarStoreId = VarStoreId;
|
|
mVarStoreType = EFI_VFR_VARSTORE_NAME;
|
|
mStorageInfo.mNameSpace.mNameTable = new EFI_VARSTORE_ID[DEFAULT_NAME_TABLE_ITEMS];
|
|
mStorageInfo.mNameSpace.mTableSize = 0;
|
|
}
|
|
|
|
SVfrVarStorageNode::~SVfrVarStorageNode (
|
|
VOID
|
|
)
|
|
{
|
|
if (mVarStoreName != NULL) {
|
|
delete mVarStoreName;
|
|
}
|
|
|
|
if (mVarStoreType == EFI_VFR_VARSTORE_NAME) {
|
|
delete mStorageInfo.mNameSpace.mNameTable;
|
|
}
|
|
}
|
|
|
|
CVfrDataStorage::CVfrDataStorage (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
|
|
for (Index = 0; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) {
|
|
mFreeVarStoreIdBitMap[Index] = 0;
|
|
}
|
|
|
|
// Question ID 0 is reserved.
|
|
mFreeVarStoreIdBitMap[0] = 0x80000000;
|
|
|
|
mBufferVarStoreList = NULL;
|
|
mEfiVarStoreList = NULL;
|
|
mNameVarStoreList = NULL;
|
|
mCurrVarStorageNode = NULL;
|
|
mNewVarStorageNode = NULL;
|
|
}
|
|
|
|
CVfrDataStorage::~CVfrDataStorage (
|
|
VOID
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode;
|
|
|
|
while (mBufferVarStoreList != NULL) {
|
|
pNode = mBufferVarStoreList;
|
|
mBufferVarStoreList = mBufferVarStoreList->mNext;
|
|
delete pNode;
|
|
}
|
|
while (mEfiVarStoreList != NULL) {
|
|
pNode = mEfiVarStoreList;
|
|
mEfiVarStoreList = mEfiVarStoreList->mNext;
|
|
delete pNode;
|
|
}
|
|
while (mNameVarStoreList != NULL) {
|
|
pNode = mNameVarStoreList;
|
|
mNameVarStoreList = mNameVarStoreList->mNext;
|
|
delete pNode;
|
|
}
|
|
if (mNewVarStorageNode != NULL) {
|
|
delete mNewVarStorageNode;
|
|
}
|
|
}
|
|
|
|
EFI_VARSTORE_ID
|
|
CVfrDataStorage::GetFreeVarStoreId (
|
|
EFI_VFR_VARSTORE_TYPE VarType
|
|
)
|
|
{
|
|
UINT32 Index, Mask, Offset;
|
|
|
|
//
|
|
// Assign the different ID range for the different type VarStore to support Framework Vfr
|
|
//
|
|
Index = 0;
|
|
if ((!VfrCompatibleMode) || (VarType == EFI_VFR_VARSTORE_BUFFER)) {
|
|
Index = 0;
|
|
} else if (VarType == EFI_VFR_VARSTORE_EFI) {
|
|
Index = 1;
|
|
} else if (VarType == EFI_VFR_VARSTORE_NAME) {
|
|
Index = 2;
|
|
}
|
|
|
|
for (; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) {
|
|
if (mFreeVarStoreIdBitMap[Index] != 0xFFFFFFFF) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
|
|
if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) {
|
|
mFreeVarStoreIdBitMap[Index] |= Mask;
|
|
return (EFI_VARSTORE_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset);
|
|
}
|
|
}
|
|
|
|
return EFI_VARSTORE_ID_INVALID;
|
|
}
|
|
|
|
BOOLEAN
|
|
CVfrDataStorage::ChekVarStoreIdFree (
|
|
IN EFI_VARSTORE_ID VarStoreId
|
|
)
|
|
{
|
|
UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32);
|
|
UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
|
|
|
|
return (mFreeVarStoreIdBitMap[Index] & (0x80000000 >> Offset)) == 0;
|
|
}
|
|
|
|
VOID
|
|
CVfrDataStorage::MarkVarStoreIdUsed (
|
|
IN EFI_VARSTORE_ID VarStoreId
|
|
)
|
|
{
|
|
UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32);
|
|
UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
|
|
|
|
mFreeVarStoreIdBitMap[Index] |= (0x80000000 >> Offset);
|
|
}
|
|
|
|
VOID
|
|
CVfrDataStorage::MarkVarStoreIdUnused (
|
|
IN EFI_VARSTORE_ID VarStoreId
|
|
)
|
|
{
|
|
UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32);
|
|
UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
|
|
|
|
mFreeVarStoreIdBitMap[Index] &= ~(0x80000000 >> Offset);
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::DeclareNameVarStoreBegin (
|
|
IN CHAR8 *StoreName,
|
|
IN EFI_VARSTORE_ID VarStoreId
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode = NULL;
|
|
EFI_VARSTORE_ID TmpVarStoreId;
|
|
|
|
if (StoreName == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if (GetVarStoreId (StoreName, &TmpVarStoreId) == VFR_RETURN_SUCCESS) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
|
|
if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
|
|
VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME);
|
|
} else {
|
|
if (ChekVarStoreIdFree (VarStoreId) == FALSE) {
|
|
return VFR_RETURN_VARSTOREID_REDEFINED;
|
|
}
|
|
MarkVarStoreIdUsed (VarStoreId);
|
|
}
|
|
|
|
if ((pNode = new SVfrVarStorageNode (StoreName, VarStoreId)) == NULL) {
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
mNewVarStorageNode = pNode;
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::NameTableAddItem (
|
|
IN EFI_STRING_ID Item
|
|
)
|
|
{
|
|
EFI_VARSTORE_ID *NewTable, *OldTable;
|
|
UINT32 TableSize;
|
|
|
|
OldTable = mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable;
|
|
TableSize = mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize;
|
|
|
|
if ((TableSize != 0) && ((TableSize % DEFAULT_NAME_TABLE_ITEMS) == 0)) {
|
|
if ((NewTable = new EFI_VARSTORE_ID[TableSize + DEFAULT_NAME_TABLE_ITEMS]) == NULL) {
|
|
return VFR_RETURN_OUT_FOR_RESOURCES;
|
|
}
|
|
memcpy (NewTable, OldTable, TableSize);
|
|
mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable = NewTable;
|
|
}
|
|
|
|
mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable[TableSize++] = Item;
|
|
mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize = TableSize;
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::DeclareNameVarStoreEnd (
|
|
IN EFI_GUID *Guid
|
|
)
|
|
{
|
|
mNewVarStorageNode->mGuid = *Guid;
|
|
mNewVarStorageNode->mNext = mNameVarStoreList;
|
|
mNameVarStoreList = mNewVarStorageNode;
|
|
|
|
mNewVarStorageNode = NULL;
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::DeclareEfiVarStore (
|
|
IN CHAR8 *StoreName,
|
|
IN EFI_GUID *Guid,
|
|
IN EFI_STRING_ID NameStrId,
|
|
IN UINT32 VarSize,
|
|
IN BOOLEAN Flag
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode;
|
|
EFI_VARSTORE_ID VarStoreId;
|
|
|
|
if ((StoreName == NULL) || (Guid == NULL)) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if (VarSize > sizeof (UINT64)) {
|
|
return VFR_RETURN_EFIVARSTORE_SIZE_ERROR;
|
|
}
|
|
|
|
if (GetVarStoreId (StoreName, &VarStoreId, Guid) == VFR_RETURN_SUCCESS) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
|
|
VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI);
|
|
if ((pNode = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, NameStrId, VarSize, Flag)) == NULL) {
|
|
return VFR_RETURN_OUT_FOR_RESOURCES;
|
|
}
|
|
|
|
pNode->mNext = mEfiVarStoreList;
|
|
mEfiVarStoreList = pNode;
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::DeclareBufferVarStore (
|
|
IN CHAR8 *StoreName,
|
|
IN EFI_GUID *Guid,
|
|
IN CVfrVarDataTypeDB *DataTypeDB,
|
|
IN CHAR8 *TypeName,
|
|
IN EFI_VARSTORE_ID VarStoreId,
|
|
IN BOOLEAN Flag
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNew = NULL;
|
|
SVfrDataType *pDataType = NULL;
|
|
EFI_VARSTORE_ID TempVarStoreId;
|
|
|
|
if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if (GetVarStoreId (StoreName, &TempVarStoreId, Guid) == VFR_RETURN_SUCCESS) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
|
|
CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS);
|
|
|
|
if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
|
|
VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_BUFFER);
|
|
} else {
|
|
if (ChekVarStoreIdFree (VarStoreId) == FALSE) {
|
|
return VFR_RETURN_VARSTOREID_REDEFINED;
|
|
}
|
|
MarkVarStoreIdUsed (VarStoreId);
|
|
}
|
|
|
|
if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, Flag)) == NULL) {
|
|
return VFR_RETURN_OUT_FOR_RESOURCES;
|
|
}
|
|
|
|
pNew->mNext = mBufferVarStoreList;
|
|
mBufferVarStoreList = pNew;
|
|
|
|
if (gCVfrBufferConfig.Register(StoreName, Guid) != 0) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::GetVarStoreByDataType (
|
|
IN CHAR8 *DataTypeName,
|
|
OUT SVfrVarStorageNode **VarNode,
|
|
IN EFI_GUID *VarGuid
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode;
|
|
SVfrVarStorageNode *MatchNode;
|
|
|
|
//
|
|
// Framework VFR uses Data type name as varstore name, so don't need check again.
|
|
//
|
|
if (VfrCompatibleMode) {
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
MatchNode = NULL;
|
|
for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (strcmp (pNode->mStorageInfo.mDataType->mTypeName, DataTypeName) != 0) {
|
|
continue;
|
|
}
|
|
|
|
if ((VarGuid != NULL)) {
|
|
if (memcmp (VarGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) {
|
|
*VarNode = pNode;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
} else {
|
|
if (MatchNode == NULL) {
|
|
MatchNode = pNode;
|
|
} else {
|
|
//
|
|
// More than one varstores referred the same data structures.
|
|
//
|
|
return VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (MatchNode == NULL) {
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
*VarNode = MatchNode;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VARSTORE_ID
|
|
CVfrDataStorage::CheckGuidField (
|
|
IN SVfrVarStorageNode *pNode,
|
|
IN EFI_GUID *StoreGuid,
|
|
IN BOOLEAN *HasFoundOne,
|
|
OUT EFI_VFR_RETURN_CODE *ReturnCode
|
|
)
|
|
{
|
|
if (StoreGuid != NULL) {
|
|
//
|
|
// If has guid info, compare the guid filed.
|
|
//
|
|
if (memcmp (StoreGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) {
|
|
//
|
|
// Both name and guid are same, this this varstore.
|
|
//
|
|
mCurrVarStorageNode = pNode;
|
|
*ReturnCode = VFR_RETURN_SUCCESS;
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
//
|
|
// Not has Guid field, check whether this name is the only one.
|
|
//
|
|
if (*HasFoundOne) {
|
|
//
|
|
// The name has conflict, return name redefined.
|
|
//
|
|
*ReturnCode = VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR;
|
|
return TRUE;
|
|
}
|
|
|
|
*HasFoundOne = TRUE;
|
|
mCurrVarStorageNode = pNode;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Base on the input store name and guid to find the varstore id.
|
|
|
|
If both name and guid are inputed, base on the name and guid to
|
|
found the varstore. If only name inputed, base on the name to
|
|
found the varstore and go on to check whether more than one varstore
|
|
has the same name. If only has found one varstore, return this
|
|
varstore; if more than one varstore has same name, return varstore
|
|
name redefined error. If no varstore found by varstore name, call
|
|
function GetVarStoreByDataType and use inputed varstore name as
|
|
data type name to search.
|
|
**/
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::GetVarStoreId (
|
|
IN CHAR8 *StoreName,
|
|
OUT EFI_VARSTORE_ID *VarStoreId,
|
|
IN EFI_GUID *StoreGuid
|
|
)
|
|
{
|
|
EFI_VFR_RETURN_CODE ReturnCode;
|
|
SVfrVarStorageNode *pNode;
|
|
BOOLEAN HasFoundOne = FALSE;
|
|
|
|
mCurrVarStorageNode = NULL;
|
|
|
|
for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
|
|
if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
|
|
*VarStoreId = mCurrVarStorageNode->mVarStoreId;
|
|
return ReturnCode;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
|
|
if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
|
|
*VarStoreId = mCurrVarStorageNode->mVarStoreId;
|
|
return ReturnCode;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
|
|
if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
|
|
*VarStoreId = mCurrVarStorageNode->mVarStoreId;
|
|
return ReturnCode;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (HasFoundOne) {
|
|
*VarStoreId = mCurrVarStorageNode->mVarStoreId;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
*VarStoreId = EFI_VARSTORE_ID_INVALID;
|
|
|
|
//
|
|
// Assume that Data strucutre name is used as StoreName, and check again.
|
|
//
|
|
ReturnCode = GetVarStoreByDataType (StoreName, &pNode, StoreGuid);
|
|
if (pNode != NULL) {
|
|
mCurrVarStorageNode = pNode;
|
|
*VarStoreId = pNode->mVarStoreId;
|
|
}
|
|
|
|
return ReturnCode;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::GetBufferVarStoreDataTypeName (
|
|
IN EFI_VARSTORE_ID VarStoreId,
|
|
OUT CHAR8 **DataTypeName
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode;
|
|
|
|
if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
*DataTypeName = pNode->mStorageInfo.mDataType->mTypeName;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_VARSTORE_TYPE
|
|
CVfrDataStorage::GetVarStoreType (
|
|
IN EFI_VARSTORE_ID VarStoreId
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode;
|
|
EFI_VFR_VARSTORE_TYPE VarStoreType;
|
|
|
|
VarStoreType = EFI_VFR_VARSTORE_INVALID;
|
|
|
|
if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
|
|
return VarStoreType;
|
|
}
|
|
|
|
for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
VarStoreType = pNode->mVarStoreType;
|
|
return VarStoreType;
|
|
}
|
|
}
|
|
|
|
for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
VarStoreType = pNode->mVarStoreType;
|
|
return VarStoreType;
|
|
}
|
|
}
|
|
|
|
for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
VarStoreType = pNode->mVarStoreType;
|
|
return VarStoreType;
|
|
}
|
|
}
|
|
|
|
return VarStoreType;
|
|
}
|
|
|
|
EFI_GUID *
|
|
CVfrDataStorage::GetVarStoreGuid (
|
|
IN EFI_VARSTORE_ID VarStoreId
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode;
|
|
EFI_GUID *VarGuid;
|
|
|
|
VarGuid = NULL;
|
|
|
|
if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
|
|
return VarGuid;
|
|
}
|
|
|
|
for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
VarGuid = &pNode->mGuid;
|
|
return VarGuid;
|
|
}
|
|
}
|
|
|
|
for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
VarGuid = &pNode->mGuid;
|
|
return VarGuid;
|
|
}
|
|
}
|
|
|
|
for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
VarGuid = &pNode->mGuid;
|
|
return VarGuid;
|
|
}
|
|
}
|
|
|
|
return VarGuid;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::GetVarStoreName (
|
|
IN EFI_VARSTORE_ID VarStoreId,
|
|
OUT CHAR8 **VarStoreName
|
|
)
|
|
{
|
|
SVfrVarStorageNode *pNode;
|
|
|
|
if (VarStoreName == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
*VarStoreName = pNode->mVarStoreName;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
*VarStoreName = pNode->mVarStoreName;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mVarStoreId == VarStoreId) {
|
|
*VarStoreName = pNode->mVarStoreName;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
*VarStoreName = NULL;
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::GetEfiVarStoreInfo (
|
|
IN OUT EFI_VARSTORE_INFO *Info
|
|
)
|
|
{
|
|
if (Info == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if (mCurrVarStorageNode == NULL) {
|
|
return VFR_RETURN_GET_EFIVARSTORE_ERROR;
|
|
}
|
|
|
|
Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarName;
|
|
Info->mVarTotalSize = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarSize;
|
|
switch (Info->mVarTotalSize) {
|
|
case 1:
|
|
Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
|
|
break;
|
|
case 2:
|
|
Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_16;
|
|
break;
|
|
case 4:
|
|
Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_32;
|
|
break;
|
|
case 8:
|
|
Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_64;
|
|
break;
|
|
default :
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDataStorage::GetNameVarStoreInfo (
|
|
OUT EFI_VARSTORE_INFO *Info,
|
|
IN UINT32 Index
|
|
)
|
|
{
|
|
if (Info == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if (mCurrVarStorageNode == NULL) {
|
|
return VFR_RETURN_GET_NVVARSTORE_ERROR;
|
|
}
|
|
|
|
//
|
|
// Framework Vfr file Index is from 1, but Uefi Vfr file Index is from 0.
|
|
//
|
|
if (VfrCompatibleMode) {
|
|
if (Index == 0) {
|
|
return VFR_RETURN_ERROR_ARRARY_NUM;
|
|
}
|
|
Index --;
|
|
}
|
|
|
|
Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mNameSpace.mNameTable[Index];
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
SVfrDefaultStoreNode::SVfrDefaultStoreNode (
|
|
IN EFI_IFR_DEFAULTSTORE *ObjBinAddr,
|
|
IN CHAR8 *RefName,
|
|
IN EFI_STRING_ID DefaultStoreNameId,
|
|
IN UINT16 DefaultId
|
|
)
|
|
{
|
|
mObjBinAddr = ObjBinAddr;
|
|
|
|
if (RefName != NULL) {
|
|
mRefName = new CHAR8[strlen (RefName) + 1];
|
|
strcpy (mRefName, RefName);
|
|
} else {
|
|
mRefName = NULL;
|
|
}
|
|
|
|
mNext = NULL;
|
|
mDefaultId = DefaultId;
|
|
mDefaultStoreNameId = DefaultStoreNameId;
|
|
}
|
|
|
|
SVfrDefaultStoreNode::~SVfrDefaultStoreNode (
|
|
VOID
|
|
)
|
|
{
|
|
if (mRefName != NULL) {
|
|
delete mRefName;
|
|
}
|
|
}
|
|
|
|
CVfrDefaultStore::CVfrDefaultStore (
|
|
VOID
|
|
)
|
|
{
|
|
mDefaultStoreList = NULL;
|
|
}
|
|
|
|
CVfrDefaultStore::~CVfrDefaultStore (
|
|
VOID
|
|
)
|
|
{
|
|
SVfrDefaultStoreNode *pTmp = NULL;
|
|
|
|
while (mDefaultStoreList != NULL) {
|
|
pTmp = mDefaultStoreList;
|
|
mDefaultStoreList = mDefaultStoreList->mNext;
|
|
delete pTmp;
|
|
}
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDefaultStore::RegisterDefaultStore (
|
|
IN CHAR8 *ObjBinAddr,
|
|
IN CHAR8 *RefName,
|
|
IN EFI_STRING_ID DefaultStoreNameId,
|
|
IN UINT16 DefaultId
|
|
)
|
|
{
|
|
SVfrDefaultStoreNode *pNode = NULL;
|
|
|
|
if (RefName == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (strcmp (pNode->mRefName, RefName) == 0) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
}
|
|
|
|
if ((pNode = new SVfrDefaultStoreNode ((EFI_IFR_DEFAULTSTORE *)ObjBinAddr, RefName, DefaultStoreNameId, DefaultId)) == NULL) {
|
|
return VFR_RETURN_OUT_FOR_RESOURCES;
|
|
}
|
|
|
|
pNode->mNext = mDefaultStoreList;
|
|
mDefaultStoreList = pNode;
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* assign new reference name or new default store name id only if
|
|
* the original is invalid
|
|
*/
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDefaultStore::ReRegisterDefaultStoreById (
|
|
IN UINT16 DefaultId,
|
|
IN CHAR8 *RefName,
|
|
IN EFI_STRING_ID DefaultStoreNameId
|
|
)
|
|
{
|
|
SVfrDefaultStoreNode *pNode = NULL;
|
|
|
|
for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mDefaultId == DefaultId) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pNode == NULL) {
|
|
return VFR_RETURN_UNDEFINED;
|
|
} else {
|
|
if (pNode->mDefaultStoreNameId == EFI_STRING_ID_INVALID) {
|
|
pNode->mDefaultStoreNameId = DefaultStoreNameId;
|
|
if (pNode->mObjBinAddr != NULL) {
|
|
pNode->mObjBinAddr->DefaultName = DefaultStoreNameId;
|
|
}
|
|
} else {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
|
|
if (RefName != NULL) {
|
|
delete pNode->mRefName;
|
|
pNode->mRefName = new CHAR8[strlen (RefName) + 1];
|
|
if (pNode->mRefName != NULL) {
|
|
strcpy (pNode->mRefName, RefName);
|
|
}
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
CVfrDefaultStore::DefaultIdRegistered (
|
|
IN UINT16 DefaultId
|
|
)
|
|
{
|
|
SVfrDefaultStoreNode *pNode = NULL;
|
|
|
|
for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mDefaultId == DefaultId) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDefaultStore::GetDefaultId (
|
|
IN CHAR8 *RefName,
|
|
OUT UINT16 *DefaultId
|
|
)
|
|
{
|
|
SVfrDefaultStoreNode *pTmp = NULL;
|
|
|
|
if (DefaultId == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
for (pTmp = mDefaultStoreList; pTmp != NULL; pTmp = pTmp->mNext) {
|
|
if (strcmp (pTmp->mRefName, RefName) == 0) {
|
|
*DefaultId = pTmp->mDefaultId;
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrDefaultStore::BufferVarStoreAltConfigAdd (
|
|
IN EFI_VARSTORE_ID DefaultId,
|
|
IN EFI_VARSTORE_INFO &Info,
|
|
IN CHAR8 *VarStoreName,
|
|
IN EFI_GUID *VarStoreGuid,
|
|
IN UINT8 Type,
|
|
IN EFI_IFR_TYPE_VALUE Value
|
|
)
|
|
{
|
|
SVfrDefaultStoreNode *pNode = NULL;
|
|
CHAR8 NewAltCfg[2 * 2 * sizeof (UINT16) + 1] = {0,};
|
|
INTN Returnvalue = 0;
|
|
|
|
if (VarStoreName == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mDefaultId == DefaultId) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pNode == NULL) {
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
gCVfrBufferConfig.Open ();
|
|
|
|
sprintf (NewAltCfg, "%04x", pNode->mDefaultId);
|
|
if ((Returnvalue = gCVfrBufferConfig.Select(VarStoreName, VarStoreGuid)) == 0) {
|
|
if ((Returnvalue = gCVfrBufferConfig.Write ('a', VarStoreName, VarStoreGuid, NewAltCfg, Type, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value)) != 0) {
|
|
goto WriteError;
|
|
}
|
|
}
|
|
|
|
gCVfrBufferConfig.Close ();
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
|
|
WriteError:
|
|
gCVfrBufferConfig.Close ();
|
|
return (EFI_VFR_RETURN_CODE)Returnvalue;
|
|
}
|
|
|
|
SVfrRuleNode::SVfrRuleNode (
|
|
IN CHAR8 *RuleName,
|
|
IN UINT8 RuleId
|
|
)
|
|
{
|
|
if (RuleName != NULL) {
|
|
mRuleName = new CHAR8[strlen (RuleName) + 1];
|
|
strcpy (mRuleName, RuleName);
|
|
} else {
|
|
mRuleName = NULL;
|
|
}
|
|
|
|
mNext = NULL;
|
|
mRuleId = RuleId;
|
|
}
|
|
|
|
SVfrRuleNode::~SVfrRuleNode (
|
|
VOID
|
|
)
|
|
{
|
|
if (mRuleName != NULL) {
|
|
delete mRuleName;
|
|
}
|
|
}
|
|
|
|
CVfrRulesDB::CVfrRulesDB ()
|
|
{
|
|
mRuleList = NULL;
|
|
mFreeRuleId = EFI_VARSTORE_ID_START;
|
|
}
|
|
|
|
CVfrRulesDB::~CVfrRulesDB ()
|
|
{
|
|
SVfrRuleNode *pNode;
|
|
|
|
while(mRuleList != NULL) {
|
|
pNode = mRuleList;
|
|
mRuleList = mRuleList->mNext;
|
|
delete pNode;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CVfrRulesDB::RegisterRule (
|
|
IN CHAR8 *RuleName
|
|
)
|
|
{
|
|
SVfrRuleNode *pNew;
|
|
|
|
if (RuleName == NULL) {
|
|
return ;
|
|
}
|
|
|
|
if ((pNew = new SVfrRuleNode (RuleName, mFreeRuleId)) == NULL) {
|
|
return ;
|
|
}
|
|
|
|
mFreeRuleId++;
|
|
|
|
pNew->mNext = mRuleList;
|
|
mRuleList = pNew;
|
|
}
|
|
|
|
UINT8
|
|
CVfrRulesDB::GetRuleId (
|
|
IN CHAR8 *RuleName
|
|
)
|
|
{
|
|
SVfrRuleNode *pNode;
|
|
|
|
if (RuleName == NULL) {
|
|
return EFI_RULE_ID_INVALID;
|
|
}
|
|
|
|
for (pNode = mRuleList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (strcmp (pNode->mRuleName, RuleName) == 0) {
|
|
return pNode->mRuleId;
|
|
}
|
|
}
|
|
|
|
return EFI_RULE_ID_INVALID;
|
|
}
|
|
|
|
CVfrRulesDB gCVfrRulesDB;
|
|
|
|
EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
|
|
VOID
|
|
)
|
|
{
|
|
mVarStoreId = EFI_VARSTORE_ID_INVALID;
|
|
mInfo.mVarName = EFI_STRING_ID_INVALID;
|
|
mInfo.mVarOffset = EFI_VAROFFSET_INVALID;
|
|
mVarType = EFI_IFR_TYPE_OTHER;
|
|
mVarTotalSize = 0;
|
|
}
|
|
|
|
EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
|
|
IN EFI_VARSTORE_INFO &Info
|
|
)
|
|
{
|
|
mVarStoreId = Info.mVarStoreId;
|
|
mInfo.mVarName = Info.mInfo.mVarName;
|
|
mInfo.mVarOffset = Info.mInfo.mVarOffset;
|
|
mVarType = Info.mVarType;
|
|
mVarTotalSize = Info.mVarTotalSize;
|
|
}
|
|
|
|
BOOLEAN
|
|
EFI_VARSTORE_INFO::operator == (
|
|
IN EFI_VARSTORE_INFO *Info
|
|
)
|
|
{
|
|
if ((mVarStoreId == Info->mVarStoreId) &&
|
|
(mInfo.mVarName == Info->mInfo.mVarName) &&
|
|
(mInfo.mVarOffset == Info->mInfo.mVarOffset) &&
|
|
(mVarType == Info->mVarType) &&
|
|
(mVarTotalSize == Info->mVarTotalSize)) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo;
|
|
|
|
EFI_QUESTION_ID
|
|
CVfrQuestionDB::GetFreeQuestionId (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 Index, Mask, Offset;
|
|
|
|
for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
|
|
if (mFreeQIdBitMap[Index] != 0xFFFFFFFF) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
|
|
if ((mFreeQIdBitMap[Index] & Mask) == 0) {
|
|
mFreeQIdBitMap[Index] |= Mask;
|
|
return (EFI_QUESTION_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset);
|
|
}
|
|
}
|
|
|
|
return EFI_QUESTION_ID_INVALID;
|
|
}
|
|
|
|
BOOLEAN
|
|
CVfrQuestionDB::ChekQuestionIdFree (
|
|
IN EFI_QUESTION_ID QId
|
|
)
|
|
{
|
|
UINT32 Index = (QId / EFI_BITS_PER_UINT32);
|
|
UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
|
|
|
|
return (mFreeQIdBitMap[Index] & (0x80000000 >> Offset)) == 0;
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::MarkQuestionIdUsed (
|
|
IN EFI_QUESTION_ID QId
|
|
)
|
|
{
|
|
UINT32 Index = (QId / EFI_BITS_PER_UINT32);
|
|
UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
|
|
|
|
mFreeQIdBitMap[Index] |= (0x80000000 >> Offset);
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::MarkQuestionIdUnused (
|
|
IN EFI_QUESTION_ID QId
|
|
)
|
|
{
|
|
UINT32 Index = (QId / EFI_BITS_PER_UINT32);
|
|
UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
|
|
|
|
mFreeQIdBitMap[Index] &= ~(0x80000000 >> Offset);
|
|
}
|
|
|
|
SVfrQuestionNode::SVfrQuestionNode (
|
|
IN CHAR8 *Name,
|
|
IN CHAR8 *VarIdStr,
|
|
IN UINT32 BitMask
|
|
)
|
|
{
|
|
mName = NULL;
|
|
mVarIdStr = NULL;
|
|
mQuestionId = EFI_QUESTION_ID_INVALID;
|
|
mBitMask = BitMask;
|
|
mNext = NULL;
|
|
mQtype = QUESTION_NORMAL;
|
|
|
|
if (Name == NULL) {
|
|
mName = new CHAR8[strlen ("$DEFAULT") + 1];
|
|
strcpy (mName, "$DEFAULT");
|
|
} else {
|
|
mName = new CHAR8[strlen (Name) + 1];
|
|
strcpy (mName, Name);
|
|
}
|
|
|
|
if (VarIdStr != NULL) {
|
|
mVarIdStr = new CHAR8[strlen (VarIdStr) + 1];
|
|
strcpy (mVarIdStr, VarIdStr);
|
|
} else {
|
|
mVarIdStr = new CHAR8[strlen ("$") + 1];
|
|
strcpy (mVarIdStr, "$");
|
|
}
|
|
}
|
|
|
|
SVfrQuestionNode::~SVfrQuestionNode (
|
|
VOID
|
|
)
|
|
{
|
|
if (mName != NULL) {
|
|
delete mName;
|
|
}
|
|
|
|
if (mVarIdStr != NULL) {
|
|
delete mVarIdStr;
|
|
}
|
|
}
|
|
|
|
CVfrQuestionDB::CVfrQuestionDB ()
|
|
{
|
|
UINT32 Index;
|
|
|
|
for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
|
|
mFreeQIdBitMap[Index] = 0;
|
|
}
|
|
|
|
// Question ID 0 is reserved.
|
|
mFreeQIdBitMap[0] = 0x80000000;
|
|
mQuestionList = NULL;
|
|
}
|
|
|
|
CVfrQuestionDB::~CVfrQuestionDB ()
|
|
{
|
|
SVfrQuestionNode *pNode;
|
|
|
|
while (mQuestionList != NULL) {
|
|
pNode = mQuestionList;
|
|
mQuestionList = mQuestionList->mNext;
|
|
delete pNode;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Reset to init state
|
|
//
|
|
VOID
|
|
CVfrQuestionDB::ResetInit(
|
|
IN VOID
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
SVfrQuestionNode *pNode;
|
|
|
|
while (mQuestionList != NULL) {
|
|
pNode = mQuestionList;
|
|
mQuestionList = mQuestionList->mNext;
|
|
delete pNode;
|
|
}
|
|
|
|
for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
|
|
mFreeQIdBitMap[Index] = 0;
|
|
}
|
|
|
|
// Question ID 0 is reserved.
|
|
mFreeQIdBitMap[0] = 0x80000000;
|
|
mQuestionList = NULL;
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::PrintAllQuestion (
|
|
VOID
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode = NULL;
|
|
|
|
for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
|
|
printf ("Question VarId is %s and QuesitonId is 0x%x\n", pNode->mVarIdStr, pNode->mQuestionId);
|
|
}
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrQuestionDB::RegisterQuestion (
|
|
IN CHAR8 *Name,
|
|
IN CHAR8 *VarIdStr,
|
|
IN OUT EFI_QUESTION_ID &QuestionId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode = NULL;
|
|
|
|
if ((Name != NULL) && (FindQuestion(Name) == VFR_RETURN_SUCCESS)) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
|
|
if ((pNode = new SVfrQuestionNode (Name, VarIdStr)) == NULL) {
|
|
return VFR_RETURN_OUT_FOR_RESOURCES;
|
|
}
|
|
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
//
|
|
// For Framework Vfr, don't check question ID conflict.
|
|
//
|
|
if (!VfrCompatibleMode && ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
delete pNode;
|
|
return VFR_RETURN_QUESTIONID_REDEFINED;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
pNode->mQuestionId = QuestionId;
|
|
|
|
pNode->mNext = mQuestionList;
|
|
mQuestionList = pNode;
|
|
|
|
gCFormPkg.DoPendingAssign (VarIdStr, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::RegisterOldDateQuestion (
|
|
IN CHAR8 *YearVarId,
|
|
IN CHAR8 *MonthVarId,
|
|
IN CHAR8 *DayVarId,
|
|
IN OUT EFI_QUESTION_ID &QuestionId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode[3] = {NULL, };
|
|
UINT32 Index;
|
|
|
|
if ((YearVarId == NULL) || (MonthVarId == NULL) || (DayVarId == NULL)) {
|
|
return;
|
|
}
|
|
|
|
if ((pNode[0] = new SVfrQuestionNode (NULL, YearVarId, DATE_YEAR_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[1] = new SVfrQuestionNode (NULL, MonthVarId, DATE_MONTH_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[2] = new SVfrQuestionNode (NULL, DayVarId, DATE_DAY_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
if (ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
goto Err;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
|
|
pNode[0]->mQuestionId = QuestionId;
|
|
pNode[1]->mQuestionId = QuestionId;
|
|
pNode[2]->mQuestionId = QuestionId;
|
|
pNode[0]->mQtype = QUESTION_DATE;
|
|
pNode[1]->mQtype = QUESTION_DATE;
|
|
pNode[2]->mQtype = QUESTION_DATE;
|
|
pNode[0]->mNext = pNode[1];
|
|
pNode[1]->mNext = pNode[2];
|
|
pNode[2]->mNext = mQuestionList;
|
|
mQuestionList = pNode[0];
|
|
|
|
gCFormPkg.DoPendingAssign (YearVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (MonthVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (DayVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
|
|
return;
|
|
|
|
Err:
|
|
for (Index = 0; Index < 3; Index++) {
|
|
if (pNode[Index] != NULL) {
|
|
delete pNode[Index];
|
|
}
|
|
}
|
|
QuestionId = EFI_QUESTION_ID_INVALID;
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::RegisterNewDateQuestion (
|
|
IN CHAR8 *Name,
|
|
IN CHAR8 *BaseVarId,
|
|
IN OUT EFI_QUESTION_ID &QuestionId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode[3] = {NULL, };
|
|
UINT32 Len;
|
|
CHAR8 *VarIdStr[3] = {NULL, };
|
|
CHAR8 Index;
|
|
|
|
if (BaseVarId == NULL && Name == NULL) {
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
if (ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
goto Err;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (BaseVarId != NULL) {
|
|
Len = strlen (BaseVarId);
|
|
|
|
VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1];
|
|
if (VarIdStr[0] != NULL) {
|
|
strcpy (VarIdStr[0], BaseVarId);
|
|
strcat (VarIdStr[0], ".Year");
|
|
}
|
|
VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1];
|
|
if (VarIdStr[1] != NULL) {
|
|
strcpy (VarIdStr[1], BaseVarId);
|
|
strcat (VarIdStr[1], ".Month");
|
|
}
|
|
VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1];
|
|
if (VarIdStr[2] != NULL) {
|
|
strcpy (VarIdStr[2], BaseVarId);
|
|
strcat (VarIdStr[2], ".Day");
|
|
}
|
|
} else {
|
|
Len = strlen (Name);
|
|
|
|
VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1];
|
|
if (VarIdStr[0] != NULL) {
|
|
strcpy (VarIdStr[0], Name);
|
|
strcat (VarIdStr[0], ".Year");
|
|
}
|
|
VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1];
|
|
if (VarIdStr[1] != NULL) {
|
|
strcpy (VarIdStr[1], Name);
|
|
strcat (VarIdStr[1], ".Month");
|
|
}
|
|
VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1];
|
|
if (VarIdStr[2] != NULL) {
|
|
strcpy (VarIdStr[2], Name);
|
|
strcat (VarIdStr[2], ".Day");
|
|
}
|
|
}
|
|
|
|
if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], DATE_YEAR_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], DATE_MONTH_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], DATE_DAY_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
if (ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
goto Err;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
|
|
pNode[0]->mQuestionId = QuestionId;
|
|
pNode[1]->mQuestionId = QuestionId;
|
|
pNode[2]->mQuestionId = QuestionId;
|
|
pNode[0]->mQtype = QUESTION_DATE;
|
|
pNode[1]->mQtype = QUESTION_DATE;
|
|
pNode[2]->mQtype = QUESTION_DATE;
|
|
pNode[0]->mNext = pNode[1];
|
|
pNode[1]->mNext = pNode[2];
|
|
pNode[2]->mNext = mQuestionList;
|
|
mQuestionList = pNode[0];
|
|
|
|
for (Index = 0; Index < 3; Index++) {
|
|
if (VarIdStr[Index] != NULL) {
|
|
delete VarIdStr[Index];
|
|
}
|
|
}
|
|
|
|
gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
|
|
return;
|
|
|
|
Err:
|
|
for (Index = 0; Index < 3; Index++) {
|
|
if (pNode[Index] != NULL) {
|
|
delete pNode[Index];
|
|
}
|
|
|
|
if (VarIdStr[Index] != NULL) {
|
|
delete VarIdStr[Index];
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::RegisterOldTimeQuestion (
|
|
IN CHAR8 *HourVarId,
|
|
IN CHAR8 *MinuteVarId,
|
|
IN CHAR8 *SecondVarId,
|
|
IN OUT EFI_QUESTION_ID &QuestionId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode[3] = {NULL, };
|
|
UINT32 Index;
|
|
|
|
if ((HourVarId == NULL) || (MinuteVarId == NULL) || (SecondVarId == NULL)) {
|
|
return;
|
|
}
|
|
|
|
if ((pNode[0] = new SVfrQuestionNode (NULL, HourVarId, TIME_HOUR_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[1] = new SVfrQuestionNode (NULL, MinuteVarId, TIME_MINUTE_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[2] = new SVfrQuestionNode (NULL, SecondVarId, TIME_SECOND_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
if (ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
goto Err;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
|
|
pNode[0]->mQuestionId = QuestionId;
|
|
pNode[1]->mQuestionId = QuestionId;
|
|
pNode[2]->mQuestionId = QuestionId;
|
|
pNode[0]->mQtype = QUESTION_TIME;
|
|
pNode[1]->mQtype = QUESTION_TIME;
|
|
pNode[2]->mQtype = QUESTION_TIME;
|
|
pNode[0]->mNext = pNode[1];
|
|
pNode[1]->mNext = pNode[2];
|
|
pNode[2]->mNext = mQuestionList;
|
|
mQuestionList = pNode[0];
|
|
|
|
gCFormPkg.DoPendingAssign (HourVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (MinuteVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (SecondVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
|
|
return;
|
|
|
|
Err:
|
|
for (Index = 0; Index < 3; Index++) {
|
|
if (pNode[Index] != NULL) {
|
|
delete pNode[Index];
|
|
}
|
|
}
|
|
QuestionId = EFI_QUESTION_ID_INVALID;
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::RegisterNewTimeQuestion (
|
|
IN CHAR8 *Name,
|
|
IN CHAR8 *BaseVarId,
|
|
IN OUT EFI_QUESTION_ID &QuestionId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode[3] = {NULL, };
|
|
UINT32 Len;
|
|
CHAR8 *VarIdStr[3] = {NULL, };
|
|
CHAR8 Index;
|
|
|
|
if (BaseVarId == NULL && Name == NULL) {
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
if (ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
goto Err;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (BaseVarId != NULL) {
|
|
Len = strlen (BaseVarId);
|
|
|
|
VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1];
|
|
if (VarIdStr[0] != NULL) {
|
|
strcpy (VarIdStr[0], BaseVarId);
|
|
strcat (VarIdStr[0], ".Hour");
|
|
}
|
|
VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1];
|
|
if (VarIdStr[1] != NULL) {
|
|
strcpy (VarIdStr[1], BaseVarId);
|
|
strcat (VarIdStr[1], ".Minute");
|
|
}
|
|
VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1];
|
|
if (VarIdStr[2] != NULL) {
|
|
strcpy (VarIdStr[2], BaseVarId);
|
|
strcat (VarIdStr[2], ".Second");
|
|
}
|
|
} else {
|
|
Len = strlen (Name);
|
|
|
|
VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1];
|
|
if (VarIdStr[0] != NULL) {
|
|
strcpy (VarIdStr[0], Name);
|
|
strcat (VarIdStr[0], ".Hour");
|
|
}
|
|
VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1];
|
|
if (VarIdStr[1] != NULL) {
|
|
strcpy (VarIdStr[1], Name);
|
|
strcat (VarIdStr[1], ".Minute");
|
|
}
|
|
VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1];
|
|
if (VarIdStr[2] != NULL) {
|
|
strcpy (VarIdStr[2], Name);
|
|
strcat (VarIdStr[2], ".Second");
|
|
}
|
|
}
|
|
|
|
if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], TIME_HOUR_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], TIME_MINUTE_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], TIME_SECOND_BITMASK)) == NULL) {
|
|
goto Err;
|
|
}
|
|
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
if (ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
goto Err;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
|
|
pNode[0]->mQuestionId = QuestionId;
|
|
pNode[1]->mQuestionId = QuestionId;
|
|
pNode[2]->mQuestionId = QuestionId;
|
|
pNode[0]->mQtype = QUESTION_TIME;
|
|
pNode[1]->mQtype = QUESTION_TIME;
|
|
pNode[2]->mQtype = QUESTION_TIME;
|
|
pNode[0]->mNext = pNode[1];
|
|
pNode[1]->mNext = pNode[2];
|
|
pNode[2]->mNext = mQuestionList;
|
|
mQuestionList = pNode[0];
|
|
|
|
for (Index = 0; Index < 3; Index++) {
|
|
if (VarIdStr[Index] != NULL) {
|
|
delete VarIdStr[Index];
|
|
}
|
|
}
|
|
|
|
gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
|
|
return;
|
|
|
|
Err:
|
|
for (Index = 0; Index < 3; Index++) {
|
|
if (pNode[Index] != NULL) {
|
|
delete pNode[Index];
|
|
}
|
|
|
|
if (VarIdStr[Index] != NULL) {
|
|
delete VarIdStr[Index];
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::RegisterRefQuestion (
|
|
IN CHAR8 *Name,
|
|
IN CHAR8 *BaseVarId,
|
|
IN OUT EFI_QUESTION_ID &QuestionId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode[4] = {NULL, };
|
|
UINT32 Len;
|
|
CHAR8 *VarIdStr[4] = {NULL, };
|
|
CHAR8 Index;
|
|
|
|
if (BaseVarId == NULL && Name == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (BaseVarId != NULL) {
|
|
Len = strlen (BaseVarId);
|
|
|
|
VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
|
|
if (VarIdStr[0] != NULL) {
|
|
strcpy (VarIdStr[0], BaseVarId);
|
|
strcat (VarIdStr[0], ".QuestionId");
|
|
}
|
|
VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
|
|
if (VarIdStr[1] != NULL) {
|
|
strcpy (VarIdStr[1], BaseVarId);
|
|
strcat (VarIdStr[1], ".FormId");
|
|
}
|
|
VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
|
|
if (VarIdStr[2] != NULL) {
|
|
strcpy (VarIdStr[2], BaseVarId);
|
|
strcat (VarIdStr[2], ".FormSetGuid");
|
|
}
|
|
VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
|
|
if (VarIdStr[3] != NULL) {
|
|
strcpy (VarIdStr[3], BaseVarId);
|
|
strcat (VarIdStr[3], ".DevicePath");
|
|
}
|
|
} else {
|
|
Len = strlen (Name);
|
|
|
|
VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
|
|
if (VarIdStr[0] != NULL) {
|
|
strcpy (VarIdStr[0], Name);
|
|
strcat (VarIdStr[0], ".QuestionId");
|
|
}
|
|
VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
|
|
if (VarIdStr[1] != NULL) {
|
|
strcpy (VarIdStr[1], Name);
|
|
strcat (VarIdStr[1], ".FormId");
|
|
}
|
|
VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
|
|
if (VarIdStr[2] != NULL) {
|
|
strcpy (VarIdStr[2], Name);
|
|
strcat (VarIdStr[2], ".FormSetGuid");
|
|
}
|
|
VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
|
|
if (VarIdStr[3] != NULL) {
|
|
strcpy (VarIdStr[3], Name);
|
|
strcat (VarIdStr[3], ".DevicePath");
|
|
}
|
|
}
|
|
|
|
if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0])) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1])) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2])) == NULL) {
|
|
goto Err;
|
|
}
|
|
if ((pNode[3] = new SVfrQuestionNode (Name, VarIdStr[3])) == NULL) {
|
|
goto Err;
|
|
}
|
|
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
QuestionId = GetFreeQuestionId ();
|
|
} else {
|
|
if (ChekQuestionIdFree (QuestionId) == FALSE) {
|
|
goto Err;
|
|
}
|
|
MarkQuestionIdUsed (QuestionId);
|
|
}
|
|
|
|
pNode[0]->mQuestionId = QuestionId;
|
|
pNode[1]->mQuestionId = QuestionId;
|
|
pNode[2]->mQuestionId = QuestionId;
|
|
pNode[3]->mQuestionId = QuestionId;
|
|
pNode[0]->mQtype = QUESTION_REF;
|
|
pNode[1]->mQtype = QUESTION_REF;
|
|
pNode[2]->mQtype = QUESTION_REF;
|
|
pNode[3]->mQtype = QUESTION_REF;
|
|
pNode[0]->mNext = pNode[1];
|
|
pNode[1]->mNext = pNode[2];
|
|
pNode[2]->mNext = pNode[3];
|
|
pNode[3]->mNext = mQuestionList;
|
|
mQuestionList = pNode[0];
|
|
|
|
gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
gCFormPkg.DoPendingAssign (VarIdStr[3], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
|
|
|
|
return;
|
|
|
|
Err:
|
|
for (Index = 0; Index < 4; Index++) {
|
|
if (pNode[Index] != NULL) {
|
|
delete pNode[Index];
|
|
}
|
|
|
|
if (VarIdStr[Index] != NULL) {
|
|
delete VarIdStr[Index];
|
|
}
|
|
}
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrQuestionDB::UpdateQuestionId (
|
|
IN EFI_QUESTION_ID QId,
|
|
IN EFI_QUESTION_ID NewQId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode = NULL;
|
|
|
|
if (QId == NewQId) {
|
|
// don't update
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// For Framework Vfr, don't check question ID conflict.
|
|
//
|
|
if (!VfrCompatibleMode && ChekQuestionIdFree (NewQId) == FALSE) {
|
|
return VFR_RETURN_REDEFINED;
|
|
}
|
|
|
|
for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mQuestionId == QId) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pNode == NULL) {
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
MarkQuestionIdUnused (QId);
|
|
pNode->mQuestionId = NewQId;
|
|
MarkQuestionIdUsed (NewQId);
|
|
|
|
gCFormPkg.DoPendingAssign (pNode->mVarIdStr, (VOID *)&NewQId, sizeof(EFI_QUESTION_ID));
|
|
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
CVfrQuestionDB::GetQuestionId (
|
|
IN CHAR8 *Name,
|
|
IN CHAR8 *VarIdStr,
|
|
OUT EFI_QUESTION_ID &QuestionId,
|
|
OUT UINT32 &BitMask,
|
|
OUT EFI_QUESION_TYPE *QType
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode;
|
|
|
|
QuestionId = EFI_QUESTION_ID_INVALID;
|
|
BitMask = 0x00000000;
|
|
if (QType != NULL) {
|
|
*QType = QUESTION_NORMAL;
|
|
}
|
|
|
|
if ((Name == NULL) && (VarIdStr == NULL)) {
|
|
return ;
|
|
}
|
|
|
|
for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (Name != NULL) {
|
|
if (strcmp (pNode->mName, Name) != 0) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (VarIdStr != NULL) {
|
|
if (strcmp (pNode->mVarIdStr, VarIdStr) != 0) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
QuestionId = pNode->mQuestionId;
|
|
BitMask = pNode->mBitMask;
|
|
if (QType != NULL) {
|
|
*QType = pNode->mQtype;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrQuestionDB::FindQuestion (
|
|
IN EFI_QUESTION_ID QuestionId
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode;
|
|
|
|
if (QuestionId == EFI_QUESTION_ID_INVALID) {
|
|
return VFR_RETURN_INVALID_PARAMETER;
|
|
}
|
|
|
|
for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (pNode->mQuestionId == QuestionId) {
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
EFI_VFR_RETURN_CODE
|
|
CVfrQuestionDB::FindQuestion (
|
|
IN CHAR8 *Name
|
|
)
|
|
{
|
|
SVfrQuestionNode *pNode;
|
|
|
|
if (Name == NULL) {
|
|
return VFR_RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
|
|
if (strcmp (pNode->mName, Name) == 0) {
|
|
return VFR_RETURN_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return VFR_RETURN_UNDEFINED;
|
|
}
|
|
|
|
CVfrStringDB::CVfrStringDB ()
|
|
{
|
|
mStringFileName = NULL;
|
|
}
|
|
|
|
CVfrStringDB::~CVfrStringDB ()
|
|
{
|
|
if (mStringFileName != NULL) {
|
|
delete mStringFileName;
|
|
}
|
|
mStringFileName = NULL;
|
|
}
|
|
|
|
|
|
VOID
|
|
CVfrStringDB::SetStringFileName(IN CHAR8 *StringFileName)
|
|
{
|
|
UINT32 FileLen = 0;
|
|
|
|
if (StringFileName == NULL) {
|
|
return;
|
|
}
|
|
|
|
FileLen = strlen (StringFileName) + 1;
|
|
mStringFileName = new CHAR8[FileLen];
|
|
if (mStringFileName == NULL) {
|
|
return;
|
|
}
|
|
|
|
strcpy (mStringFileName, StringFileName);
|
|
mStringFileName[FileLen - 1] = '\0';
|
|
}
|
|
|
|
|
|
/**
|
|
Returns TRUE or FALSE whether SupportedLanguages contains the best matching language
|
|
from a set of supported languages.
|
|
|
|
@param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that
|
|
contains a set of language codes.
|
|
@param[in] Language A variable that contains pointers to Null-terminated
|
|
ASCII strings that contain one language codes.
|
|
|
|
@retval FALSE The best matching language could not be found in SupportedLanguages.
|
|
@retval TRUE The best matching language could be found in SupportedLanguages.
|
|
|
|
**/
|
|
BOOLEAN
|
|
CVfrStringDB::GetBestLanguage (
|
|
IN CONST CHAR8 *SupportedLanguages,
|
|
IN CHAR8 *Language
|
|
)
|
|
{
|
|
UINTN CompareLength;
|
|
UINTN LanguageLength;
|
|
CONST CHAR8 *Supported;
|
|
|
|
if (SupportedLanguages == NULL || Language == NULL){
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Determine the length of the first RFC 4646 language code in Language
|
|
//
|
|
for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
|
|
|
|
//
|
|
// Trim back the length of Language used until it is empty
|
|
//
|
|
while (LanguageLength > 0) {
|
|
//
|
|
// Loop through all language codes in SupportedLanguages
|
|
//
|
|
for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
|
|
//
|
|
// Skip ';' characters in Supported
|
|
//
|
|
for (; *Supported != '\0' && *Supported == ';'; Supported++);
|
|
//
|
|
// Determine the length of the next language code in Supported
|
|
//
|
|
for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
|
|
//
|
|
// If Language is longer than the Supported, then skip to the next language
|
|
//
|
|
if (LanguageLength > CompareLength) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// See if the first LanguageLength characters in Supported match Language
|
|
//
|
|
if (strncmp (Supported, Language, LanguageLength) == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Trim Language from the right to the next '-' character
|
|
//
|
|
for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
|
|
}
|
|
|
|
//
|
|
// No matches were found
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
CHAR8 *
|
|
CVfrStringDB::GetVarStoreNameFormStringId (
|
|
IN EFI_STRING_ID StringId
|
|
)
|
|
{
|
|
FILE *pInFile = NULL;
|
|
UINT32 NameOffset;
|
|
UINT32 Length;
|
|
UINT8 *StringPtr;
|
|
CHAR8 *StringName;
|
|
CHAR16 *UnicodeString;
|
|
CHAR8 *VarStoreName = NULL;
|
|
CHAR8 *DestTmp;
|
|
UINT8 *Current;
|
|
EFI_STATUS Status;
|
|
CHAR8 LineBuf[EFI_IFR_MAX_LENGTH];
|
|
UINT8 BlockType;
|
|
EFI_HII_STRING_PACKAGE_HDR *PkgHeader;
|
|
|
|
if (mStringFileName == '\0' ) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((pInFile = fopen (mStringFileName, "rb")) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Get file length.
|
|
//
|
|
fseek (pInFile, 0, SEEK_END);
|
|
Length = ftell (pInFile);
|
|
fseek (pInFile, 0, SEEK_SET);
|
|
|
|
//
|
|
// Get file data.
|
|
//
|
|
StringPtr = new UINT8[Length];
|
|
if (StringPtr == NULL) {
|
|
fclose (pInFile);
|
|
return NULL;
|
|
}
|
|
fread ((char *)StringPtr, sizeof (UINT8), Length, pInFile);
|
|
fclose (pInFile);
|
|
|
|
PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
|
|
//
|
|
// Check the String package.
|
|
//
|
|
if (PkgHeader->Header.Type != EFI_HII_PACKAGE_STRINGS) {
|
|
delete StringPtr;
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Search the language, get best language base on RFC 4647 matching algorithm.
|
|
//
|
|
Current = StringPtr;
|
|
while (!GetBestLanguage ("en", PkgHeader->Language)) {
|
|
Current += PkgHeader->Header.Length;
|
|
PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current;
|
|
//
|
|
// If can't find string package base on language, just return the first string package.
|
|
//
|
|
if (Current - StringPtr >= Length) {
|
|
Current = StringPtr;
|
|
PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Current += PkgHeader->HdrSize;
|
|
//
|
|
// Find the string block according the stringId.
|
|
//
|
|
Status = FindStringBlock(Current, StringId, &NameOffset, &BlockType);
|
|
if (Status != EFI_SUCCESS) {
|
|
delete StringPtr;
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Get varstore name according the string type.
|
|
//
|
|
switch (BlockType) {
|
|
case EFI_HII_SIBT_STRING_SCSU:
|
|
case EFI_HII_SIBT_STRING_SCSU_FONT:
|
|
case EFI_HII_SIBT_STRINGS_SCSU:
|
|
case EFI_HII_SIBT_STRINGS_SCSU_FONT:
|
|
StringName = (CHAR8*)(Current + NameOffset);
|
|
VarStoreName = new CHAR8[strlen(StringName) + 1];
|
|
strcpy (VarStoreName, StringName);
|
|
break;
|
|
case EFI_HII_SIBT_STRING_UCS2:
|
|
case EFI_HII_SIBT_STRING_UCS2_FONT:
|
|
case EFI_HII_SIBT_STRINGS_UCS2:
|
|
case EFI_HII_SIBT_STRINGS_UCS2_FONT:
|
|
UnicodeString = (CHAR16*)(Current + NameOffset);
|
|
Length = GetUnicodeStringTextSize ((UINT8*)UnicodeString) ;
|
|
DestTmp = new CHAR8[Length / 2 + 1];
|
|
VarStoreName = DestTmp;
|
|
while (*UnicodeString != '\0') {
|
|
*(DestTmp++) = (CHAR8) *(UnicodeString++);
|
|
}
|
|
*DestTmp = '\0';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
delete StringPtr;
|
|
|
|
return VarStoreName;
|
|
}
|
|
|
|
EFI_STATUS
|
|
CVfrStringDB::FindStringBlock (
|
|
IN UINT8 *StringData,
|
|
IN EFI_STRING_ID StringId,
|
|
OUT UINT32 *StringTextOffset,
|
|
OUT UINT8 *BlockType
|
|
)
|
|
{
|
|
UINT8 *BlockHdr;
|
|
EFI_STRING_ID CurrentStringId;
|
|
UINT32 BlockSize;
|
|
UINT32 Index;
|
|
UINT8 *StringTextPtr;
|
|
UINT32 Offset;
|
|
UINT16 StringCount;
|
|
UINT16 SkipCount;
|
|
UINT8 Length8;
|
|
EFI_HII_SIBT_EXT2_BLOCK Ext2;
|
|
UINT32 Length32;
|
|
UINT32 StringSize;
|
|
|
|
CurrentStringId = 1;
|
|
|
|
//
|
|
// Parse the string blocks to get the string text and font.
|
|
//
|
|
BlockHdr = StringData;
|
|
BlockSize = 0;
|
|
Offset = 0;
|
|
while (*BlockHdr != EFI_HII_SIBT_END) {
|
|
switch (*BlockHdr) {
|
|
case EFI_HII_SIBT_STRING_SCSU:
|
|
Offset = sizeof (EFI_HII_STRING_BLOCK);
|
|
StringTextPtr = BlockHdr + Offset;
|
|
BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
|
|
CurrentStringId++;
|
|
break;
|
|
|
|
case EFI_HII_SIBT_STRING_SCSU_FONT:
|
|
Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
|
|
StringTextPtr = BlockHdr + Offset;
|
|
BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
|
|
CurrentStringId++;
|
|
break;
|
|
|
|
case EFI_HII_SIBT_STRINGS_SCSU:
|
|
memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
|
|
StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);
|
|
BlockSize += StringTextPtr - BlockHdr;
|
|
|
|
for (Index = 0; Index < StringCount; Index++) {
|
|
BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
|
|
if (CurrentStringId == StringId) {
|
|
*BlockType = *BlockHdr;
|
|
*StringTextOffset = StringTextPtr - StringData;
|
|
return EFI_SUCCESS;
|
|
}
|
|
StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
|
|
CurrentStringId++;
|
|
}
|
|
break;
|
|
|
|
case EFI_HII_SIBT_STRINGS_SCSU_FONT:
|
|
memcpy (
|
|
&StringCount,
|
|
BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
|
|
sizeof (UINT16)
|
|
);
|
|
StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);
|
|
BlockSize += StringTextPtr - BlockHdr;
|
|
|
|
for (Index = 0; Index < StringCount; Index++) {
|
|
BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
|
|
if (CurrentStringId == StringId) {
|
|
*BlockType = *BlockHdr;
|
|
*StringTextOffset = StringTextPtr - StringData;
|
|
return EFI_SUCCESS;
|
|
}
|
|
StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
|
|
CurrentStringId++;
|
|
}
|
|
break;
|
|
|
|
case EFI_HII_SIBT_STRING_UCS2:
|
|
Offset = sizeof (EFI_HII_STRING_BLOCK);
|
|
StringTextPtr = BlockHdr + Offset;
|
|
//
|
|
// Use StringSize to store the size of the specified string, including the NULL
|
|
// terminator.
|
|
//
|
|
StringSize = GetUnicodeStringTextSize (StringTextPtr);
|
|
BlockSize += Offset + StringSize;
|
|
CurrentStringId++;
|
|
break;
|
|
|
|
case EFI_HII_SIBT_STRING_UCS2_FONT:
|
|
Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
|
|
StringTextPtr = BlockHdr + Offset;
|
|
//
|
|
// Use StrSize to store the size of the specified string, including the NULL
|
|
// terminator.
|
|
//
|
|
StringSize = GetUnicodeStringTextSize (StringTextPtr);
|
|
BlockSize += Offset + StringSize;
|
|
CurrentStringId++;
|
|
break;
|
|
|
|
case EFI_HII_SIBT_STRINGS_UCS2:
|
|
Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
|
|
StringTextPtr = BlockHdr + Offset;
|
|
BlockSize += Offset;
|
|
memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
|
|
for (Index = 0; Index < StringCount; Index++) {
|
|
StringSize = GetUnicodeStringTextSize (StringTextPtr);
|
|
BlockSize += StringSize;
|
|
if (CurrentStringId == StringId) {
|
|
*BlockType = *BlockHdr;
|
|
*StringTextOffset = StringTextPtr - StringData;
|
|
return EFI_SUCCESS;
|
|
}
|
|
StringTextPtr = StringTextPtr + StringSize;
|
|
CurrentStringId++;
|
|
}
|
|
break;
|
|
|
|
case EFI_HII_SIBT_STRINGS_UCS2_FONT:
|
|
Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
|
|
StringTextPtr = BlockHdr + Offset;
|
|
BlockSize += Offset;
|
|
memcpy (
|
|
&StringCount,
|
|
BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
|
|
sizeof (UINT16)
|
|
);
|
|
for (Index = 0; Index < StringCount; Index++) {
|
|
StringSize = GetUnicodeStringTextSize (StringTextPtr);
|
|
BlockSize += StringSize;
|
|
if (CurrentStringId == StringId) {
|
|
*BlockType = *BlockHdr;
|
|
*StringTextOffset = StringTextPtr - StringData;
|
|
return EFI_SUCCESS;
|
|
}
|
|
StringTextPtr = StringTextPtr + StringSize;
|
|
CurrentStringId++;
|
|
}
|
|
break;
|
|
|
|
case EFI_HII_SIBT_DUPLICATE:
|
|
if (CurrentStringId == StringId) {
|
|
//
|
|
// Incoming StringId is an id of a duplicate string block.
|
|
// Update the StringId to be the previous string block.
|
|
// Go back to the header of string block to search.
|
|
//
|
|
memcpy (
|
|
&StringId,
|
|
BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
|
|
sizeof (EFI_STRING_ID)
|
|
);
|
|
CurrentStringId = 1;
|
|
BlockSize = 0;
|
|
} else {
|
|
BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
|
|
CurrentStringId++;
|
|
}
|
|
break;
|
|
|
|
case EFI_HII_SIBT_SKIP1:
|
|
SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
|
|
CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
|
|
BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
|
|
break;
|
|
|
|
case EFI_HII_SIBT_SKIP2:
|
|
memcpy (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
|
|
CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
|
|
BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
|
|
break;
|
|
|
|
case EFI_HII_SIBT_EXT1:
|
|
memcpy (
|
|
&Length8,
|
|
BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
|
|
sizeof (UINT8)
|
|
);
|
|
BlockSize += Length8;
|
|
break;
|
|
|
|
case EFI_HII_SIBT_EXT2:
|
|
memcpy (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
|
|
BlockSize += Ext2.Length;
|
|
break;
|
|
|
|
case EFI_HII_SIBT_EXT4:
|
|
memcpy (
|
|
&Length32,
|
|
BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
|
|
sizeof (UINT32)
|
|
);
|
|
|
|
BlockSize += Length32;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) {
|
|
*StringTextOffset = BlockHdr - StringData + Offset;
|
|
*BlockType = *BlockHdr;
|
|
|
|
if (StringId == CurrentStringId - 1) {
|
|
//
|
|
// if only one skip item, return EFI_NOT_FOUND.
|
|
//
|
|
if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) {
|
|
return EFI_NOT_FOUND;
|
|
} else {
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
if (StringId < CurrentStringId - 1) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
BlockHdr = StringData + BlockSize;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
UINT32
|
|
CVfrStringDB::GetUnicodeStringTextSize (
|
|
IN UINT8 *StringSrc
|
|
)
|
|
{
|
|
UINT32 StringSize;
|
|
CHAR16 *StringPtr;
|
|
|
|
StringSize = sizeof (CHAR16);
|
|
StringPtr = (UINT16*)StringSrc;
|
|
while (*StringPtr++ != L'\0') {
|
|
StringSize += sizeof (CHAR16);
|
|
}
|
|
|
|
return StringSize;
|
|
}
|
|
|
|
BOOLEAN VfrCompatibleMode = FALSE;
|
|
|
|
CVfrVarDataTypeDB gCVfrVarDataTypeDB;
|
|
|
|
|