/** @file Parser for IFR binary encoding. Copyright (c) 2011-2019, Intel Corporation. All rights reserved.
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; }