summaryrefslogtreecommitdiffstats
path: root/BaseTools/Source/C/FCE/IfrParse.c
diff options
context:
space:
mode:
authorShenglei Zhang <shenglei.zhang@intel.com>2019-05-28 16:07:43 +0800
committerLiming Gao <liming.gao@intel.com>2019-07-04 11:34:56 +0800
commit3c59d94637adbfdd497b5a2c16073c7dc62b669c (patch)
treea926e317184ec49ffad96d4a53f8a21bfc3a7705 /BaseTools/Source/C/FCE/IfrParse.c
parentdc7b0dc8d662b3bedece2cf1015e2a94884cb111 (diff)
downloadedk2-3c59d94637adbfdd497b5a2c16073c7dc62b669c.tar.gz
edk2-3c59d94637adbfdd497b5a2c16073c7dc62b669c.tar.bz2
edk2-3c59d94637adbfdd497b5a2c16073c7dc62b669c.zip
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>
Diffstat (limited to 'BaseTools/Source/C/FCE/IfrParse.c')
-rw-r--r--BaseTools/Source/C/FCE/IfrParse.c4836
1 files changed, 4836 insertions, 0 deletions
diff --git a/BaseTools/Source/C/FCE/IfrParse.c b/BaseTools/Source/C/FCE/IfrParse.c
new file mode 100644
index 0000000000..2f5a87baf3
--- /dev/null
+++ b/BaseTools/Source/C/FCE/IfrParse.c
@@ -0,0 +1,4836 @@
+/** @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;
+}
+