audk/BaseTools/Source/C/FCE/IfrParse.c
Shenglei Zhang 3c59d94637 BaseTools/FCE: Add a tool FCE
FCE is a tool to retrieve and change HII configuration data in
Firmware Device(*.fd) files.
https://bugzilla.tianocore.org/show_bug.cgi?id=1848

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
2019-07-04 11:34:56 +08:00

4837 lines
152 KiB
C

/** @file
Parser for IFR binary encoding.
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "IfrParse.h"
#ifndef EDKII_IFR_BIT_VARSTORE_GUID
#define EDKII_IFR_BIT_VARSTORE_GUID \
{0x82DDD68B, 0x9163, 0x4187, {0x9B, 0x27, 0x20, 0xA8, 0xFD, 0x60 ,0xA7, 0x1D}}
#endif
#ifndef EDKII_IFR_NUMERIC_SIZE_BIT
#define EDKII_IFR_NUMERIC_SIZE_BIT 0x3F
#endif
UINT16 mStatementIndex;
UINT16 mExpressionOpCodeIndex;
BOOLEAN mInScopeSubtitle;
BOOLEAN mInScopeSuppress;
BOOLEAN mInScopeGrayOut;
BOOLEAN mInScopeDisable;
FORM_EXPRESSION *mSuppressExpression;
FORM_EXPRESSION *mGrayOutExpression;
FORM_EXPRESSION *mDisableExpression;
extern MULTI_PLATFORM_PARAMETERS mMultiPlatformParam;
extern LIST_ENTRY mVarListEntry;
extern LIST_ENTRY mFormSetListEntry;
extern UINT32 mFormSetOrderParse;
#define FORM_SET_GUID_PREFIX "Form Set GUID: "
#define EFI_GUID_FORMAT "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
UINT32 mMaxCount = 0x100000;
UINT32 mCount = 0;
CHAR8 *mStringBuffer = NULL;
static EFI_GUID gEdkiiIfrBitVarGuid = EDKII_IFR_BIT_VARSTORE_GUID;
/**
Produces a Null-terminated ASCII string in mStringBuffer based on a Null-terminated
ASCII format string and variable argument list.
@param FormatString A null-terminated ASCII format string.
@param ... The variable argument list whose contents are accessed based on the
format string specified by FormatString.
**/
VOID
StringPrint (
CHAR8 *FormatString,
...
)
{
va_list Marker;
INT32 Count;
va_start (Marker, FormatString);
Count = vsprintf (mStringBuffer + mCount, FormatString, Marker);
mCount = mCount + Count;
va_end (Marker);
if (mCount + 0x400 > mMaxCount) {
mStringBuffer[mCount] = '\0';
fwrite (mStringBuffer, sizeof (CHAR8), mCount, stdout);
mCount = 0;
}
}
/**
Print the information of questions.
@param FormSet The pointer to the formset.
@param FormSet The pointer to the form.
@param Question The pointer to the question.
@param PrintOrNot Decide whether print or not.
@return NULL.
**/
static
VOID
PrintQuestion (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form,
IN FORM_BROWSER_STATEMENT *Question,
IN BOOLEAN PrintOrNot
);
/**
Writes a Unicode string specified by iStringToken and iLanguage to the script file (converted to ASCII).
@param Package A pointer to the Unicode string.
@return NULL
**/
static
VOID
LogUnicodeString (
IN CHAR16 *pcString
)
{
UINTN Index;
if (pcString == NULL) {
return;
}
//
// replace the 0x0D to 0x20, because if the pcString has 0D 0A, then after print it,
// different editor may have different format
//
for (Index = 0; pcString[Index] != 0; Index++) {
if (pcString[Index] == 0x0D) {
pcString[Index] = 0x20;
}
StringPrint("%c", pcString[Index] & 0x00FF);
}
}
/**
Writes a UQIL Unicode string specified by iStringToken to the script file as an array of 16-bit integers in ASCII.
@param Package A pointer to the Unicode string.
@return NULL
**/
static
VOID
LogUqi (
IN CHAR16 *pcString
)
{
UINT16 Index;
//
// Find the UNICODE string length (in CHAR16)
//
for (Index = 0; pcString[Index] != 0; Index++);
//
// Write each word as a hex integer
//
for (Index = 0; pcString[Index] != 0; Index++) {
StringPrint("%04X ", pcString[Index]);
}
}
/**
Get the question value with bit field from the buffer.
@param Question The question refer to bit field.
@param Buffer The buffer which the question value get from.
@param Value Retun the value.
**/
VOID
GetBitsQuestionValue(
IN FORM_BROWSER_STATEMENT *Question,
IN UINT8 *Buffer,
OUT UINT32 *Value
)
{
UINT32 PreBits;
UINT32 Mask;
PreBits = Question->BitVarOffset - Question->VarStoreInfo.VarOffset * 8;
Mask = (1<< Question->BitStorageWidth) -1;
*Value = *(UINT32*)Buffer;
(*Value) >>= PreBits;
(*Value) &= Mask;
}
/**
Set the question value with bit field to the buffer.
@param Question The question refer to bit field.
@param Buffer The buffer which the question value set to.
@param Value The value need to set.
**/
VOID
SetBitsQuestionValue (
IN FORM_BROWSER_STATEMENT *Question,
IN OUT UINT8 *Buffer,
IN UINT32 Value
)
{
UINT32 PreBits;
UINT32 Mask;
UINT32 TmpValue;
PreBits = Question->BitVarOffset - Question->VarStoreInfo.VarOffset * 8;
Value <<= PreBits;
Mask = (1<< Question->BitStorageWidth) -1;
Mask <<= PreBits;
TmpValue = *(UINT32*)(Buffer);
TmpValue = (TmpValue & (~Mask)) | Value;
CopyMem ((UINT32*)Buffer, &TmpValue, sizeof (UINT32));
}
/**
Print the current value of the specified question.
@param Question The pointer to question
@return EFI_SUCCESS
**/
static
EFI_STATUS
LogIfrValue (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_STATEMENT *Question
)
{
EFI_STATUS Status;
FORMSET_STORAGE *VarList;
UINT8 *VarBuffer;
UINT32 Value;
VarBuffer = NULL;
Status = SearchVarStorage (
Question,
NULL,
Question->VarStoreInfo.VarOffset,
FormSet->StorageListHead,
(CHAR8 **)&VarBuffer,
&VarList
);
if (EFI_ERROR (Status)) {
StringPrint("\nCouldn't read current variable data.");
return EFI_ABORTED;
}
//
// Log the Value
//
if (
(Question->VarStoreInfo.VarOffset > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_OP)
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else if (
(Question->VarStoreInfo.VarOffset > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
&& VarList->NewEfiVarstore
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else if (
(Question->StorageWidth > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
&& !VarList->NewEfiVarstore
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else {
if (Question->QuestionReferToBitField) {
GetBitsQuestionValue (Question, VarBuffer, &Value);
VarBuffer = (UINT8*)(&Value);
}
switch (Question->StorageWidth) {
case sizeof (UINT8):
StringPrint("%02X", (*(UINT8 *)VarBuffer) & 0xFF);
break;
case sizeof (UINT16):
StringPrint("%04X", (*(UINT16 *)VarBuffer) & 0xFFFF);
break;
case sizeof (UINT32):
StringPrint("%08X", (*(UINT32 *)VarBuffer) & 0xFFFFFFFF);
break;
case sizeof (UINT64):
StringPrint("%016llX", *((UINT64 *)VarBuffer));
break;
default:
StringPrint("0000 // Width > 16 is not supported -- FAILURE");
break;
}
}
return EFI_SUCCESS;
}
/**
Print the current value of the STRING question.
@param Question The pointer to question
@return EFI_SUCCESS
**/
static
EFI_STATUS
LogIfrValueStr (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_STATEMENT *Question
)
{
EFI_STATUS Status;
FORMSET_STORAGE *VarList;
UINT8 *VarBuffer;
VarBuffer = NULL;
Status = SearchVarStorage (
Question,
NULL,
Question->VarStoreInfo.VarOffset,
FormSet->StorageListHead,
(CHAR8 **)&VarBuffer,
&VarList
);
if (EFI_ERROR (Status)) {
StringPrint("\nCouldn't read current variable data.");
return EFI_ABORTED;
}
//
// Log the Value
//
if (
(Question->VarStoreInfo.VarOffset > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_OP)
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else if (
(Question->VarStoreInfo.VarOffset > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
&& VarList->NewEfiVarstore
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else if (
(Question->StorageWidth > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
&& !VarList->NewEfiVarstore
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else {
StringPrint("\"");
LogUnicodeString((CHAR16 *)VarBuffer);
StringPrint("\"");
}
return EFI_SUCCESS;
}
/**
Print the current values of an Ordered List question.
@param Question The pointer to question
@param MaxEntries The max number of options
@param VarList The dual pointer to the Node of VarList
@return EFI_SUCCESS
**/
static
EFI_STATUS
LogIfrValueList (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_STATEMENT *Question
)
{
EFI_STATUS Status;
FORMSET_STORAGE *VarList;
UINT8 CurrentEntry;
UINT8 *VarBuffer;
CurrentEntry = 0;
VarBuffer = NULL;
Status = SearchVarStorage (
Question,
NULL,
Question->VarStoreInfo.VarOffset,
FormSet->StorageListHead,
(CHAR8 **)&VarBuffer,
&VarList
);
if (EFI_ERROR (Status)) {
StringPrint("\nCouldn't read current variable data.");
return EFI_ABORTED;
}
//
// Log the value
//
if (
((Question->VarStoreInfo.VarOffset + Question->MaxContainers) > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_OP)
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else if (
(Question->MaxContainers > VarList->Size) \
&& (VarList->Type == EFI_IFR_VARSTORE_EFI_OP)
) {
StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
} else {
for (CurrentEntry = 0; CurrentEntry < Question->MaxContainers; CurrentEntry++) {
switch (Question->StorageWidth/Question->MaxContainers){
case 1:
StringPrint("%02X ", VarBuffer[CurrentEntry]);
break;
case 2:
StringPrint("%04X ", *((UINT16 *)VarBuffer + CurrentEntry));
break;
case 4:
StringPrint("%08X ", *((UINT32 *)VarBuffer + CurrentEntry));
break;
case 8:
StringPrint("%016llX ", *((UINT64 *)VarBuffer + CurrentEntry));
break;
default:
StringPrint("%02X ", VarBuffer[CurrentEntry]);
}
}
}
return EFI_SUCCESS;
}
/**
Compare two Uqi parameters
@param UqiParm1 The pointer to the first Uqi parameter.
@param UqiParm2 The pointer to the second Uqi parameter.
@retval TRUE If these two Uqi parameters are the same, return TRUE;
@return FALSE Otherwise, return FALSE;
**/
BOOLEAN
CompareUqiHeader (
IN CONST UQI_HEADER *UqiParm1,
IN CONST UQI_HEADER *UqiParm2
)
{
INT32 Index;
if (UqiParm1->HexNum != UqiParm2->HexNum) {
return FALSE;
}
for (Index = UqiParm1->HexNum - 1; Index >= 0; Index--) {
if (UqiParm1->Data[Index] != UqiParm2->Data[Index]) {
return FALSE;
}
}
return TRUE;
}
/**
Check whether existed a same variable in the LIST_ENTRY.
@param CurVarList A pointer to a variable node.
@return Pointer If existed the same variable, return the pointer to the Node.
@return NULL Otherwise, return FALSE
**/
static
FORMSET_STORAGE *
NotSameVariableInVarList (
IN LIST_ENTRY *VariableListEntry,
IN FORMSET_STORAGE *StorageNode
)
{
FORMSET_STORAGE *CurNode;
LIST_ENTRY *Link;
LIST_ENTRY *StorageListHead;
StorageListHead = VariableListEntry;
CurNode = NULL;
//
// Find Storage for this Question
//
Link = GetFirstNode (StorageListHead);
while (!IsNull (StorageListHead, Link)) {
CurNode = FORMSET_STORAGE_FROM_LINK (Link);
if (!CompareGuid (&StorageNode->Guid, &CurNode->Guid) \
&& (CurNode->Name != NULL) \
&& (StorageNode->Name != NULL) \
&& !FceStrCmp (StorageNode->Name, CurNode->Name) \
&& (StorageNode - CurNode != 0)
) {
//
// If not multi-plaform support mode, take VarStore as the EfiVarStore. So If there are
// two variables with same guid same name, but different type, we will take as the same
// in general mode
//
if (mMultiPlatformParam.MultiPlatformOrNot && (CurNode->Type == StorageNode->Type)) {
//
// If matched, get the address of EFI_IFR_VARSTORE data.
//
return CurNode;
break;
} else if (!mMultiPlatformParam.MultiPlatformOrNot) {
return CurNode;
break;
}
}
Link = GetNextNode (StorageListHead, Link);
}
return NULL;
}
/**
Get the UniString by the offset.
@param UniPackge A pointer to the beginning of Null-terminated Unicode string Array.
@param CurUniPackge A pointer to the current position of Null-terminated Unicode string Array.
@param VarDefaultNameId The string ID.
@param CurOrDefaultLang Use the current language or the default language.
@param VarDefaultName return the name string.
@return EFI_SUCCESS
@return EFI_INVALID_PARAMETER
@return EFI_NOT_FOUND
**/
static
EFI_STATUS
GetStringByOffset (
IN UINT8 *UniPackge,
IN UINT8 *CurUniPackge,
IN UINT16 VarDefaultNameId,
IN BOOLEAN CurOrDefaultLang,
IN OUT CHAR16 **VarDefaultName
)
{
UINT8 *HiiStringHeader;
UINT32 Offset;
UINT32 Count;
UINT32 Index;
EFI_HII_STRING_BLOCK *Block;
VOID *ThisBlock;
assert ((UniPackge != NULL) && (CurUniPackge != NULL));
HiiStringHeader = NULL;
Offset = 1;
Count = 0;
Block = NULL;
ThisBlock = NULL;
if (VarDefaultNameId == 0) {
return EFI_INVALID_PARAMETER;
}
if (CurOrDefaultLang) {
HiiStringHeader = CurUniPackge;
} else {
HiiStringHeader = UniPackge + 4;
}
Block = (EFI_HII_STRING_BLOCK *)((UINT8*)HiiStringHeader + ((EFI_HII_STRING_PACKAGE_HDR *)HiiStringHeader)->HdrSize);
//
// Search the matched String in specificated language package by the Offset
//
while( Block->BlockType != EFI_HII_SIBT_END ) {
switch (Block->BlockType) {
case EFI_HII_SIBT_STRING_SCSU:
ThisBlock = (VOID *)Block;
for (Index = 0 ; ((EFI_HII_SIBT_STRING_SCSU_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
Block = (EFI_HII_STRING_BLOCK *)&((EFI_HII_SIBT_STRING_SCSU_BLOCK *)ThisBlock)->StringText[Index + 1];
break;
case EFI_HII_SIBT_STRING_SCSU_FONT:
ThisBlock = (VOID *)Block;
for (Index = 0 ; ((EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
Block = (EFI_HII_STRING_BLOCK *)(((EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK *)ThisBlock) + 1);
break;
case EFI_HII_SIBT_STRINGS_SCSU:
ThisBlock = (VOID *)Block;
for( Count= ((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ThisBlock)->StringCount, Index = 0 ; Count; Count--, Index++ ) {
for ( ; ((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
}
Block = (EFI_HII_STRING_BLOCK *)&((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ThisBlock)->StringText[Index];
break;
case EFI_HII_SIBT_STRINGS_SCSU_FONT:
ThisBlock = (VOID *)Block;
for( Count = ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ThisBlock)->StringCount, Index = 0 ; Count; Count--, Index++ ) ;
Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ThisBlock)->StringText[Index];
break;
case EFI_HII_SIBT_STRING_UCS2:
ThisBlock = (VOID *)Block;
if (Offset == VarDefaultNameId) {
*VarDefaultName = malloc ((FceStrLen ((CHAR16 *) ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)ThisBlock)->StringText) + 1) * sizeof (CHAR16));
if (*VarDefaultName == NULL) {
printf ("Fail to allocate memory");
return EFI_OUT_OF_RESOURCES;
}
memset (
*VarDefaultName,
0,
(FceStrLen ((CHAR16 *) ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)ThisBlock)->StringText) + 1) * sizeof (CHAR16)
);
StrCpy (
*VarDefaultName,
(CHAR16 *) ((EFI_HII_SIBT_STRING_UCS2_BLOCK *) ThisBlock)->StringText
);
return EFI_SUCCESS;
}
for (Index = 0 ; ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRING_UCS2_BLOCK *) ThisBlock)->StringText[Index + 1];
Offset += 1;
break;
case EFI_HII_SIBT_STRING_UCS2_FONT:
ThisBlock = (VOID *)Block;
for (Index = 0 ; ((EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK *) ThisBlock)->StringText[Index] != 0 ; Index++) ;
Block = (EFI_HII_STRING_BLOCK *)& ((EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK *) ThisBlock)->StringText[Index + 1];
break;
case EFI_HII_SIBT_STRINGS_UCS2:
ThisBlock = (VOID *)Block;
for( Count = ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *)ThisBlock)->StringCount, Index = 0 ; Count; Count--, Index++ ) {
for ( ; ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *) ThisBlock)->StringText[Index] != 0 ; Index++) ;
}
Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *) ThisBlock)->StringText[Index];
break;
case EFI_HII_SIBT_STRINGS_UCS2_FONT:
ThisBlock = (VOID *)Block;
for( Count= ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *) ThisBlock)->StringCount, Index = 0 ; Count ; Count--, Index++ ) {
for ( ; ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *) ThisBlock)->StringText[Index] != 0 ; Index++) ;
}
Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *)ThisBlock)->StringText[Index];
break;
case EFI_HII_SIBT_DUPLICATE:
ThisBlock = (VOID *)Block;
Block = (EFI_HII_STRING_BLOCK *)((EFI_HII_SIBT_DUPLICATE_BLOCK *) ThisBlock + 1);
break;
case EFI_HII_SIBT_SKIP2:
ThisBlock = (VOID *)Block;
Offset += ((EFI_HII_SIBT_SKIP2_BLOCK *) ThisBlock)->SkipCount;
Block = (EFI_HII_STRING_BLOCK *)( (EFI_HII_SIBT_SKIP2_BLOCK *) ThisBlock + 1);
break;
case EFI_HII_SIBT_SKIP1:
ThisBlock = (VOID *)Block;
Offset += ((EFI_HII_SIBT_SKIP1_BLOCK *) ThisBlock)->SkipCount;
Block = (EFI_HII_STRING_BLOCK *)((EFI_HII_SIBT_SKIP1_BLOCK *)ThisBlock + 1);
break;
case EFI_HII_SIBT_EXT1:
ThisBlock = (VOID *)Block;
Block = (EFI_HII_STRING_BLOCK *)((UINT8*)ThisBlock + ((EFI_HII_SIBT_EXT1_BLOCK *) ThisBlock)->Length);
break;
case EFI_HII_SIBT_EXT2:
ThisBlock = (VOID *)Block;
Block = (EFI_HII_STRING_BLOCK *)((UINT8*)ThisBlock + ((EFI_HII_SIBT_EXT2_BLOCK *) ThisBlock)->Length);
break;
case EFI_HII_SIBT_EXT4:
ThisBlock = (VOID *)Block;
Block = (EFI_HII_STRING_BLOCK *)((UINT8*)ThisBlock + ((EFI_HII_SIBT_EXT4_BLOCK *)ThisBlock)->Length);
break;
case EFI_HII_SIBT_FONT:
ThisBlock = (VOID *)Block;
for (Index = 0 ; ((EFI_HII_SIBT_FONT_BLOCK *) ThisBlock)->FontName[Index] != 0 ; Index++) ;
Block = (EFI_HII_STRING_BLOCK *)& ((EFI_HII_SIBT_FONT_BLOCK *) ThisBlock)->FontName[Index + 1];
break;
default:
StringPrint("Unhandled type = 0x%x\n", Block->BlockType);
}
}
return EFI_NOT_FOUND;
}
/**
Parse the UniString to get the string information.
@param CachedStringList A pointer to cached string list
@param UniPackge A pointer to a Null-terminated Unicode string Array.
@param VarDefaultNameId The string ID.
@param Language The language, en-US UQI or eng.
@param VarDefaultName return the name string.
@return EFI_SUCCESS If get the name string successfully
@return EFI_NOT_FOUND An error occurred.
@return EFI_INVALID_PARAMETER
**/
EFI_STATUS
FindDefaultName (
IN FORMSET_STRING_LIST *CachedStringList,
IN UINT8 *UniPackge,
IN UINT16 VarDefaultNameId,
IN LANGUAGE Language,
IN OUT CHAR16 **VarDefaultName
)
{
CHAR8 *UniPackgeEnd;
CHAR8 *UniBin;
CHAR8 LangStr[10];
BOOLEAN IsFound;
EFI_STATUS Status;
EFI_STRING_ID Index;
STRING_INFO *TempBuffer;
UniBin = NULL;
IsFound = FALSE;
Status = EFI_NOT_FOUND;
UniBin = (CHAR8 *) UniPackge + 4;
UniPackgeEnd = (CHAR8 *) UniPackge + *(UINT32 *)UniPackge;
//
//Handle with the invalid usage "STRING_TOKEN(0)"
//
if (VarDefaultNameId == 0) {
*VarDefaultName = L"";
return EFI_SUCCESS;
}
if (CachedStringList != NULL) {
for (Index = 0; Index < CachedStringList->CachedIdNum; Index ++) {
if (VarDefaultNameId == CachedStringList->StringInfoList[Index].StringId) {
*VarDefaultName = CachedStringList->StringInfoList[Index].String;
return EFI_SUCCESS;
}
}
}
switch (Language) {
case UQI:
strcpy (LangStr, "uqi");
break;
case EN_US:
strcpy (LangStr, "en-US");
break;
case ENG:
strcpy (LangStr, "eng");
break;
default:
strcpy (LangStr, "en-US");
break;
}
IsFound = FALSE;
if (((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
//
// Search the specified language package
//
while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, LangStr) == 0) {
IsFound = TRUE;
break;
}
UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
}
//
//If not find the string ID, use the en eng or en-US instead.
//
if (!IsFound) {
UniBin = (CHAR8 *) UniPackge + 4;
while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
if ((strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en") == 0) \
|| (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en-US") == 0) \
|| (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "eng") == 0) \
) {
IsFound = TRUE;
break;
}
UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
}
}
//
//If not still find the string ID, use the first one instead.
//
Status = GetStringByOffset (
UniPackge,
(UINT8 *)UniBin,
VarDefaultNameId,
IsFound,
VarDefaultName
);
if (!EFI_ERROR (Status)) {
goto Done;
}
//
//If not find the specified string in UQI package, we use the en en-us eng or uqi insteadly
//
IsFound = FALSE;
UniBin = (CHAR8 *) UniPackge + 4;
while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en") == 0) {
IsFound = TRUE;
break;
}
UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
}
Status = GetStringByOffset (
UniPackge,
(UINT8 *)UniBin,
VarDefaultNameId,
IsFound,
VarDefaultName
);
if (!EFI_ERROR (Status)) {
goto Done;
}
IsFound = FALSE;
UniBin = (CHAR8 *) UniPackge + 4;
while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en-US") == 0) {
IsFound = TRUE;
break;
}
UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
}
Status = GetStringByOffset (
UniPackge,
(UINT8 *)UniBin,
VarDefaultNameId,
IsFound,
VarDefaultName
);
if (!EFI_ERROR (Status)) {
goto Done;
}
IsFound = FALSE;
UniBin = (CHAR8 *) UniPackge + 4;
while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "eng") == 0) {
IsFound = TRUE;
break;
}
UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
}
Status = GetStringByOffset (
UniPackge,
(UINT8 *)UniBin,
VarDefaultNameId,
IsFound,
VarDefaultName
);
if (!EFI_ERROR (Status)) {
goto Done;
}
IsFound = FALSE;
UniBin = (CHAR8 *) UniPackge + 4;
while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "uqi") == 0) {
IsFound = TRUE;
break;
}
UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
}
Status = GetStringByOffset (
UniPackge,
(UINT8 *)UniBin,
VarDefaultNameId,
IsFound,
VarDefaultName
);
if (!EFI_ERROR (Status)) {
goto Done;
}
}
Done:
if (EFI_ERROR (Status)) {
*VarDefaultName = NULL;
return EFI_NOT_FOUND;
}
if (CachedStringList != NULL) {
if (CachedStringList->CachedIdNum >= CachedStringList->MaxIdNum) {
TempBuffer = calloc (sizeof (STRING_INFO), CachedStringList->MaxIdNum + STRING_NUMBER);
if (TempBuffer == NULL) {
printf ("Fail to allocate memory! \n");
free (*VarDefaultName);
*VarDefaultName = NULL;
return EFI_OUT_OF_RESOURCES;
}
CopyMem (TempBuffer, CachedStringList->StringInfoList, sizeof (STRING_INFO) * CachedStringList->MaxIdNum);
FreePool (CachedStringList->StringInfoList);
CachedStringList->StringInfoList = TempBuffer;
CachedStringList->MaxIdNum = CachedStringList->MaxIdNum + STRING_NUMBER;
}
CachedStringList->StringInfoList[CachedStringList->CachedIdNum].StringId = VarDefaultNameId;
CachedStringList->StringInfoList[CachedStringList->CachedIdNum].String = *VarDefaultName;
CachedStringList->CachedIdNum ++;
}
return EFI_SUCCESS;
}
/**
Get the variable Guid and Name by the variableId and FormSetOrder.
@param FormSet The pointer to the formset.
@param FormSet The pointer to the form.
@param ListEntry The pointer to the LIST_ENTRY.
@return EFI_SUCCESS
@return EFI_NOT_FOUND If not find the the variable, or the variable doesn't belong to EfiVarStore or VarStore.
**/
static
EFI_STATUS
GetGuidNameByVariableId (
IN FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_STATEMENT *Question,
IN LIST_ENTRY *ListEntry
)
{
FORMSET_STORAGE *CurNode;
LIST_ENTRY *Link;
LIST_ENTRY *StorageListHead;
EFI_STATUS Status;
CHAR16 *EfiVariableName;
StorageListHead = ListEntry;
CurNode = NULL;
Status = EFI_SUCCESS;
EfiVariableName = NULL;
Link = GetFirstNode (StorageListHead);
while (!IsNull (StorageListHead, Link)) {
CurNode = FORMSET_STORAGE_FROM_LINK (Link);
if ((FormSet->FormSetOrder == CurNode->FormSetOrder) \
&& (Question->VarStoreId == CurNode->VarStoreId)
) {
//
// Copy type to question to avoid the case that EfiVarStore and VarStore have the same Guid and name.
//
Question->Type = CurNode->Type;
Question->NewEfiVarstore = CurNode->NewEfiVarstore;
Question->Attributes = CurNode->Attributes;
if (CurNode->Type == EFI_IFR_VARSTORE_EFI_OP) {
CopyMem (&Question->Guid, &CurNode->Guid, sizeof (EFI_GUID));
//
// If the first time to access the old EfiVarStore, need to sync the variable name
//
if (!CurNode->NewEfiVarstore) {
if (CurNode->Buffer == NULL) {
CurNode->Buffer = malloc (Question->StorageWidth);
}
if (CurNode->Name == NULL) {
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->VarStoreInfo.VarName,
EN_US,
&EfiVariableName
);
if (EFI_ERROR(Status)) {
return Status;
}
CurNode->Name = EfiVariableName;
}
if (CurNode->Size == 0) {
CurNode->Size = Question->StorageWidth;
}
}
//
// Check whether the Efivariable variable name is valid.
//
if ((CurNode->Name == NULL) || (FceStrLen (CurNode->Name) == 0)) {
StringPrint ("Error. The variable name of question is NULL. Its UQI is: ");
StringPrint("Q %04X ", Question->Uqi.HexNum);
LogUqi (Question->Uqi.Data);
StringPrint ("\n");
return EFI_ABORTED;
}
if (Question->VariableName == NULL) {
Question->VariableName = (CHAR16 *) malloc (2 * (FceStrLen ((CONST CHAR16 *)CurNode->Name) + 1));
if (Question->VariableName == NULL) {
return EFI_ABORTED;
}
}
StrCpy (Question->VariableName, CurNode->Name);
return EFI_SUCCESS;
} else if (CurNode->Type == EFI_IFR_VARSTORE_OP) {
CopyMem (&Question->Guid, &CurNode->Guid, sizeof (EFI_GUID));
if (Question->VariableName == NULL) {
Question->VariableName = (CHAR16 *) malloc (2 * (FceStrLen ((CONST CHAR16 *)CurNode->Name) + 1));
if (Question->VariableName == NULL) {
return EFI_ABORTED;
}
}
//
// Check whether the variable variable name is valid.
//
if ((CurNode->Name == NULL) || (FceStrLen (CurNode->Name) == 0)) {
StringPrint ("Error. The variable name of question is NULL. UQI:");
StringPrint("Q %04X ", Question->Uqi.HexNum);
LogUqi (Question->Uqi.Data);
StringPrint ("\n");
return EFI_ABORTED;
}
StrCpy (Question->VariableName, CurNode->Name);
return EFI_SUCCESS;
}
}
Link = GetNextNode (StorageListHead, Link);
}
return EFI_NOT_FOUND;
}
/**
Search the variable list according to the variable Guid and name, and return the pointer
of that Node.
@param HiiObjList The pointer to the Question
@param VarName The EFI variable name need to be updated to VarList
@param Offset The offset of the variable
@param StorageListHead The pointer to the LIST_ENTRY of Storage
@param Vaue The value in that value offset of the variable
@param VarList The dual pointer of Varlist
@return EFI_SUCCESS
@return EFI_NOT_FOUND
**/
EFI_STATUS
SearchVarStorage (
IN FORM_BROWSER_STATEMENT *Question,
IN CHAR16* VarName,
IN UINT32 Offset,
IN LIST_ENTRY *StorageListHead,
IN OUT CHAR8 **Value,
IN OUT FORMSET_STORAGE **VarList
)
{
FORMSET_STORAGE *CurNode;
LIST_ENTRY *Link;
BOOLEAN FindOrNot;
CurNode = NULL;
FindOrNot = FALSE;
*VarList = NULL;
//
// Find Storage for this Question
//
Link = GetFirstNode (StorageListHead);
while (!IsNull (StorageListHead, Link)) {
CurNode = FORMSET_STORAGE_FROM_LINK (Link);
//
// Deal with the old EfiVarstore before UEFI2.31
//
if (!CompareGuid (&Question->Guid, &CurNode->Guid) \
&& (CurNode->Type == EFI_IFR_VARSTORE_EFI_OP) \
&& !CurNode->NewEfiVarstore \
&& (Question->VariableName != NULL) \
&& (CurNode->Name != NULL) \
&& !FceStrCmp(Question->VariableName, CurNode->Name)
) {
//
// If not multi-plaform support mode, take VarStore as the EfiVarStore. So If there are
// two variables with same guid same name, but different type, we will take as the same
// in general mode
//
if (mMultiPlatformParam.MultiPlatformOrNot && (CurNode->Type == Question->Type)) {
//
// check whether exist a old EFI_IFR_VARSTORE_EFI or not.
//
*Value = (CHAR8 *)CurNode->Buffer;
*VarList = CurNode;
FindOrNot = TRUE;
break;
} else if (!mMultiPlatformParam.MultiPlatformOrNot) {
//
// check whether exist a old EFI_IFR_VARSTORE_EFI or not.
//
*Value = (CHAR8 *)CurNode->Buffer;
*VarList = CurNode;
FindOrNot = TRUE;
break;
}
}
if (!CompareGuid (&Question->Guid, &CurNode->Guid) \
&& (CurNode->Name != NULL) \
&& (Question->VariableName != NULL) \
&& !FceStrCmp(Question->VariableName, CurNode->Name)
) {
//
// If not multi-plaform support mode, take VarStore as the EfiVarStore. So If there are
// two variables with same guid same name, but different type, we will take as the same
// in general mode
//
if (mMultiPlatformParam.MultiPlatformOrNot && (CurNode->Type == Question->Type)) {
//
// If matched, get the address of EFI_IFR_VARSTORE data.
//
*Value = (CHAR8 *)(CurNode->Buffer + Offset);
*VarList = CurNode;
FindOrNot = TRUE;
break;
} else if (!mMultiPlatformParam.MultiPlatformOrNot) {
//
// If matched, get the address of EFI_IFR_VARSTORE data.
//
*Value = (CHAR8 *)(CurNode->Buffer + Offset);
*VarList = CurNode;
FindOrNot = TRUE;
break;
}
}
Link = GetNextNode (StorageListHead, Link);
}
if (!FindOrNot) {
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/**
Get the string based on the StringId and HII Package List Handle.
@param Token The String's ID.
@param HiiHandle The package list in the HII database to search for
the specified string.
@return The output string.
**/
CHAR16 *
GetToken (
IN EFI_STRING_ID Token,
IN UINT8 *UniPackge
)
{
CHAR16 *VarDefaultName;
EFI_STATUS Status;
Status = EFI_SUCCESS;
if (UniPackge == NULL) {
return NULL;
}
Status = FindDefaultName (
NULL,
UniPackge,
Token,
EN_US,
&VarDefaultName
);
if (EFI_ERROR (Status)) {
return NULL;
}
return VarDefaultName;
}
/**
Initialize Statement header members.
@param OpCodeData Pointer of the raw OpCode data.
@param FormSet Pointer of the current FormSe.
@param Form Pointer of the current Form.
@return The Statement.
**/
FORM_BROWSER_STATEMENT *
CreateStatement (
IN UINT8 *OpCodeData,
IN OUT FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_FORM *Form
)
{
FORM_BROWSER_STATEMENT *Statement;
EFI_IFR_STATEMENT_HEADER *StatementHdr;
if (Form == NULL) {
//
// We are currently not in a Form Scope, so just skip this Statement
//
return NULL;
}
Statement = &FormSet->StatementBuffer[mStatementIndex];
mStatementIndex++;
InitializeListHead (&Statement->DefaultListHead);
InitializeListHead (&Statement->OptionListHead);
InitializeListHead (&Statement->InconsistentListHead);
InitializeListHead (&Statement->NoSubmitListHead);
InitializeListHead (&Statement->WarningListHead);
Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
Statement->QuestionReferToBitField = FALSE;
StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
if (mInScopeSuppress) {
Statement->SuppressExpression = mSuppressExpression;
}
if (mInScopeGrayOut) {
Statement->GrayOutExpression = mGrayOutExpression;
}
if (mInScopeDisable) {
Statement->DisableExpression = mDisableExpression;
}
Statement->InSubtitle = mInScopeSubtitle;
//
// Insert this Statement into current Form
//
InsertTailList (&Form->StatementListHead, &Statement->Link);
return Statement;
}
/**
Initialize Question's members.
@param OpCodeData Pointer of the raw OpCode data.
@param FormSet Pointer of the current FormSet.
@param Form Pointer of the current Form.
@return The Question.
**/
FORM_BROWSER_STATEMENT *
CreateQuestion (
IN UINT8 *OpCodeData,
IN OUT FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_FORM *Form
)
{
FORM_BROWSER_STATEMENT *Statement;
EFI_IFR_QUESTION_HEADER *QuestionHdr;
LIST_ENTRY *Link;
FORMSET_STORAGE *Storage;
NAME_VALUE_NODE *NameValueNode;
Statement = CreateStatement (OpCodeData, FormSet, Form);
if (Statement == NULL) {
return NULL;
}
QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
Statement->QuestionFlags = QuestionHdr->Flags;
Statement->FormSetOrder = mFormSetOrderParse;
if (Statement->VarStoreId == 0) {
//
// VarStoreId of zero indicates no variable storage
//
return Statement;
}
//
// Find Storage for this Question
//
Link = GetFirstNode (FormSet->StorageListHead);
while (!IsNull (FormSet->StorageListHead, Link)) {
Storage = FORMSET_STORAGE_FROM_LINK (Link);
if ((Storage->VarStoreId == Statement->VarStoreId)
&& (Storage->FormSetOrder == Statement->FormSetOrder)) {
Statement->Storage = Storage;
break;
}
Link = GetNextNode (FormSet->StorageListHead, Link);
}
ASSERT (Statement->Storage != NULL);
if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->UnicodeBinary);
ASSERT (Statement->VariableName != NULL);
//
// Insert to Name/Value varstore list
//
NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
ASSERT (NameValueNode != NULL);
NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
NameValueNode->Name = FceAllocateCopyPool (FceStrSize (Statement->VariableName), Statement->VariableName);
ASSERT (NameValueNode->Name != NULL);
NameValueNode->Value = AllocateZeroPool (0x10);
ASSERT (NameValueNode->Value != NULL);
NameValueNode->EditValue = AllocateZeroPool (0x10);
ASSERT (NameValueNode->EditValue != NULL);
InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
}
return Statement;
}
/**
Allocate a FORM_EXPRESSION node.
@param Form The Form associated with this Expression
@return Pointer to a FORM_EXPRESSION data structure.
**/
FORM_EXPRESSION *
CreateExpression (
IN OUT FORM_BROWSER_FORM *Form
)
{
FORM_EXPRESSION *Expression;
Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
ASSERT (Expression != NULL);
Expression->Signature = FORM_EXPRESSION_SIGNATURE;
InitializeListHead (&Expression->OpCodeListHead);
return Expression;
}
/**
Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
@param FormSet Pointer of the current FormSet
@return Pointer to a FORMSET_STORAGE data structure.
**/
FORMSET_STORAGE *
CreateStorage (
IN FORM_BROWSER_FORMSET *FormSet
)
{
FORMSET_STORAGE *Storage;
Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
ASSERT (Storage != NULL);
Storage->Signature = FORMSET_STORAGE_SIGNATURE;
InitializeListHead (&Storage->NameValueListHead);
InsertTailList (FormSet->StorageListHead, &Storage->Link);
return Storage;
}
/**
Free resources of a Expression.
@param FormSet Pointer of the Expression
**/
VOID
DestroyExpression (
IN FORM_EXPRESSION *Expression
)
{
LIST_ENTRY *Link;
EXPRESSION_OPCODE *OpCode;
LIST_ENTRY *SubExpressionLink;
FORM_EXPRESSION *SubExpression;
while (!IsListEmpty (&Expression->OpCodeListHead)) {
Link = GetFirstNode (&Expression->OpCodeListHead);
OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
RemoveEntryList (&OpCode->Link);
if (OpCode->ValueList != NULL) {
FreePool (OpCode->ValueList);
}
if (OpCode->ValueName != NULL) {
FreePool (OpCode->ValueName);
}
if (OpCode->MapExpressionList.ForwardLink != NULL) {
while (!IsListEmpty (&OpCode->MapExpressionList)) {
SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
RemoveEntryList(&SubExpression->Link);
DestroyExpression (SubExpression);
}
}
}
//
// Free this Expression
//
FreePool (Expression);
}
/**
Free resources of a storage.
@param Storage Pointer of the storage
**/
VOID
DestroyStorage (
IN FORMSET_STORAGE *Storage
)
{
LIST_ENTRY *Link;
NAME_VALUE_NODE *NameValueNode;
if (Storage == NULL) {
return;
}
if (Storage->Name != NULL) {
FreePool (Storage->Name);
}
if (Storage->Buffer != NULL) {
FreePool (Storage->Buffer);
}
while (!IsListEmpty (&Storage->NameValueListHead)) {
Link = GetFirstNode (&Storage->NameValueListHead);
NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
RemoveEntryList (&NameValueNode->Link);
if (NameValueNode->Name != NULL) {
FreePool (NameValueNode->Name);
}
if (NameValueNode->Value != NULL) {
FreePool (NameValueNode->Value);
}
if (NameValueNode->EditValue != NULL) {
FreePool (NameValueNode->EditValue);
}
FreePool (NameValueNode);
}
FreePool (Storage);
Storage = NULL;
}
/**
Free resources allocated for all Storage in an LIST_ENTRY.
@param FormSet Pointer of the FormSet
**/
VOID
DestroyAllStorage (
IN LIST_ENTRY *StorageEntryListHead
)
{
LIST_ENTRY *Link;
FORMSET_STORAGE *Storage;
//
// Parse Fromset one by one
//
if (StorageEntryListHead->ForwardLink != NULL) {
while (!IsListEmpty (StorageEntryListHead)) {
Link = GetFirstNode (StorageEntryListHead);
Storage = FORMSET_STORAGE_FROM_LINK (Link);
RemoveEntryList (&Storage->Link);
DestroyStorage (Storage);
}
}
StorageEntryListHead = NULL;
}
/**
Free resources of a Statement.
@param FormSet Pointer of the FormSet
@param Statement Pointer of the Statement
**/
VOID
DestroyStatement (
IN FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_STATEMENT *Statement
)
{
LIST_ENTRY *Link;
QUESTION_DEFAULT *Default;
QUESTION_OPTION *Option;
FORM_EXPRESSION *Expression;
//
// Free Default value List
//
while (!IsListEmpty (&Statement->DefaultListHead)) {
Link = GetFirstNode (&Statement->DefaultListHead);
Default = QUESTION_DEFAULT_FROM_LINK (Link);
RemoveEntryList (&Default->Link);
if (Default->Value.Buffer != NULL) {
FreePool(Default->Value.Buffer);
}
FreePool (Default);
}
//
// Free Options List
//
while (!IsListEmpty (&Statement->OptionListHead)) {
Link = GetFirstNode (&Statement->OptionListHead);
Option = QUESTION_OPTION_FROM_LINK (Link);
RemoveEntryList (&Option->Link);
FreePool (Option);
}
//
// Free Inconsistent List
//
while (!IsListEmpty (&Statement->InconsistentListHead)) {
Link = GetFirstNode (&Statement->InconsistentListHead);
Expression = FORM_EXPRESSION_FROM_LINK (Link);
RemoveEntryList (&Expression->Link);
DestroyExpression (Expression);
}
//
// Free NoSubmit List
//
while (!IsListEmpty (&Statement->NoSubmitListHead)) {
Link = GetFirstNode (&Statement->NoSubmitListHead);
Expression = FORM_EXPRESSION_FROM_LINK (Link);
RemoveEntryList (&Expression->Link);
DestroyExpression (Expression);
}
//
// Free WarningIf List
//
while (!IsListEmpty (&Statement->WarningListHead)) {
Link = GetFirstNode (&Statement->WarningListHead);
Expression = FORM_EXPRESSION_FROM_LINK (Link);
RemoveEntryList (&Expression->Link);
DestroyExpression (Expression);
}
if (Statement->VariableName != NULL) {
FreePool (Statement->VariableName);
}
if (Statement->BufferValue != NULL) {
FreePool (Statement->BufferValue);
}
}
/**
Free resources of a Form.
@param FormSet Pointer of the FormSet
@param Form Pointer of the Form.
**/
VOID
DestroyForm (
IN FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_FORM *Form
)
{
LIST_ENTRY *Link;
FORM_EXPRESSION *Expression;
FORM_BROWSER_STATEMENT *Statement;
//
// Free Form Expressions
//
while (!IsListEmpty (&Form->ExpressionListHead)) {
Link = GetFirstNode (&Form->ExpressionListHead);
Expression = FORM_EXPRESSION_FROM_LINK (Link);
RemoveEntryList (&Expression->Link);
DestroyExpression (Expression);
}
//
// Free Statements/Questions
//
while (!IsListEmpty (&Form->StatementListHead)) {
Link = GetFirstNode (&Form->StatementListHead);
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
RemoveEntryList (&Statement->Link);
DestroyStatement (FormSet, Statement);
}
//
// Free this Form
//
FreePool (Form);
}
/**
Free resources allocated for a FormSet.
@param FormSet Pointer of the FormSet
**/
VOID
DestroyFormSet (
IN FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
FORMSET_DEFAULTSTORE *DefaultStore;
FORM_EXPRESSION *Expression;
FORM_BROWSER_FORM *Form;
UINT16 Index;
//
// Free FormSet Default Store
//
if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
Link = GetFirstNode (&FormSet->DefaultStoreListHead);
DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
RemoveEntryList (&DefaultStore->Link);
FreePool (DefaultStore);
}
}
//
// Free Formset Expressions
//
while (!IsListEmpty (&FormSet->ExpressionListHead)) {
Link = GetFirstNode (&FormSet->ExpressionListHead);
Expression = FORM_EXPRESSION_FROM_LINK (Link);
RemoveEntryList (&Expression->Link);
DestroyExpression (Expression);
}
//
// Free Forms
//
if (FormSet->FormListHead.ForwardLink != NULL) {
while (!IsListEmpty (&FormSet->FormListHead)) {
Link = GetFirstNode (&FormSet->FormListHead);
Form = FORM_BROWSER_FORM_FROM_LINK (Link);
RemoveEntryList (&Form->Link);
DestroyForm (FormSet, Form);
}
}
if (FormSet->StatementBuffer != NULL) {
FreePool (FormSet->StatementBuffer);
}
if (FormSet->ExpressionBuffer != NULL) {
FreePool (FormSet->ExpressionBuffer);
}
if (FormSet->EnUsStringList.StringInfoList != NULL) {
for (Index = 0; Index < FormSet->EnUsStringList.CachedIdNum; Index ++) {
FreePool (FormSet->EnUsStringList.StringInfoList[Index].String);
}
FreePool (FormSet->EnUsStringList.StringInfoList);
}
if (FormSet->UqiStringList.StringInfoList != NULL) {
for (Index = 0; Index < FormSet->UqiStringList.CachedIdNum; Index ++) {
FreePool (FormSet->UqiStringList.StringInfoList[Index].String);
}
FreePool (FormSet->UqiStringList.StringInfoList);
}
FreePool (FormSet);
}
/**
Free resources allocated for all FormSet in an LIST_ENTRY.
@param FormSet Pointer of the FormSet
**/
VOID
DestroyAllFormSet (
IN LIST_ENTRY *FormSetEntryListHead
)
{
LIST_ENTRY *Link;
FORM_BROWSER_FORMSET *FormSet;
//
// Parse Fromset one by one
//
if (FormSetEntryListHead->ForwardLink != NULL) {
while (!IsListEmpty (FormSetEntryListHead)) {
Link = GetFirstNode (FormSetEntryListHead);
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
RemoveEntryList (&FormSet->Link);
DestroyFormSet (FormSet);
}
}
}
/**
Tell whether this Operand is an Expression OpCode or not
@param Operand Operand of an IFR OpCode.
@retval TRUE This is an Expression OpCode.
@retval FALSE Not an Expression OpCode.
**/
BOOLEAN
IsExpressionOpCode (
IN UINT8 Operand
)
{
if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) ||
((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
(Operand == EFI_IFR_CATENATE_OP) ||
(Operand == EFI_IFR_TO_LOWER_OP) ||
(Operand == EFI_IFR_TO_UPPER_OP) ||
(Operand == EFI_IFR_MAP_OP) ||
(Operand == EFI_IFR_VERSION_OP) ||
(Operand == EFI_IFR_SECURITY_OP)) {
return TRUE;
} else {
return FALSE;
}
}
/**
Calculate number of Statemens(Questions) and Expression OpCodes.
@param FormSet The FormSet to be counted.
@param NumberOfStatement Number of Statemens(Questions)
@param NumberOfExpression Number of Expression OpCodes
**/
VOID
CountOpCodes (
IN FORM_BROWSER_FORMSET *FormSet,
IN OUT UINT16 *NumberOfStatement,
IN OUT UINT16 *NumberOfExpression
)
{
UINT16 StatementCount;
UINT16 ExpressionCount;
UINT8 *OpCodeData;
UINTN Offset;
UINTN OpCodeLen;
Offset = 0;
StatementCount = 0;
ExpressionCount = 0;
while (Offset < FormSet->IfrBinaryLength) {
OpCodeData = FormSet->IfrBinaryData + Offset;
OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
Offset += OpCodeLen;
if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
ExpressionCount++;
} else {
StatementCount++;
}
}
*NumberOfStatement = StatementCount;
*NumberOfExpression = ExpressionCount;
}
/**
Parse opcodes in the formset IFR binary.
@param FormSet Pointer of the FormSet data structure.
@retval EFI_SUCCESS Opcode parse success.
@retval Other Opcode parse fail.
**/
EFI_STATUS
ParseOpCodes (
IN FORM_BROWSER_FORMSET *FormSet
)
{
EFI_STATUS Status;
UINT16 Index;
FORM_BROWSER_FORM *CurrentForm;
FORM_BROWSER_STATEMENT *CurrentStatement;
EXPRESSION_OPCODE *ExpressionOpCode;
FORM_EXPRESSION *CurrentExpression;
UINT8 Operand;
UINT8 Scope;
UINTN OpCodeOffset;
UINTN OpCodeLength;
UINT8 *OpCodeData;
UINT8 ScopeOpCode;
FORMSET_STORAGE *Storage;
FORMSET_STORAGE *TempStorage;
FORMSET_DEFAULTSTORE *DefaultStore;
QUESTION_DEFAULT *CurrentDefault;
QUESTION_OPTION *CurrentOption;
UINT8 Width;
CHAR8 *AsciiString;
UINT16 NumberOfStatement;
UINT16 NumberOfExpression;
BOOLEAN SuppressForQuestion;
BOOLEAN SuppressForOption;
BOOLEAN InScopeOptionSuppress;
FORM_EXPRESSION *OptionSuppressExpression;
BOOLEAN InScopeFormSuppress;
FORM_EXPRESSION *FormSuppressExpression;
UINT16 DepthOfDisable;
BOOLEAN OpCodeDisabled;
BOOLEAN SingleOpCodeExpression;
BOOLEAN InScopeDefault;
EFI_HII_VALUE *Value;
UINT8 MapScopeDepth;
LIST_ENTRY *Link;
FORMSET_STORAGE *VarStorage;
LIST_ENTRY *MapExpressionList;
EFI_VARSTORE_ID TempVarstoreId;
BOOLEAN ConstantFlag;
FORMSET_DEFAULTSTORE *PreDefaultStore;
LIST_ENTRY *DefaultLink;
BOOLEAN HaveInserted;
BOOLEAN BitFieldStorage;
UINT16 TotalBits;
mInScopeSubtitle = FALSE;
SuppressForQuestion = FALSE;
SuppressForOption = FALSE;
InScopeFormSuppress = FALSE;
mInScopeSuppress = FALSE;
InScopeOptionSuppress = FALSE;
mInScopeGrayOut = FALSE;
mInScopeDisable = FALSE;
DepthOfDisable = 0;
OpCodeDisabled = FALSE;
SingleOpCodeExpression = FALSE;
InScopeDefault = FALSE;
CurrentExpression = NULL;
CurrentDefault = NULL;
CurrentOption = NULL;
OptionSuppressExpression = NULL;
FormSuppressExpression = NULL;
MapScopeDepth = 0;
Link = NULL;
VarStorage = NULL;
MapExpressionList = NULL;
TempVarstoreId = 0;
ConstantFlag = TRUE;
BitFieldStorage = FALSE;
//
// Get the number of Statements and Expressions
//
CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
mStatementIndex = 0;
FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
if (FormSet->StatementBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
mExpressionOpCodeIndex = 0;
FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
if (FormSet->ExpressionBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
FormSet->StorageListHead = &mVarListEntry;
InitializeListHead (&FormSet->DefaultStoreListHead);
InitializeListHead (&FormSet->FormListHead);
InitializeListHead (&FormSet->ExpressionListHead);
ResetCurrentExpressionStack ();
ResetMapExpressionListStack ();
CurrentForm = NULL;
CurrentStatement = NULL;
ResetScopeStack ();
OpCodeOffset = 0;
while (OpCodeOffset < FormSet->IfrBinaryLength) {
OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
OpCodeOffset += OpCodeLength;
Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
//
// If scope bit set, push onto scope stack
//
if (Scope != 0) {
PushScope (Operand);
}
if (OpCodeDisabled) {
//
// DisableIf Expression is evaluated to be TRUE, try to find its end.
// Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
//
if (Operand == EFI_IFR_DISABLE_IF_OP) {
DepthOfDisable++;
} else if (Operand == EFI_IFR_END_OP) {
Status = PopScope (&ScopeOpCode);
if (EFI_ERROR (Status)) {
return Status;
}
if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
if (DepthOfDisable == 0) {
mInScopeDisable = FALSE;
OpCodeDisabled = FALSE;
} else {
DepthOfDisable--;
}
}
}
continue;
}
if (IsExpressionOpCode (Operand)) {
ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
mExpressionOpCodeIndex++;
ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
ExpressionOpCode->Operand = Operand;
Value = &ExpressionOpCode->Value;
switch (Operand) {
case EFI_IFR_EQ_ID_VAL_OP:
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
break;
case EFI_IFR_EQ_ID_ID_OP:
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
break;
case EFI_IFR_EQ_ID_VAL_LIST_OP:
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
ExpressionOpCode->ValueList = FceAllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
break;
case EFI_IFR_TO_STRING_OP:
case EFI_IFR_FIND_OP:
ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
break;
case EFI_IFR_STRING_REF1_OP:
Value->Type = EFI_IFR_TYPE_STRING;
CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
break;
case EFI_IFR_RULE_REF_OP:
ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
break;
case EFI_IFR_SPAN_OP:
ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
break;
case EFI_IFR_THIS_OP:
ASSERT (CurrentStatement != NULL);
ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
break;
case EFI_IFR_SECURITY_OP:
CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
break;
case EFI_IFR_GET_OP:
case EFI_IFR_SET_OP:
CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
if (TempVarstoreId != 0) {
if (FormSet->StorageListHead->ForwardLink != NULL) {
Link = GetFirstNode (FormSet->StorageListHead);
while (!IsNull (FormSet->StorageListHead, Link)) {
VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
ExpressionOpCode->VarStorage = VarStorage;
break;
}
Link = GetNextNode (FormSet->StorageListHead, Link);
}
}
if (ExpressionOpCode->VarStorage == NULL) {
//
// VarStorage is not found.
//
return EFI_INVALID_PARAMETER;
}
}
ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;
switch (ExpressionOpCode->ValueType) {
case EFI_IFR_TYPE_BOOLEAN:
case EFI_IFR_TYPE_NUM_SIZE_8:
ExpressionOpCode->ValueWidth = 1;
break;
case EFI_IFR_TYPE_NUM_SIZE_16:
case EFI_IFR_TYPE_STRING:
ExpressionOpCode->ValueWidth = 2;
break;
case EFI_IFR_TYPE_NUM_SIZE_32:
ExpressionOpCode->ValueWidth = 4;
break;
case EFI_IFR_TYPE_NUM_SIZE_64:
ExpressionOpCode->ValueWidth = 8;
break;
case EFI_IFR_TYPE_DATE:
ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_DATE);
break;
case EFI_IFR_TYPE_TIME:
ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_TIME);
break;
case EFI_IFR_TYPE_REF:
ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);
break;
case EFI_IFR_TYPE_OTHER:
case EFI_IFR_TYPE_UNDEFINED:
case EFI_IFR_TYPE_ACTION:
case EFI_IFR_TYPE_BUFFER:
default:
//
// Invalid value type for Get/Set opcode.
//
return EFI_INVALID_PARAMETER;
}
CopyMem (&ExpressionOpCode->VarStoreInfo.VarName, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName, sizeof (EFI_STRING_ID));
CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));
if ((ExpressionOpCode->VarStorage != NULL) &&
((ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE)
|| ((ExpressionOpCode->VarStorage->Type == EFI_IFR_VARSTORE_EFI_OP) && !ExpressionOpCode->VarStorage->NewEfiVarstore))
) {
ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->UnicodeBinary);
if (ExpressionOpCode->ValueName == NULL) {
//
// String ID is invalid.
//
return EFI_INVALID_PARAMETER;
}
}
break;
case EFI_IFR_QUESTION_REF1_OP:
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
break;
case EFI_IFR_QUESTION_REF3_OP:
if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
}
}
break;
//
// constant
//
case EFI_IFR_TRUE_OP:
Value->Type = EFI_IFR_TYPE_BOOLEAN;
Value->Value.b = TRUE;
break;
case EFI_IFR_FALSE_OP:
Value->Type = EFI_IFR_TYPE_BOOLEAN;
Value->Value.b = FALSE;
break;
case EFI_IFR_ONE_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
Value->Value.u8 = 1;
break;
case EFI_IFR_ZERO_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
Value->Value.u8 = 0;
break;
case EFI_IFR_ONES_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
Value->Value.u64 = 0xffffffffffffffffULL;
break;
case EFI_IFR_UINT8_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
break;
case EFI_IFR_UINT16_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
break;
case EFI_IFR_UINT32_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
break;
case EFI_IFR_UINT64_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
break;
case EFI_IFR_UNDEFINED_OP:
Value->Type = EFI_IFR_TYPE_UNDEFINED;
break;
case EFI_IFR_VERSION_OP:
Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
break;
default:
break;
}
//
// Create sub expression nested in MAP opcode
//
if ((CurrentExpression == NULL) && (MapScopeDepth > 0)) {
CurrentExpression = CreateExpression (CurrentForm);
ASSERT (MapExpressionList != NULL);
InsertTailList (MapExpressionList, &CurrentExpression->Link);
if (Scope == 0) {
SingleOpCodeExpression = TRUE;
}
}
ASSERT (CurrentExpression != NULL);
InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
if (Operand == EFI_IFR_MAP_OP) {
//
// Store current Map Expression List.
//
if (MapExpressionList != NULL) {
PushMapExpressionList (MapExpressionList);
}
//
// Initialize new Map Expression List.
//
MapExpressionList = &ExpressionOpCode->MapExpressionList;
InitializeListHead (MapExpressionList);
//
// Store current expression.
//
PushCurrentExpression (CurrentExpression);
CurrentExpression = NULL;
MapScopeDepth ++;
} else if (SingleOpCodeExpression) {
//
// There are two cases to indicate the end of an Expression:
// for single OpCode expression: one Expression OpCode
// for expression consists of more than one OpCode: EFI_IFR_END
//
SingleOpCodeExpression = FALSE;
if (mInScopeDisable && (CurrentForm == NULL)) {
//
// This is DisableIf expression for Form, it should be a constant expression
//
ConstantFlag = TRUE;
Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression, &ConstantFlag);
if (EFI_ERROR (Status)) {
return Status;
}
if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
return EFI_INVALID_PARAMETER;
}
if (!ConstantFlag) {
StringPrint ("WARNING. The DisableIf expression for Form should be a constant expression.\n");
}
OpCodeDisabled = CurrentExpression->Result.Value.b;
}
CurrentExpression = NULL;
}
continue;
}
//
// Parse the Opcode
//
switch (Operand) {
case EFI_IFR_FORM_SET_OP:
CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
CopyMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
//
// The formset OpCode contains ClassGuid
//
FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
}
FormSet->FormSetOrder = ++mFormSetOrderParse;
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
//
// Create a new Form for this FormSet
//
CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
ASSERT (CurrentForm != NULL);
CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
InitializeListHead (&CurrentForm->ExpressionListHead);
InitializeListHead (&CurrentForm->StatementListHead);
CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
if (InScopeFormSuppress) {
//
// Form is inside of suppressif
//
CurrentForm->SuppressExpression = FormSuppressExpression;
}
if (Scope != 0) {
//
// Enter scope of a Form, suppressif will be used for Question or Option
//
SuppressForQuestion = TRUE;
}
//
// Insert into Form list of this FormSet
//
InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
break;
//
// Storage
//
case EFI_IFR_VARSTORE_OP:
//
// Create a buffer Storage for this FormSet
//
Storage = CreateStorage (FormSet);
Storage->Type = EFI_IFR_VARSTORE_OP;
CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
Storage->Buffer = AllocateZeroPool (Storage->Size);
AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
Storage->Name = AllocateZeroPool ((strlen (AsciiString) + 1) * 2);
ASSERT (Storage->Name != NULL);
for (Index = 0; AsciiString[Index] != 0; Index++) {
Storage->Name[Index] = (CHAR16) AsciiString[Index];
}
Storage->FormSetOrder = mFormSetOrderParse;
//
// If not existed the same variable in StorageList, insert the new one. Or else, use the old one.
// If these two variales have the same Guid name but different size, report an error.
//
if ((TempStorage = NotSameVariableInVarList (FormSet->StorageListHead, Storage)) != NULL) {
if (Storage->Size != TempStorage->Size) {
StringPrint ("Error. Two modules found with VarStore variables with same name %S and GUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x, but with different sizes %d and %d.\n",
Storage->Name,
Storage->Guid.Data1,
Storage->Guid.Data2,
Storage->Guid.Data3,
Storage->Guid.Data4[0],
Storage->Guid.Data4[1],
Storage->Guid.Data4[2],
Storage->Guid.Data4[3],
Storage->Guid.Data4[4],
Storage->Guid.Data4[5],
Storage->Guid.Data4[6],
Storage->Guid.Data4[7],
Storage->Size,
TempStorage->Size
);
return EFI_ABORTED;
}
//
// Update the VarStoreId for current question to get the variable guid and name information
//
TempStorage->VarStoreId = Storage->VarStoreId;
TempStorage->FormSetOrder = Storage->FormSetOrder;
RemoveEntryList (&Storage->Link);
DestroyStorage(Storage);
}
break;
case EFI_IFR_VARSTORE_NAME_VALUE_OP:
//
// Create a name/value Storage for this FormSet
//
Storage = CreateStorage (FormSet);
Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
Storage->FormSetOrder = mFormSetOrderParse;
break;
case EFI_IFR_VARSTORE_EFI_OP:
//
// Create a EFI variable Storage for this FormSet
//
Storage = CreateStorage (FormSet);
Storage->Type = EFI_IFR_VARSTORE_EFI_OP;
CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
//
// Check whether the EfiVarStore before UEFI2.31 or not
//
Storage->Size = sizeof (EFI_IFR_VARSTORE_EFI_OLD);
if (((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Header.Length == sizeof (EFI_IFR_VARSTORE_EFI_OLD)) {
Storage->NewEfiVarstore = FALSE;
Storage->Size = 0;
Storage->Buffer = NULL;
Storage->Name = NULL;
Storage->Size = 0;
} else {
//
// EfiVarStore structure for UEFI2.31
//
Storage->NewEfiVarstore = TRUE;
CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size, sizeof (UINT16));
Storage->Buffer = AllocateZeroPool (Storage->Size);
AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;
Storage->Name = AllocateZeroPool ((strlen (AsciiString) + 1) * 2);
ASSERT (Storage->Name != NULL);
for (Index = 0; AsciiString[Index] != 0; Index++) {
Storage->Name[Index] = (CHAR16) AsciiString[Index];
}
}
Storage->FormSetOrder = mFormSetOrderParse;
//
// If not existed the same variable in StorageList, insert the new one. Or else, use the old one.
// If these two variales have the same Guid name but different size, report an error.
//
if ((TempStorage = NotSameVariableInVarList (FormSet->StorageListHead, Storage)) != NULL) {
if (Storage->Size != TempStorage->Size) {
StringPrint ("Error. Two modules found with EfiVarStore variables with same name %S and GUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x, but different sizes %d and %d.\n",
Storage->Name,
Storage->Guid.Data1,
Storage->Guid.Data2,
Storage->Guid.Data3,
Storage->Guid.Data4[0],
Storage->Guid.Data4[1],
Storage->Guid.Data4[2],
Storage->Guid.Data4[3],
Storage->Guid.Data4[4],
Storage->Guid.Data4[5],
Storage->Guid.Data4[6],
Storage->Guid.Data4[7],
Storage->Size,
TempStorage->Size
);
return EFI_ABORTED;
}
//
// Update the VarStoreId for current question to get the variable guid and name information
//
TempStorage->VarStoreId = Storage->VarStoreId;
TempStorage->FormSetOrder = Storage->FormSetOrder;
RemoveEntryList (&Storage->Link);
DestroyStorage( Storage);
}
break;
//
// DefaultStore
//
case EFI_IFR_DEFAULTSTORE_OP:
HaveInserted = FALSE;
DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
ASSERT (DefaultStore != NULL);
DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
//
// Insert it to the DefaultStore list of this Formset with ascending order.
//
if (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
PreDefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
if (DefaultStore->DefaultId < PreDefaultStore->DefaultId) {
InsertTailList (&PreDefaultStore->Link, &DefaultStore->Link);
HaveInserted = TRUE;
break;
}
}
}
if (!HaveInserted) {
InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
}
break;
//
// Statements
//
case EFI_IFR_SUBTITLE_OP:
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
if (Scope != 0) {
mInScopeSubtitle = TRUE;
}
break;
case EFI_IFR_TEXT_OP:
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
break;
case EFI_IFR_RESET_BUTTON_OP:
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
break;
//
// Questions
//
case EFI_IFR_ACTION_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
//
// No need to deal with the EFI_IFR_ACTION
//
break;
case EFI_IFR_REF_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
Value = &CurrentStatement->HiiValue;
Value->Type = EFI_IFR_TYPE_REF;
if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
}
}
}
}
CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
break;
case EFI_IFR_ONE_OF_OP:
case EFI_IFR_NUMERIC_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT(CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
Value = &CurrentStatement->HiiValue;
if (BitFieldStorage) {
//
// Get the bit var store info (bit/byte offset, bit/byte offset)
//
CurrentStatement->QuestionReferToBitField = TRUE;
CurrentStatement->BitStorageWidth = CurrentStatement->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;
CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;
TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;
CurrentStatement->StorageWidth = (TotalBits % 8 == 0? TotalBits / 8: TotalBits / 8 + 1);
//
// Get the Minimum/Maximum/Step value(Note: bit field type has been stored as UINT32 type)
//
CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue;
CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue;
CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step;
} else {
switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
case EFI_IFR_NUMERIC_SIZE_1:
CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
break;
case EFI_IFR_NUMERIC_SIZE_2:
CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
break;
case EFI_IFR_NUMERIC_SIZE_4:
CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
break;
case EFI_IFR_NUMERIC_SIZE_8:
CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
break;
default:
break;
}
}
if ((Operand == EFI_IFR_ONE_OF_OP) && (Scope != 0)) {
SuppressForOption = TRUE;
}
//
// Get the UQI information
//
PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
//
// Exchange the Guid and name information between VarList and Question List
//
Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
//
// Remove the question which isn't stored by EfiVarStore or VarStore
//
if (EFI_ERROR (Status)) {
RemoveEntryList (&CurrentStatement->Link);
DestroyStatement (FormSet, CurrentStatement);
}
break;
case EFI_IFR_ORDERED_LIST_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT(CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
CurrentStatement->BufferValue = NULL;
if (Scope != 0) {
SuppressForOption = TRUE;
}
//
// Get the UQI information
//
PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
//
// Exchange the Guid and name information between VarList and Question List
//
Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
//
// Remove the question which isn't stored by EfiVarStore or VarStore
//
if (EFI_ERROR (Status)) {
RemoveEntryList (&CurrentStatement->Link);
DestroyStatement (FormSet, CurrentStatement);
}
break;
case EFI_IFR_CHECKBOX_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT(CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
if (BitFieldStorage) {
//
// Get the bit var store info (bit/byte offset, bit/byte width)
//
CurrentStatement->QuestionReferToBitField = TRUE;
CurrentStatement->BitStorageWidth = 1;
CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;
CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;
TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;
CurrentStatement->StorageWidth = (TotalBits % 8 == 0? TotalBits / 8: TotalBits / 8 + 1);
}
//
// Get the UQI information
//
PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
//
// Exchange the Guid and name information between VarList and Question List
//
Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
//
// Remove the question which isn't stored by EfiVarStore or VarStore
//
if (EFI_ERROR (Status)) {
RemoveEntryList (&CurrentStatement->Link);
DestroyStatement (FormSet, CurrentStatement);
}
break;
case EFI_IFR_STRING_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
//
// MinSize is the minimum number of characters that can be accepted for this opcode,
// MaxSize is the maximum number of characters that can be accepted for this opcode.
// The characters are stored as Unicode, so the storage width should multiply 2.
//
CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
//
// Get the UQI information
//
PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
//
// Exchange the Guid and name information between VarList and Question List
//
Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
//
// Remove the question which isn't stored by EfiVarStore or VarStore
//
if (EFI_ERROR (Status)) {
RemoveEntryList (&CurrentStatement->Link);
DestroyStatement (FormSet, CurrentStatement);
}
break;
case EFI_IFR_PASSWORD_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
//
// MinSize is the minimum number of characters that can be accepted for this opcode,
// MaxSize is the maximum number of characters that can be accepted for this opcode.
// The characters are stored as Unicode, so the storage width should multiply 2.
//
CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
break;
case EFI_IFR_DATE_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT(CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
} else {
//
// Don't assign storage for RTC type of date/time
//
CurrentStatement->Storage = NULL;
CurrentStatement->StorageWidth = 0;
}
break;
case EFI_IFR_TIME_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT(CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
} else {
//
// Don't assign storage for RTC type of date/time
//
CurrentStatement->Storage = NULL;
CurrentStatement->StorageWidth = 0;
}
break;
//
// Default
//
case EFI_IFR_DEFAULT_OP:
//
// EFI_IFR_DEFAULT appear in scope of a Question,
// It creates a default value for the current question.
// A Question may have more than one Default value which have different default types.
//
CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
ASSERT (CurrentDefault != NULL);
CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {
CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF(EFI_IFR_DEFAULT, Value));
CurrentDefault->Value.Buffer = FceAllocateCopyPool(CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *)OpCodeData)->Value);
ASSERT(CurrentDefault->Value.Buffer != NULL);
} else {
CopyMem(&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *)OpCodeData)->Value, OpCodeLength - OFFSET_OF(EFI_IFR_DEFAULT, Value));
ExtendValueToU64(&CurrentDefault->Value);
}
//
// Insert to Default Value list of current Question
//
InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
if (Scope != 0) {
InScopeDefault = TRUE;
}
break;
//
// Option
//
case EFI_IFR_ONE_OF_OPTION_OP:
ASSERT (CurrentStatement != NULL);
if (CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP &&
((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0)) {
//
// It's keep the default value for ordered list opcode.
//
CurrentDefault = AllocateZeroPool(sizeof (QUESTION_DEFAULT));
ASSERT(CurrentDefault != NULL);
CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;
if ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
} else {
CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
}
CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value));
CurrentDefault->Value.Buffer = FceAllocateCopyPool(CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value);
ASSERT(CurrentDefault->Value.Buffer != NULL);
//
// Insert to Default Value list of current Question
//
InsertTailList(&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
break;
}
//
// EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
// It create a selection for use in current Question.
//
CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
ASSERT (CurrentOption != NULL);
CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
ExtendValueToU64 (&CurrentOption->Value);
if (InScopeOptionSuppress) {
CurrentOption->SuppressExpression = OptionSuppressExpression;
}
//
// Insert to Option list of current Question
//
InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
//
// Now we know the Storage width of nested Ordered List
//
if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) {
Width = 1;
switch (CurrentOption->Value.Type) {
case EFI_IFR_TYPE_NUM_SIZE_8:
Width = 1;
break;
case EFI_IFR_TYPE_NUM_SIZE_16:
Width = 2;
break;
case EFI_IFR_TYPE_NUM_SIZE_32:
Width = 4;
break;
case EFI_IFR_TYPE_NUM_SIZE_64:
Width = 8;
break;
default:
//
// Invalid type for Ordered List
//
break;
}
CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width);
CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
CurrentStatement->ValueType = CurrentOption->Value.Type;
if (CurrentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
CurrentStatement->HiiValue.Buffer = CurrentStatement->BufferValue;
CurrentStatement->HiiValue.BufferLen = CurrentStatement->StorageWidth;
}
}
break;
//
// Conditional
//
case EFI_IFR_NO_SUBMIT_IF_OP:
case EFI_IFR_INCONSISTENT_IF_OP:
//
// Create an Expression node
//
CurrentExpression = CreateExpression (CurrentForm);
CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
} else {
CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
}
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_WARNING_IF_OP:
//
// Create an Expression node
//
CurrentExpression = CreateExpression (CurrentForm);
CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));
CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;
CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF;
InsertTailList (&CurrentStatement->WarningListHead, &CurrentExpression->Link);
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_SUPPRESS_IF_OP:
//
// Question and Option will appear in scope of this OpCode
//
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
if (CurrentForm == NULL) {
InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
} else {
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
}
if (SuppressForOption) {
InScopeOptionSuppress = TRUE;
OptionSuppressExpression = CurrentExpression;
} else if (SuppressForQuestion) {
mInScopeSuppress = TRUE;
mSuppressExpression = CurrentExpression;
} else {
InScopeFormSuppress = TRUE;
FormSuppressExpression = CurrentExpression;
}
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_GRAY_OUT_IF_OP:
//
// Questions will appear in scope of this OpCode
//
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
mInScopeGrayOut = TRUE;
mGrayOutExpression = CurrentExpression;
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_DISABLE_IF_OP:
//
// The DisableIf expression should only rely on constant, so it could be
// evaluated at initialization and it will not be queued
//
CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
ASSERT (CurrentExpression != NULL);
CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
InitializeListHead (&CurrentExpression->OpCodeListHead);
if (CurrentForm != NULL) {
//
// This is DisableIf for Question, enqueue it to Form expression list
//
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
}
mDisableExpression = CurrentExpression;
mInScopeDisable = TRUE;
OpCodeDisabled = FALSE;
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
//
// Expression
//
case EFI_IFR_VALUE_OP:
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
if (InScopeDefault) {
//
// Used for default (EFI_IFR_DEFAULT)
//
CurrentDefault->ValueExpression = CurrentExpression;
} else {
//
// If used for a question, then the question will be read-only
//
//
// Make sure CurrentStatement is not NULL.
// If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
// file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
//
ASSERT (CurrentStatement != NULL);
CurrentStatement->ValueExpression = CurrentExpression;
}
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_RULE_OP:
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_READ_OP:
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
//
// Make sure CurrentStatement is not NULL.
// If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
// file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
//
ASSERT (CurrentStatement != NULL);
CurrentStatement->ReadExpression = CurrentExpression;
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_WRITE_OP:
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
//
// Make sure CurrentStatement is not NULL.
// If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
// file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
//
ASSERT (CurrentStatement != NULL);
CurrentStatement->WriteExpression = CurrentExpression;
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
//
// Image
//
case EFI_IFR_IMAGE_OP:
//
// Get ScopeOpcode from top of stack
//
PopScope (&ScopeOpCode);
PushScope (ScopeOpCode);
switch (ScopeOpCode) {
case EFI_IFR_FORM_SET_OP:
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
ASSERT (CurrentForm != NULL);
break;
case EFI_IFR_ONE_OF_OPTION_OP:
break;
default:
//
// Make sure CurrentStatement is not NULL.
// If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
// file is wrongly generated by tools such as VFR Compiler.
//
ASSERT (CurrentStatement != NULL);
break;
}
break;
//
// Refresh
//
case EFI_IFR_REFRESH_OP:
break;
//
// Refresh guid.
//
case EFI_IFR_REFRESH_ID_OP:
break;
//
// Modal tag
//
case EFI_IFR_MODAL_TAG_OP:
break;
//
// Vendor specific
//
case EFI_IFR_GUID_OP:
if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarGuid)==0) {
Scope = 0;
BitFieldStorage = TRUE;
}
break;
//
// Scope End
//
case EFI_IFR_END_OP:
BitFieldStorage = FALSE;
Status = PopScope (&ScopeOpCode);
if (EFI_ERROR (Status)) {
ResetScopeStack ();
return Status;
}
switch (ScopeOpCode) {
case EFI_IFR_FORM_SET_OP:
//
// End of FormSet, update FormSet IFR binary length
// to stop parsing substantial OpCodes
//
FormSet->IfrBinaryLength = OpCodeOffset;
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
//
// End of Form
//
CurrentForm = NULL;
SuppressForQuestion = FALSE;
break;
case EFI_IFR_ONE_OF_OPTION_OP:
//
// End of Option
//
CurrentOption = NULL;
break;
case EFI_IFR_SUBTITLE_OP:
mInScopeSubtitle = FALSE;
break;
case EFI_IFR_NO_SUBMIT_IF_OP:
case EFI_IFR_INCONSISTENT_IF_OP:
case EFI_IFR_WARNING_IF_OP:
//
// Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
//
break;
case EFI_IFR_SUPPRESS_IF_OP:
if (SuppressForOption) {
InScopeOptionSuppress = FALSE;
} else if (SuppressForQuestion) {
mInScopeSuppress = FALSE;
} else {
InScopeFormSuppress = FALSE;
}
break;
case EFI_IFR_GRAY_OUT_IF_OP:
mInScopeGrayOut = FALSE;
break;
case EFI_IFR_DISABLE_IF_OP:
mInScopeDisable = FALSE;
OpCodeDisabled = FALSE;
break;
case EFI_IFR_ONE_OF_OP:
case EFI_IFR_ORDERED_LIST_OP:
SuppressForOption = FALSE;
break;
case EFI_IFR_DEFAULT_OP:
InScopeDefault = FALSE;
break;
case EFI_IFR_MAP_OP:
//
// Get current Map Expression List.
//
Status = PopMapExpressionList ((VOID **) &MapExpressionList);
if (Status == EFI_ACCESS_DENIED) {
MapExpressionList = NULL;
}
//
// Get current expression.
//
Status = PopCurrentExpression ((VOID **) &CurrentExpression);
ASSERT (!EFI_ERROR (Status));
ASSERT (MapScopeDepth > 0);
MapScopeDepth --;
break;
default:
if (IsExpressionOpCode (ScopeOpCode)) {
if (mInScopeDisable && (CurrentForm == NULL)) {
//
// This is DisableIf expression for Form, it should be a constant expression
//
ASSERT (CurrentExpression != NULL);
ConstantFlag = TRUE;
Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression, &ConstantFlag);
if (EFI_ERROR (Status)) {
return Status;
}
if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
return EFI_INVALID_PARAMETER;
}
if (!ConstantFlag) {
StringPrint ("WARNING. The DisableIf expression for Form should be a constant expression.\n");
}
OpCodeDisabled = CurrentExpression->Result.Value.b;
//
// DisableIf Expression is only used once and not queued, free it
//
DestroyExpression (CurrentExpression);
}
//
// End of current Expression
//
CurrentExpression = NULL;
}
break;
}
break;
default:
break;
}
}
return EFI_SUCCESS;
}
/**
Search an Option of a Question by its value.
@param Question The Question
@param OptionValue Value for Option to be searched.
@retval Pointer Pointer to the found Option.
@retval NULL Option not found.
**/
QUESTION_OPTION *
ValueToOption (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_STATEMENT *Question,
IN EFI_HII_VALUE *OptionValue
)
{
LIST_ENTRY *Link;
QUESTION_OPTION *Option;
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
Option = QUESTION_OPTION_FROM_LINK (Link);
if (CompareHiiValue (&Option->Value, OptionValue, FormSet) == 0) {
return Option;
}
Link = GetNextNode (&Question->OptionListHead, Link);
}
return NULL;
}
/**
Set value of a data element in an Array by its Index.
@param Array The data array.
@param Type Type of the data in this array.
@param Index Zero based index for data in this array.
@param Value The value to be set.
**/
VOID
SetArrayData (
IN VOID *Array,
IN UINT8 Type,
IN UINTN Index,
IN UINT64 Value
)
{
ASSERT (Array != NULL);
switch (Type) {
case EFI_IFR_TYPE_NUM_SIZE_8:
*(((UINT8 *) Array) + Index) = (UINT8) Value;
break;
case EFI_IFR_TYPE_NUM_SIZE_16:
*(((UINT16 *) Array) + Index) = (UINT16) Value;
break;
case EFI_IFR_TYPE_NUM_SIZE_32:
*(((UINT32 *) Array) + Index) = (UINT32) Value;
break;
case EFI_IFR_TYPE_NUM_SIZE_64:
*(((UINT64 *) Array) + Index) = (UINT64) Value;
break;
default:
break;
}
}
/**
Reset Question of five kinds to its default value.
@param FormSet The form set.
@param Form The form.
@param Question The question.
@param DefaultId The default Id.
@param DefaultId The platform Id.
@retval EFI_SUCCESS Question is reset to default value.
**/
EFI_STATUS
GetQuestionDefault (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form,
IN FORM_BROWSER_STATEMENT *Question,
IN UINT16 DefaultId,
IN UINT64 PlatformId
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
QUESTION_DEFAULT *Default;
QUESTION_OPTION *Option;
EFI_HII_VALUE *HiiValue;
UINT8 Index;
FORMSET_STORAGE *VarList;
UINT8 *VarBuffer;
BOOLEAN ConstantFlag;
UINT16 OriginalDefaultId;
FORMSET_DEFAULTSTORE *DefaultStore;
LIST_ENTRY *DefaultLink;
CHAR16 *VarDefaultName;
VarDefaultName = NULL;
Status = EFI_SUCCESS;
ConstantFlag = TRUE;
OriginalDefaultId = DefaultId;
DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
//
// Statement don't have storage, skip them
//
if (Question->QuestionId == 0) {
return EFI_NOT_FOUND;
}
//
// Return if no any kinds of
//
if ((Question->Operand != EFI_IFR_CHECKBOX_OP)
&& (Question->Operand != EFI_IFR_ONE_OF_OP)
&& (Question->Operand != EFI_IFR_ORDERED_LIST_OP)
&& (Question->Operand != EFI_IFR_NUMERIC_OP)
&& (Question->Operand != EFI_IFR_STRING_OP)
) {
return EFI_ABORTED;
}
//
// Search the variable for this question (Compatible with the old EfiVarStore before UEFI2.31)
//
//
//VarStoreInfoDepending on the type of variable store selected,
//this contains either a 16-bit Buffer Storage offset (VarOffset)
//or a Name/Value or EFI Variable name (VarName).
//
Status = SearchVarStorage (
Question,
NULL,
Question->VarStoreInfo.VarOffset,
FormSet->StorageListHead,
(CHAR8 **)&VarBuffer,
&VarList
);
if (EFI_ERROR(Status)) {
return Status;
}
//
// There are three ways to specify default value for a Question:
// 1, use nested EFI_IFR_DEFAULT
// 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
// 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
//
ReGetDefault:
HiiValue = &Question->HiiValue;
//
// EFI_IFR_DEFAULT has highest priority
//
if (!IsListEmpty (&Question->DefaultListHead)) {
Link = GetFirstNode (&Question->DefaultListHead);
while (!IsNull (&Question->DefaultListHead, Link)) {
Default = QUESTION_DEFAULT_FROM_LINK (Link);
if (Default->DefaultId == DefaultId) {
if (Default->ValueExpression != NULL) {
//
// Default is provided by an Expression, evaluate it
//
Status = EvaluateExpression (FormSet, Form, Default->ValueExpression, &ConstantFlag);
if (EFI_ERROR (Status)) {
return Status;
}
if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {
CopyMem(Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);
Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;
} else {
CopyMem(Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);
Question->HiiValue.BufferLen = Question->StorageWidth;
}
FreePool(Default->ValueExpression->Result.Buffer);
}
HiiValue->Type = Default->ValueExpression->Result.Type;
CopyMem(&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
} else {
//
// Default value is embedded in EFI_IFR_DEFAULT
//
if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
CopyMem(HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);
} else {
CopyMem(HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
}
}
if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
CopyMem(VarBuffer, HiiValue->Buffer, HiiValue->BufferLen);
} else if (HiiValue->Type == EFI_IFR_TYPE_STRING){
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
HiiValue->Value.string,
EN_US,
&VarDefaultName
);
if (VarDefaultName == NULL) {
return EFI_NOT_FOUND;
}
if (Question->StorageWidth > FceStrSize(VarDefaultName)) {
ZeroMem (VarBuffer, Question->StorageWidth);
CopyMem (VarBuffer, VarDefaultName, FceStrSize(VarDefaultName));
} else {
CopyMem (VarBuffer, VarDefaultName, Question->StorageWidth);
}
} else {
if (Question->QuestionReferToBitField) {
SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
} else {
CopyMem(VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
}
}
return EFI_SUCCESS;
}
if (Default->DefaultId == DefaultId) {
return EFI_SUCCESS;
}
Link = GetNextNode (&Question->DefaultListHead, Link);
}
}
if (HiiValue->Buffer == NULL) {
ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
}
//
// EFI_ONE_OF_OPTION
//
if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
//
// OneOfOption could only provide Standard and Manufacturing default
//
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
Option = QUESTION_OPTION_FROM_LINK (Link);
if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
) {
CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
if (Question->QuestionReferToBitField) {
SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
} else {
CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
}
return EFI_SUCCESS;
}
Link = GetNextNode (&Question->OptionListHead, Link);
}
}
}
//
// EFI_IFR_CHECKBOX - lowest priority
//
if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
//
// Checkbox could only provide Standard and Manufacturing default
//
if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
) {
HiiValue->Value.b = TRUE;
if (Question->QuestionReferToBitField) {
SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
} else {
CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
}
return EFI_SUCCESS;
}
}
}
//
// For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
// If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
// The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
//
while (!IsNull(&FormSet->DefaultStoreListHead, DefaultLink)) {
DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead,DefaultLink);
DefaultId = DefaultStore->DefaultId;
if (DefaultId == OriginalDefaultId) {
continue;
}
goto ReGetDefault;
}
//
// For Questions without default
//
Status = EFI_NOT_FOUND;
switch (Question->Operand) {
case EFI_IFR_CHECKBOX_OP:
HiiValue->Value.b = FALSE;
if (Question->QuestionReferToBitField) {
SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
} else {
CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
}
break;
case EFI_IFR_NUMERIC_OP:
//
// Take minimum value as numeric default value
//
if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {
HiiValue->Value.u64 = Question->Minimum;
if (Question->QuestionReferToBitField) {
SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
} else {
CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
}
return EFI_SUCCESS;
}
break;
case EFI_IFR_ONE_OF_OP:
//
// Take first oneof option as oneof's default value
//
if (ValueToOption (FormSet, Question, HiiValue) == NULL) {
Link = GetFirstNode (&Question->OptionListHead);
if (!IsNull (&Question->OptionListHead, Link)) {
Option = QUESTION_OPTION_FROM_LINK (Link);
CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
if (Question->QuestionReferToBitField) {
SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
} else {
CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
}
return EFI_SUCCESS;
}
}
break;
case EFI_IFR_ORDERED_LIST_OP:
//
// Take option sequence in IFR as ordered list's default value
//
Index = 0;
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
Option = QUESTION_OPTION_FROM_LINK (Link);
SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);
SetArrayData (VarBuffer, Question->ValueType, Index, Option->Value.Value.u64);
Index++;
if (Index >= Question->MaxContainers) {
break;
}
Link = GetNextNode (&Question->OptionListHead, Link);
}
break;
default:
break;
}
return EFI_SUCCESS;
}
/**
Set the value to the variable of platformId question.
@param PlatformId The form set.
@retval EFI_SUCCESS Set successfully.
**/
EFI_STATUS
AssignThePlatformId (
IN UINT64 PlatformId
)
{
EFI_STATUS Status;
FORMSET_STORAGE *VarList;
UINT8 *VarBuffer;
Status = EFI_SUCCESS;
VarBuffer = NULL;
//
// Set the Storage
//
Status = SearchVarStorage (
&mMultiPlatformParam.PlatformIdQuestion,
NULL,
mMultiPlatformParam.PlatformIdQuestion.VarStoreInfo.VarOffset,
&mVarListEntry,
(CHAR8 **)&VarBuffer,
&VarList
);
if (EFI_ERROR(Status)) {
return Status;
}
CopyMem (VarBuffer, &PlatformId, mMultiPlatformParam.PlatformIdWidth);
//
// Set the HIIvalue of this questions
//
CopyMem (&mMultiPlatformParam.Question->HiiValue.Value.u64, &PlatformId, mMultiPlatformParam.PlatformIdWidth);
switch (mMultiPlatformParam.PlatformIdWidth) {
case sizeof (UINT8):
mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
break;
case sizeof (UINT16):
mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_16;
break;
case sizeof (UINT32):
mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_32;
break;
case sizeof (UINT64):
mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_64;
break;
default:
mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_64;
}
return EFI_SUCCESS;
}
/**
Reset Questions to their default value in a Form, Formset or System.
@param FormSet FormSet data structure.
@param Form Form data structure.
@param DefaultId The default Id
@param PlatformId The platform Id
@param SettingScope Setting Scope for Default action.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_UNSUPPORTED Unsupport SettingScope.
**/
EFI_STATUS
ExtractDefault (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form,
IN UINT16 DefaultId,
IN UINT64 PlatformId,
IN BROWSER_SETTING_SCOPE SettingScope
)
{
EFI_STATUS Status;
LIST_ENTRY *FormLink;
LIST_ENTRY *Link;
LIST_ENTRY *FormSetEntryListHead;
FORM_BROWSER_STATEMENT *Question;
//
// Check the supported setting level.
//
if (SettingScope >= MaxLevel) {
return EFI_UNSUPPORTED;
}
if (SettingScope == FormLevel) {
//
// Extract Form default
//
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Link = GetNextNode (&Form->StatementListHead, Link);
//
// Re-set the platformId before calcuate the platformId of every question to avoid over-written.
//
if (mMultiPlatformParam.MultiPlatformOrNot) {
Status = AssignThePlatformId (PlatformId);
if (EFI_ERROR (Status)) {
StringPrint ("Error. Failed to assign the platformId.\n");
return Status;
}
}
//
// Reset Question to its default value, and store the default to variable
//
Status = GetQuestionDefault (FormSet, Form, Question, DefaultId, PlatformId);
if (EFI_ERROR (Status)) {
continue;
}
}
} else if (SettingScope == FormSetLevel) {
FormLink = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, FormLink)) {
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
ExtractDefault (FormSet, Form, DefaultId, PlatformId, FormLevel);
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
}
} else if (SettingScope == SystemLevel) {
//
// Parse Fromset one by one
//
FormSetEntryListHead = &mFormSetListEntry;
FormLink = GetFirstNode (FormSetEntryListHead);
while (!IsNull (FormSetEntryListHead, FormLink)) {
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormLink);
ExtractDefault (FormSet, NULL, DefaultId, PlatformId, FormSetLevel);
FormLink = GetNextNode (FormSetEntryListHead, FormLink);
}
}
return EFI_SUCCESS;
}
/**
Check whether existed the UQI in Current Unicode String.
@param UniPackge A pointer to a Null-terminated Unicode string Array.
@return TRUE If find the uqi, return TRUE
@return FALSE Otherwise, return FALSE
**/
static
BOOLEAN
IsUqiOrNot (
IN UINT8 *UniPackge
)
{
CHAR8 *UniBin;
UINTN UniLength;
UINTN Index;
BOOLEAN FindIt;
UniBin = (CHAR8 *) UniPackge + 4;
Index = 4;
FindIt = FALSE;
UniLength = *(UINT32 *) UniPackge;
if (((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
//
// Search the uqi language
//
while ((Index < UniLength) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS){
if (!strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "uqi")) {
FindIt = TRUE;
break;
}
Index = Index + ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
}
}
return FindIt;
}
/**
Returns Length of UQI string (in CHAR16) (not including null termination).
@param UniPackge A pointer to a UQI string.
@return Number Length of UQIL string (in words) or 0
**/
static
UINT16
GetUqiNum (
IN CHAR16 *UniString
)
{
UINT16 Number;
if (UniString == NULL) {
return 0;
}
for (Number = 0; UniString[Number] != 0; Number++) {
;
}
return Number;
}
/**
Print the formset title information.
@param FormSet The pointer to the formset.
@return NULL.
**/
static
VOID
StringPrintormSetTitle (
IN FORM_BROWSER_FORMSET *FormSet
)
{
CHAR16 *VarDefaultName;
EFI_STATUS Status;
VarDefaultName = NULL;
StringPrint("\n\n// Form Set: ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
FormSet->FormSetTitle,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n// %s",FORM_SET_GUID_PREFIX);
StringPrint(
EFI_GUID_FORMAT,
FormSet->Guid.Data1, FormSet->Guid.Data2,
FormSet->Guid.Data3, FormSet->Guid.Data4[0],
FormSet->Guid.Data4[1],FormSet->Guid.Data4[2],
FormSet->Guid.Data4[3],FormSet->Guid.Data4[4],
FormSet->Guid.Data4[5],FormSet->Guid.Data4[6],
FormSet->Guid.Data4[7]);
StringPrint("\n");
if (&(FormSet->EnUsStringList) == NULL && VarDefaultName != NULL && FormSet->FormSetTitle != 0) {
free (VarDefaultName);
VarDefaultName = NULL;
}
}
/**
Print the formset title information.
@param FormSet The pointer to the formset.
@param Question The pointer to the question of ONE_OF.
@return NULL.
**/
static
EFI_STATUS
PrintOneOfOptions (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_STATEMENT *Question
)
{
LIST_ENTRY *Link;
QUESTION_OPTION *Option;
CHAR16 *VarDefaultName;
EFI_STATUS Status;
Status = EFI_SUCCESS;
VarDefaultName = NULL;
if ((Question->Operand != EFI_IFR_ONE_OF_OP)
&& (Question->Operand != EFI_IFR_ORDERED_LIST_OP)
) {
return EFI_ABORTED;
}
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
Option = QUESTION_OPTION_FROM_LINK (Link);
if (Question->QuestionReferToBitField) {
StringPrint("// %08X = ", Option->Value.Value.u32);
} else {
switch(Option->Value.Type) {
case EFI_IFR_TYPE_NUM_SIZE_8:
StringPrint("// %02X = ", Option->Value.Value.u8);
break;
case EFI_IFR_TYPE_NUM_SIZE_16:
StringPrint("// %04X = ", Option->Value.Value.u16);
break;
case EFI_IFR_TYPE_NUM_SIZE_32:
StringPrint("// %08X = ", Option->Value.Value.u32);
break;
case EFI_IFR_TYPE_NUM_SIZE_64:
StringPrint("// %016llX = ", Option->Value.Value.u64);
break;
case EFI_IFR_TYPE_BOOLEAN:
StringPrint("// %X = ", Option->Value.Value.b);
break;
case EFI_IFR_TYPE_STRING:
StringPrint("// %X = ", Option->Value.Value.string);
break;
default:
break;
}
}
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Option->Text,
EN_US,
&VarDefaultName
);
LogUnicodeString (VarDefaultName);
StringPrint("\n");
if (&(FormSet->EnUsStringList) == NULL && VarDefaultName != NULL && Option->Text != 0) {
free (VarDefaultName);
VarDefaultName = NULL;
}
Link = GetNextNode (&Question->OptionListHead, Link);
}
return Status;
}
/**
Print the form title information.
@param FormSet The pointer to the formset.
@param FormSet The pointer to the form.
@return NULL.
**/
static
VOID
StringPrintormTitle (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form
)
{
CHAR16 *VarDefaultName;
EFI_STATUS Status;
VarDefaultName = NULL;
StringPrint("\n// Form: ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Form->FormTitle,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n");
if (&(FormSet->EnUsStringList) == NULL && VarDefaultName != NULL && Form->FormTitle != 0) {
free (VarDefaultName);
VarDefaultName = NULL;
}
}
/**
Print the information of questions.
@param FormSet The pointer to the formset.
@param FormSet The pointer to the form.
@param Question The pointer to the question.
@param PrintOrNot Decide whether print or not.
@return NULL.
**/
static
VOID
PrintQuestion (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form,
IN FORM_BROWSER_STATEMENT *Question,
IN BOOLEAN PrintOrNot
)
{
EFI_STATUS Status;
CHAR16 *VarDefaultName;
UINT16 UqiStringLength;
BOOLEAN HaveUQIlanguage;
Status = EFI_SUCCESS;
VarDefaultName = NULL;
UqiStringLength = 0;
HaveUQIlanguage = IsUqiOrNot (FormSet->UnicodeBinary);
switch (Question->Operand) {
case EFI_IFR_SUBTITLE_OP:
if (PrintOrNot) {
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
if ((VarDefaultName != NULL) && (FceStrCmp (VarDefaultName, L"") != 0)) {
StringPrint("// Subtitle: ");
StringPrint("// ");
LogUnicodeString (VarDefaultName);
StringPrint("\n");
}
}
break;
case EFI_IFR_ONE_OF_OP:
if( HaveUQIlanguage ) {
Status = FindDefaultName (
&(FormSet->UqiStringList),
FormSet->UnicodeBinary,
Question->Prompt,
UQI,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
} else {
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
}
//
//Record the UQi to the Question
//
Question->Uqi.HexNum = UqiStringLength;
Question->Uqi.Data = VarDefaultName;
Question->Uqi.Type = ONE_OF;
if (PrintOrNot) {
StringPrint("ONE_OF ");
LogIfrValue (
FormSet,
Question
);
StringPrint(" // ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n");
//
// Print ONE_OF_OPTION
//
PrintOneOfOptions (FormSet, Question);
}
break;
case EFI_IFR_CHECKBOX_OP:
if( HaveUQIlanguage ) {
Status = FindDefaultName (
&(FormSet->UqiStringList),
FormSet->UnicodeBinary,
Question->Prompt,
UQI,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
} else {
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
}
//
//Record the UQi to the HiiObjList
//
Question->Uqi.HexNum = UqiStringLength;
Question->Uqi.Data = VarDefaultName;
Question->Uqi.Type = CHECKBOX;
if (PrintOrNot) {
StringPrint("CHECKBOX ");
LogIfrValue (
FormSet,
Question
);
StringPrint(" // ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n");
StringPrint("// 0 = Unchecked\n");
StringPrint("// 1 = Checked\n");
}
break;
case EFI_IFR_STRING_OP:
if( HaveUQIlanguage ) {
Status = FindDefaultName (
&(FormSet->UqiStringList),
FormSet->UnicodeBinary,
Question->Prompt,
UQI,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
} else {
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
}
//
//Record the UQi to the HiiObjList
//
Question->Uqi.HexNum = UqiStringLength;
Question->Uqi.Data = VarDefaultName;
Question->Uqi.Type = STRING;
if (PrintOrNot) {
StringPrint("STRING ");
LogIfrValueStr (
FormSet,
Question
);
StringPrint(" // ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n");
}
break;
case EFI_IFR_NUMERIC_OP:
if( HaveUQIlanguage ) {
Status = FindDefaultName (
&(FormSet->UqiStringList),
FormSet->UnicodeBinary,
Question->Prompt,
UQI,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
} else {
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
}
//
//Record the UQi to the HiiObjList
//
Question->Uqi.HexNum = UqiStringLength;
Question->Uqi.Data = VarDefaultName;
Question->Uqi.Type = NUMERIC;
if (PrintOrNot) {
StringPrint("NUMERIC ");
LogIfrValue (
FormSet,
Question
);
StringPrint(" // ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n");
if (Question->QuestionReferToBitField) {
StringPrint("// Minimum = %08llX \n", Question->Minimum);
StringPrint("// Maximum = %08llX \n", Question->Maximum);
StringPrint("// Step = %08llX \n", Question->Step);
} else {
switch (Question->StorageWidth) {
case sizeof (UINT8):
StringPrint("// Minimum = %02llX \n", Question->Minimum);
StringPrint("// Maximum = %02llX \n", Question->Maximum);
StringPrint("// Step = %02llX \n", Question->Step);
break;
case sizeof (UINT16):
StringPrint("// Minimum = %04llX \n", Question->Minimum);
StringPrint("// Maximum = %04llX \n", Question->Maximum);
StringPrint("// Step = %04llX \n", Question->Step);
break;
case sizeof (UINT32):
StringPrint("// Minimum = %08llX \n", Question->Minimum);
StringPrint("// Maximum = %08llX \n", Question->Maximum);
StringPrint("// Step = %08llX \n", Question->Step);
break;
case sizeof (UINT64):
StringPrint("// Minimum = %016llX \n", Question->Minimum);
StringPrint("// Maximum = %016llX \n", Question->Maximum);
StringPrint("// Step = %016llX \n", Question->Step);
break;
default:
StringPrint("0000 // Width > 16 is not supported -- FAILURE");
break;
}
}
}
break;
case EFI_IFR_ORDERED_LIST_OP:
if( HaveUQIlanguage ) {
Status = FindDefaultName (
&(FormSet->UqiStringList),
FormSet->UnicodeBinary,
Question->Prompt,
UQI,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
} else {
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
UqiStringLength = GetUqiNum (VarDefaultName);
if (PrintOrNot) {
if (UqiStringLength > 0) {
StringPrint("\nQ %04X ", UqiStringLength);
LogUqi(VarDefaultName);
} else {
StringPrint("\n// [No UQI] ");
}
}
}
//
//Record the UQi to the HiiObjList
//
Question->Uqi.HexNum = UqiStringLength;
Question->Uqi.Data = VarDefaultName;
Question->Uqi.Type = ORDERED_LIST;
if (PrintOrNot) {
StringPrint("ORDERED_LIST %04X ", Question->MaxContainers);
LogIfrValueList (
FormSet,
Question
);
StringPrint(" // ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Prompt,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n");
}
//
// Print ONE_OF_OPTION
//
PrintOneOfOptions (FormSet, Question);
break;
default:
break;
}
if (&(FormSet->EnUsStringList) == NULL &&VarDefaultName != NULL && Question->Prompt != 0) {
free (VarDefaultName);
VarDefaultName = NULL;
}
if (PrintOrNot && Question->Storage) {
StringPrint("// size = 0x%x", Question->StorageWidth);
StringPrint("\n// offset = 0x%x", Question->VarStoreInfo.VarOffset);
StringPrint("\n// name = ");
LogUnicodeString(Question->VariableName);
StringPrint("\n// guid = ");
StringPrint(
EFI_GUID_FORMAT,
Question->Guid.Data1, Question->Guid.Data2,
Question->Guid.Data3, Question->Guid.Data4[0],
Question->Guid.Data4[1],Question->Guid.Data4[2],
Question->Guid.Data4[3],Question->Guid.Data4[4],
Question->Guid.Data4[5],Question->Guid.Data4[6],
Question->Guid.Data4[7]
);
StringPrint("\n// attribute = 0x%x", Question->Attributes);
StringPrint("\n// help = ");
Status = FindDefaultName (
&(FormSet->EnUsStringList),
FormSet->UnicodeBinary,
Question->Help,
EN_US,
&VarDefaultName
);
assert (!EFI_ERROR (Status));
LogUnicodeString (VarDefaultName);
StringPrint("\n");
if (&(FormSet->EnUsStringList) == NULL &&VarDefaultName != NULL && Question->Help != 0) {
free (VarDefaultName);
VarDefaultName = NULL;
}
}
}
/**
Check whether current Formset or Form is NULL. If no valid questions, return FASLE.
@param FormSet The pointer to the formset.
@param FormSet The pointer to the form.
@param IsFormSet FormSet or Form.
@retval TRUE
@return FALSE
**/
BOOLEAN
CheckFormSetOrFormNull (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form,
IN BOOLEAN IsFormSet
)
{
LIST_ENTRY *FormLink;
FORM_BROWSER_STATEMENT *Question;
LIST_ENTRY *QuestionLink;
FormLink = NULL;
Question = NULL;
QuestionLink = NULL;
//
// Parse all forms in formset
//
if (IsFormSet) {
FormLink = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, FormLink)) {
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
//
// Parse five kinds of Questions in Form
//
QuestionLink = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, QuestionLink)) {
Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
//
// Parse five kinds of Questions in Form
//
if ((Question->Operand == EFI_IFR_ONE_OF_OP)
|| (Question->Operand == EFI_IFR_NUMERIC_OP)
|| (Question->Operand == EFI_IFR_CHECKBOX_OP)
|| (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
|| (Question->Operand == EFI_IFR_STRING_OP)
) {
if (mMultiPlatformParam.MultiPlatformOrNot) {
//
// Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode
//
if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) {
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
continue;
}
if (Question->Type == EFI_IFR_VARSTORE_EFI_OP
&& Question->NewEfiVarstore
&& ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
continue;
}
}
//
//If invalid variable type, skip it.
//
if ((Question->Type != EFI_IFR_VARSTORE_EFI_OP)
&& (Question->Type != EFI_IFR_VARSTORE_OP)) {
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
continue;
}
return TRUE;
}
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
}
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
}
} else {
//
// Parse five kinds of Questions in Form
//
QuestionLink = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, QuestionLink)) {
Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
//
// Parse five kinds of Questions in Form
//
if ((Question->Operand == EFI_IFR_ONE_OF_OP)
|| (Question->Operand == EFI_IFR_NUMERIC_OP)
|| (Question->Operand == EFI_IFR_CHECKBOX_OP)
|| (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
|| (Question->Operand == EFI_IFR_STRING_OP)
) {
if (mMultiPlatformParam.MultiPlatformOrNot) {
//
// Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode
//
if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) {
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
continue;
}
if ((Question->Type == EFI_IFR_VARSTORE_EFI_OP)
&& Question->NewEfiVarstore
&& ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
continue;
}
}
//
//If invalid variable type, skip it.
//
if ((Question->Type != EFI_IFR_VARSTORE_EFI_OP)
&& (Question->Type != EFI_IFR_VARSTORE_OP)) {
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
continue;
}
return TRUE;
}
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
}
}
return FALSE;
}
/**
Print all ONE_OF ORDER_LIST NUMERIC STRING and CHECKBOX in all fromsets.
@param Formset The pointer to the entry of the fromset list
@param Formset The pointer to the entry of the storage list
@retval EFI_SUCCESS It was complete successfully
@return EFI_ABORTED An error occurred
**/
EFI_STATUS
PrintInfoInAllFormset (
IN LIST_ENTRY *FormSetEntryListHead,
IN LIST_ENTRY *StorageEntryListHead
)
{
EFI_STATUS Status;
FORM_BROWSER_FORMSET *FormSet;
LIST_ENTRY *FormSetLink;
LIST_ENTRY *FormLink;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_STATEMENT *Question;
LIST_ENTRY *QuestionLink;
FORMSET_STORAGE *Storage;
CHAR8 *VarBuffer;
LIST_ENTRY *TempStorageLink;
UINT32 Index;
BOOLEAN Skip;
BOOLEAN ConstantFlag;
Status = EFI_SUCCESS;
FormSet = NULL;
FormSetLink = NULL;
FormLink = NULL;
Form = NULL;
Question = NULL;
QuestionLink = NULL;
Storage = NULL;
VarBuffer = NULL;
TempStorageLink = NULL;
Index = 0;
Skip = FALSE;
ConstantFlag = TRUE;
//
// Print platformId, defaultId and platformIdUqi
//
if (mMultiPlatformParam.MultiPlatformOrNot) {
StringPrint("\n\n// FCEKEY DEFAULT_ID:");
TempStorageLink = GetFirstNode (StorageEntryListHead);
Storage = FORMSET_STORAGE_FROM_LINK (TempStorageLink);
for (Index = 0; Index <= Storage->DefaultPlatformIdNum; Index++) {
StringPrint (" %4d", Storage->DefaultId[Index]);
}
StringPrint("\n\n//FCEKEY PLATFORM_ID:");
for (Index = 0; Index <= Storage->DefaultPlatformIdNum; Index++) {
StringPrint (" %4lld", Storage->PlatformId[Index]);
}
if (mMultiPlatformParam.Uqi.Data != NULL) {
StringPrint("\n\n//FCEKEY PLATFORM_UQI:");
StringPrint(" %04X ", mMultiPlatformParam.Uqi.HexNum);
LogUqi(mMultiPlatformParam.Uqi.Data);
}
}
FormSetLink = GetFirstNode (FormSetEntryListHead);
while (!IsNull (FormSetEntryListHead, FormSetLink)) {
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
//
//Assign the new storage list
//
FormSet->StorageListHead = StorageEntryListHead;
if (CheckFormSetOrFormNull (FormSet, NULL, TRUE)) {
StringPrintormSetTitle (FormSet);
} else {
FormSetLink = GetNextNode (FormSetEntryListHead, FormSetLink);
continue;
}
//
// Parse all forms in formset
//
FormLink = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, FormLink)) {
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
if (CheckFormSetOrFormNull (NULL, Form, FALSE)) {
StringPrintormTitle(FormSet,Form);
} else {
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
continue;
}
//
// Parse five kinds of Questions in Form
//
QuestionLink = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, QuestionLink)) {
Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
//
// Parse five kinds of Questions in Form
//
if ((Question->Operand == EFI_IFR_ONE_OF_OP)
|| (Question->Operand == EFI_IFR_NUMERIC_OP)
|| (Question->Operand == EFI_IFR_CHECKBOX_OP)
|| (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
|| (Question->Operand == EFI_IFR_SUBTITLE_OP)
|| (Question->Operand == EFI_IFR_STRING_OP)
) {
Skip = FALSE;
//
//Only output the questions stored by EFI_IFR_VARSTORE_EFI_OP.
//
if (mMultiPlatformParam.MultiPlatformOrNot
&& (Question->Operand != EFI_IFR_SUBTITLE_OP)
) {
Status = SearchVarStorage (
Question,
NULL,
Question->VarStoreInfo.VarOffset,
StorageEntryListHead,
(CHAR8 **)&VarBuffer,
&Storage
);
if (EFI_ERROR (Status)) {
Skip = TRUE;
}
}
//
// If Question is constant expression and "disabledIf True", don't output it.
//
ConstantFlag = TRUE;
if (!Skip && (Question->DisableExpression != NULL)) {
Status = EvaluateExpression (FormSet, Form, Question->DisableExpression, &ConstantFlag);
if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b && ConstantFlag) {
Skip = TRUE;
}
}
if (!Skip) {
PrintQuestion(FormSet, Form, Question, TRUE);
}
}
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
}
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
}
FormSetLink = GetNextNode (FormSetEntryListHead, FormSetLink);
}
return EFI_SUCCESS;
}