diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c | 2694 |
1 files changed, 2694 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c new file mode 100644 index 00000000..93779294 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c @@ -0,0 +1,2694 @@ +/** @file +Parser for IFR binary encoding. + +Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Setup.h" + +UINTN mStatementIndex; +UINTN mExpressionOpCodeIndex; +EFI_QUESTION_ID mUsedQuestionId; +extern LIST_ENTRY gBrowserStorageList; +/** + Initialize Statement header 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 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; + INTN ConditionalExprCount; + + if (Form == NULL) { + // + // Only guid op may out side the form level. + // + ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP); + } + + 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->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData; + 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)); + + ConditionalExprCount = GetConditionalExpressionCount(ExpressStatement); + if (ConditionalExprCount > 0) { + // + // Form is inside of suppressif + // + + Statement->Expression = (FORM_EXPRESSION_LIST *) AllocatePool( + (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *)))); + ASSERT (Statement->Expression != NULL); + Statement->Expression->Count = (UINTN) ConditionalExprCount; + Statement->Expression->Signature = FORM_EXPRESSION_LIST_SIGNATURE; + CopyMem (Statement->Expression->Expression, GetConditionalExpressionList(ExpressStatement), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount)); + } + + // + // Insert this Statement into current Form + // + if (Form == NULL) { + InsertTailList (&FormSet->StatementListOSF, &Statement->Link); + } else { + 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; + BOOLEAN Find; + + 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; + + 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) { + Statement->Storage = Storage->BrowserStorage; + break; + } + + Link = GetNextNode (&FormSet->StorageListHead, Link); + } + ASSERT (Statement->Storage != NULL); + + // + // Initialilze varname for Name/Value or EFI Variable + // + if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) || + (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) { + Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle); + ASSERT (Statement->VariableName != NULL); + + if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + // + // Check whether old string node already exist. + // + Find = FALSE; + if (!IsListEmpty(&Statement->Storage->NameValueListHead)) { + Link = GetFirstNode (&Statement->Storage->NameValueListHead); + while (!IsNull (&Statement->Storage->NameValueListHead, Link)) { + NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link); + + if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) { + Find = TRUE; + break; + } + + Link = GetNextNode (&Statement->Storage->NameValueListHead, Link); + } + } + + if (!Find) { + // + // Insert to Name/Value varstore list + // + NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE)); + ASSERT (NameValueNode != NULL); + NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE; + NameValueNode->Name = AllocateCopyPool (StrSize (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 + @param OpCode The binary opcode data. + + @return Pointer to a FORM_EXPRESSION data structure. + +**/ +FORM_EXPRESSION * +CreateExpression ( + IN OUT FORM_BROWSER_FORM *Form, + IN UINT8 *OpCode + ) +{ + FORM_EXPRESSION *Expression; + + Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION)); + ASSERT (Expression != NULL); + Expression->Signature = FORM_EXPRESSION_SIGNATURE; + InitializeListHead (&Expression->OpCodeListHead); + Expression->OpCode = (EFI_IFR_OP_HEADER *) OpCode; + + return Expression; +} + +/** + Create ConfigHdr string for a storage. + + @param FormSet Pointer of the current FormSet + @param Storage Pointer of the storage + + @retval EFI_SUCCESS Initialize ConfigHdr success + +**/ +EFI_STATUS +InitializeConfigHdr ( + IN FORM_BROWSER_FORMSET *FormSet, + IN OUT FORMSET_STORAGE *Storage + ) +{ + CHAR16 *Name; + + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER || + Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + Name = Storage->BrowserStorage->Name; + } else { + Name = NULL; + } + + Storage->ConfigHdr = HiiConstructConfigHdr ( + &Storage->BrowserStorage->Guid, + Name, + FormSet->DriverHandle + ); + + if (Storage->ConfigHdr == NULL) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Find the global storage link base on the input storate type, name and guid. + + For EFI_HII_VARSTORE_EFI_VARIABLE and EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, + same guid + name = same storage + + For EFI_HII_VARSTORE_NAME_VALUE: + same guid + HiiHandle = same storage + + For EFI_HII_VARSTORE_BUFFER: + same guid + name + HiiHandle = same storage + + @param StorageType Storage type. + @param StorageGuid Storage guid. + @param StorageName Storage Name. + @param HiiHandle HiiHandle for this varstore. + + @return Pointer to a GLOBAL_STORAGE data structure. + +**/ +BROWSER_STORAGE * +FindStorageInList ( + IN UINT8 StorageType, + IN EFI_GUID *StorageGuid, + IN CHAR16 *StorageName, + IN EFI_HII_HANDLE HiiHandle + ) +{ + LIST_ENTRY *Link; + BROWSER_STORAGE *BrowserStorage; + + Link = GetFirstNode (&gBrowserStorageList); + while (!IsNull (&gBrowserStorageList, Link)) { + BrowserStorage = BROWSER_STORAGE_FROM_LINK (Link); + Link = GetNextNode (&gBrowserStorageList, Link); + + if ((BrowserStorage->Type == StorageType) && CompareGuid (&BrowserStorage->Guid, StorageGuid)) { + if (StorageType == EFI_HII_VARSTORE_NAME_VALUE) { + if (BrowserStorage->HiiHandle == HiiHandle) { + return BrowserStorage; + } + + continue; + } + + ASSERT (StorageName != NULL); + if (StrCmp (BrowserStorage->Name, StorageName) == 0) { + if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE || StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + return BrowserStorage; + } else if (StorageType == EFI_HII_VARSTORE_BUFFER && BrowserStorage->HiiHandle == HiiHandle) { + return BrowserStorage; + } + } + } + } + + return NULL; +} + +/** + Intialize the Global Storage. + + @param BrowserStorage Pointer to the global storage. + @param StorageType Storage type. + @param OpCodeData Binary data for this opcode. + +**/ +VOID +IntializeBrowserStorage ( + IN BROWSER_STORAGE *BrowserStorage, + IN UINT8 StorageType, + IN UINT8 *OpCodeData + ) +{ + switch (StorageType) { + case EFI_HII_VARSTORE_BUFFER: + CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID)); + CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16)); + + BrowserStorage->Buffer = AllocateZeroPool (BrowserStorage->Size); + BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size); + break; + + case EFI_HII_VARSTORE_EFI_VARIABLE: + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: + CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID)); + CopyMem (&BrowserStorage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32)); + CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size, sizeof (UINT16)); + + if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + BrowserStorage->Buffer = AllocateZeroPool (BrowserStorage->Size); + BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size); + } + break; + + case EFI_HII_VARSTORE_NAME_VALUE: + CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID)); + + InitializeListHead (&BrowserStorage->NameValueListHead); + break; + + default: + break; + } +} + + +/** + Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List. + + @param FormSet Pointer of the current FormSet + @param StorageType Storage type. + @param OpCodeData Binary data for this opcode. + + @return Pointer to a FORMSET_STORAGE data structure. + +**/ +FORMSET_STORAGE * +CreateStorage ( + IN FORM_BROWSER_FORMSET *FormSet, + IN UINT8 StorageType, + IN UINT8 *OpCodeData + ) +{ + FORMSET_STORAGE *Storage; + CHAR16 *UnicodeString; + UINT16 Index; + BROWSER_STORAGE *BrowserStorage; + EFI_GUID *StorageGuid; + CHAR8 *StorageName; + + UnicodeString = NULL; + StorageName = NULL; + switch (StorageType) { + case EFI_HII_VARSTORE_BUFFER: + StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE *) OpCodeData)->Guid; + StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name; + break; + + case EFI_HII_VARSTORE_EFI_VARIABLE: + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: + StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid; + StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name; + break; + + default: + ASSERT (StorageType == EFI_HII_VARSTORE_NAME_VALUE); + StorageGuid = &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid; + break; + } + + if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) { + ASSERT (StorageName != NULL); + + UnicodeString = AllocateZeroPool (AsciiStrSize (StorageName) * 2); + ASSERT (UnicodeString != NULL); + for (Index = 0; StorageName[Index] != 0; Index++) { + UnicodeString[Index] = (CHAR16) StorageName[Index]; + } + } + + Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE)); + ASSERT (Storage != NULL); + Storage->Signature = FORMSET_STORAGE_SIGNATURE; + InsertTailList (&FormSet->StorageListHead, &Storage->Link); + + BrowserStorage = FindStorageInList(StorageType, StorageGuid, UnicodeString, FormSet->HiiHandle); + if (BrowserStorage == NULL) { + BrowserStorage = AllocateZeroPool (sizeof (BROWSER_STORAGE)); + ASSERT (BrowserStorage != NULL); + + BrowserStorage->Signature = BROWSER_STORAGE_SIGNATURE; + InsertTailList (&gBrowserStorageList, &BrowserStorage->Link); + + IntializeBrowserStorage (BrowserStorage, StorageType, OpCodeData); + BrowserStorage->Type = StorageType; + if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) { + BrowserStorage->Name = UnicodeString; + } + + BrowserStorage->HiiHandle = FormSet->HiiHandle; + + BrowserStorage->Initialized = FALSE; + } + + Storage->BrowserStorage = BrowserStorage; + InitializeConfigHdr (FormSet, Storage); + Storage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr); + Storage->SpareStrLen = 0; + + return Storage; +} + +/** + Get Formset_storage base on the input varstoreid info. + + @param FormSet Pointer of the current FormSet. + @param VarStoreId Varstore ID info. + + @return Pointer to a FORMSET_STORAGE data structure. + +**/ +FORMSET_STORAGE * +GetFstStgFromVarId ( + IN FORM_BROWSER_FORMSET *FormSet, + IN EFI_VARSTORE_ID VarStoreId + ) +{ + FORMSET_STORAGE *FormsetStorage; + LIST_ENTRY *Link; + BOOLEAN Found; + + Found = FALSE; + FormsetStorage = NULL; + // + // Find Formset Storage for this Question + // + Link = GetFirstNode (&FormSet->StorageListHead); + while (!IsNull (&FormSet->StorageListHead, Link)) { + FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link); + + if (FormsetStorage->VarStoreId == VarStoreId) { + Found = TRUE; + break; + } + + Link = GetNextNode (&FormSet->StorageListHead, Link); + } + + return Found ? FormsetStorage : NULL; +} + +/** + Get Formset_storage base on the input browser storage. + + More than one formsets may share the same browser storage, + this function just get the first formset storage which + share the browser storage. + + @param Storage browser storage info. + + @return Pointer to a FORMSET_STORAGE data structure. + + +**/ +FORMSET_STORAGE * +GetFstStgFromBrsStg ( + IN BROWSER_STORAGE *Storage + ) +{ + FORMSET_STORAGE *FormsetStorage; + LIST_ENTRY *Link; + LIST_ENTRY *FormsetLink; + FORM_BROWSER_FORMSET *FormSet; + BOOLEAN Found; + + Found = FALSE; + FormsetStorage = NULL; + + FormsetLink = GetFirstNode (&gBrowserFormSetList); + while (!IsNull (&gBrowserFormSetList, FormsetLink)) { + FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormsetLink); + FormsetLink = GetNextNode (&gBrowserFormSetList, FormsetLink); + + Link = GetFirstNode (&FormSet->StorageListHead); + while (!IsNull (&FormSet->StorageListHead, Link)) { + FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link); + Link = GetNextNode (&FormSet->StorageListHead, Link); + + if (FormsetStorage->BrowserStorage == Storage) { + Found = TRUE; + break; + } + } + + if (Found) { + break; + } + } + + return Found ? FormsetStorage : NULL; +} + +/** + Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label> + + @param FormSet Pointer of the current FormSet. + @param Question The Question to be initialized. + @param Form Pointer of the current form. + + @retval EFI_SUCCESS Function success. + @retval EFI_INVALID_PARAMETER No storage associated with the Question. + +**/ +EFI_STATUS +InitializeRequestElement ( + IN OUT FORM_BROWSER_FORMSET *FormSet, + IN OUT FORM_BROWSER_STATEMENT *Question, + IN OUT FORM_BROWSER_FORM *Form + ) +{ + BROWSER_STORAGE *Storage; + FORMSET_STORAGE *FormsetStorage; + UINTN StrLen; + UINTN StringSize; + CHAR16 *NewStr; + CHAR16 RequestElement[30]; + LIST_ENTRY *Link; + BOOLEAN Find; + FORM_BROWSER_CONFIG_REQUEST *ConfigInfo; + UINTN MaxLen; + + Storage = Question->Storage; + if (Storage == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { + // + // <ConfigRequest> is unnecessary for EFI variable storage, + // GetVariable()/SetVariable() will be used to retrieve/save values + // + return EFI_SUCCESS; + } + + // + // Prepare <RequestElement> + // + if (Storage->Type == EFI_HII_VARSTORE_BUFFER || + Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + StrLen = UnicodeSPrint ( + RequestElement, + 30 * sizeof (CHAR16), + L"&OFFSET=%04x&WIDTH=%04x", + Question->VarStoreInfo.VarOffset, + Question->StorageWidth + ); + HiiToLower(RequestElement); + Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement); + } else { + StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName); + } + + if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) { + // + // Password with CALLBACK flag is stored in encoded format, + // so don't need to append it to <ConfigRequest> + // + return EFI_SUCCESS; + } + + // + // Find Formset Storage for this Question + // + FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId); + ASSERT (FormsetStorage != NULL); + StringSize = (FormsetStorage->ConfigRequest != NULL) ? StrSize (FormsetStorage->ConfigRequest) : sizeof (CHAR16); + MaxLen = StringSize / sizeof (CHAR16) + FormsetStorage->SpareStrLen; + + // + // Append <RequestElement> to <ConfigRequest> + // + if (StrLen > FormsetStorage->SpareStrLen) { + // + // Old String buffer is not sufficient for RequestElement, allocate a new one + // + MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL; + NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16)); + ASSERT (NewStr != NULL); + if (FormsetStorage->ConfigRequest != NULL) { + CopyMem (NewStr, FormsetStorage->ConfigRequest, StringSize); + FreePool (FormsetStorage->ConfigRequest); + } + FormsetStorage->ConfigRequest = NewStr; + FormsetStorage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL; + } + + StrCatS (FormsetStorage->ConfigRequest, MaxLen, RequestElement); + FormsetStorage->ElementCount++; + FormsetStorage->SpareStrLen -= StrLen; + + // + // Update the Config Request info saved in the form. + // + ConfigInfo = NULL; + Find = FALSE; + Link = GetFirstNode (&Form->ConfigRequestHead); + while (!IsNull (&Form->ConfigRequestHead, Link)) { + ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link); + + if (ConfigInfo != NULL && ConfigInfo->Storage == FormsetStorage->BrowserStorage) { + Find = TRUE; + break; + } + + Link = GetNextNode (&Form->ConfigRequestHead, Link); + } + + if (!Find) { + ConfigInfo = AllocateZeroPool(sizeof (FORM_BROWSER_CONFIG_REQUEST)); + ASSERT (ConfigInfo != NULL); + ConfigInfo->Signature = FORM_BROWSER_CONFIG_REQUEST_SIGNATURE; + ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (FormsetStorage->ConfigHdr), FormsetStorage->ConfigHdr); + ASSERT (ConfigInfo->ConfigRequest != NULL); + ConfigInfo->SpareStrLen = 0; + ConfigInfo->Storage = FormsetStorage->BrowserStorage; + InsertTailList(&Form->ConfigRequestHead, &ConfigInfo->Link); + } + StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16); + MaxLen = StringSize / sizeof (CHAR16) + ConfigInfo->SpareStrLen; + + // + // Append <RequestElement> to <ConfigRequest> + // + if (StrLen > ConfigInfo->SpareStrLen) { + // + // Old String buffer is not sufficient for RequestElement, allocate a new one + // + MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL; + NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16)); + ASSERT (NewStr != NULL); + if (ConfigInfo->ConfigRequest != NULL) { + CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize); + FreePool (ConfigInfo->ConfigRequest); + } + ConfigInfo->ConfigRequest = NewStr; + ConfigInfo->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL; + } + + StrCatS (ConfigInfo->ConfigRequest, MaxLen, RequestElement); + ConfigInfo->ElementCount++; + ConfigInfo->SpareStrLen -= StrLen; + return EFI_SUCCESS; +} + + +/** + 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 + ) +{ + if (Storage == NULL) { + return; + } + + if (Storage->ConfigRequest != NULL) { + FreePool (Storage->ConfigRequest); + } + + FreePool (Storage); +} + + +/** + 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); + if (Option->SuppressExpression != NULL) { + FreePool (Option->SuppressExpression); + } + 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->Expression != NULL) { + FreePool (Statement->Expression); + } + + if (Statement->VariableName != NULL) { + FreePool (Statement->VariableName); + } + if (Statement->BlockName != NULL) { + FreePool (Statement->BlockName); + } + if (Statement->BufferValue != NULL) { + FreePool (Statement->BufferValue); + } + if (Statement->Operand == EFI_IFR_STRING_OP || Statement->Operand == EFI_IFR_PASSWORD_OP) { + DeleteString(Statement->HiiValue.Value.string, FormSet->HiiHandle); + } +} + + +/** + 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; + FORM_BROWSER_CONFIG_REQUEST *ConfigInfo; + + // + // 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 ConfigRequest string. + // + while (!IsListEmpty (&Form->ConfigRequestHead)) { + Link = GetFirstNode (&Form->ConfigRequestHead); + ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link); + RemoveEntryList (&ConfigInfo->Link); + + FreePool (ConfigInfo->ConfigRequest); + FreePool (ConfigInfo); + } + + if (Form->SuppressExpression != NULL) { + FreePool (Form->SuppressExpression); + } + + UiFreeMenuList (&Form->FormViewListHead); + + // + // Free this Form + // + FreePool (Form); +} + + +/** + Free resources allocated for a FormSet. + + @param FormSet Pointer of the FormSet + +**/ +VOID +DestroyFormSet ( + IN OUT FORM_BROWSER_FORMSET *FormSet + ) +{ + LIST_ENTRY *Link; + FORMSET_STORAGE *Storage; + FORMSET_DEFAULTSTORE *DefaultStore; + FORM_EXPRESSION *Expression; + FORM_BROWSER_FORM *Form; + + if (FormSet->IfrBinaryData == NULL) { + // + // Uninitialized FormSet + // + FreePool (FormSet); + return; + } + + // + // Free IFR binary buffer + // + FreePool (FormSet->IfrBinaryData); + + // + // Free FormSet Storage + // + if (FormSet->StorageListHead.ForwardLink != NULL) { + while (!IsListEmpty (&FormSet->StorageListHead)) { + Link = GetFirstNode (&FormSet->StorageListHead); + Storage = FORMSET_STORAGE_FROM_LINK (Link); + RemoveEntryList (&Storage->Link); + + DestroyStorage (Storage); + } + } + + // + // 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); + } + + FreePool (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) || + (Operand == EFI_IFR_MATCH2_OP)) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Tell whether this Operand is an Statement OpCode. + + @param Operand Operand of an IFR OpCode. + + @retval TRUE This is an Statement OpCode. + @retval FALSE Not an Statement OpCode. + +**/ +BOOLEAN +IsStatementOpCode ( + IN UINT8 Operand + ) +{ + if ((Operand == EFI_IFR_SUBTITLE_OP) || + (Operand == EFI_IFR_TEXT_OP) || + (Operand == EFI_IFR_RESET_BUTTON_OP) || + (Operand == EFI_IFR_REF_OP) || + (Operand == EFI_IFR_ACTION_OP) || + (Operand == EFI_IFR_NUMERIC_OP) || + (Operand == EFI_IFR_ORDERED_LIST_OP) || + (Operand == EFI_IFR_CHECKBOX_OP) || + (Operand == EFI_IFR_STRING_OP) || + (Operand == EFI_IFR_PASSWORD_OP) || + (Operand == EFI_IFR_DATE_OP) || + (Operand == EFI_IFR_TIME_OP) || + (Operand == EFI_IFR_GUID_OP) || + (Operand == EFI_IFR_ONE_OF_OP)) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Tell whether this Operand is an known OpCode. + + @param Operand Operand of an IFR OpCode. + + @retval TRUE This is an Statement OpCode. + @retval FALSE Not an Statement OpCode. + +**/ +BOOLEAN +IsUnKnownOpCode ( + IN UINT8 Operand + ) +{ + return Operand > EFI_IFR_MATCH2_OP ? TRUE : 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, + OUT UINTN *NumberOfStatement, + OUT UINTN *NumberOfExpression + ) +{ + UINTN StatementCount; + UINTN 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; + FORM_BROWSER_FORM *CurrentForm; + FORM_BROWSER_STATEMENT *CurrentStatement; + FORM_BROWSER_STATEMENT *ParentStatement; + EXPRESSION_OPCODE *ExpressionOpCode; + FORM_EXPRESSION *CurrentExpression; + UINT8 Operand; + UINT8 Scope; + UINTN OpCodeOffset; + UINTN OpCodeLength; + UINT8 *OpCodeData; + UINT8 ScopeOpCode; + FORMSET_STORAGE *Storage; + FORMSET_DEFAULTSTORE *DefaultStore; + QUESTION_DEFAULT *CurrentDefault; + QUESTION_OPTION *CurrentOption; + UINT8 Width; + UINTN NumberOfStatement; + UINTN NumberOfExpression; + EFI_IMAGE_ID *ImageId; + BOOLEAN SuppressForQuestion; + BOOLEAN SuppressForOption; + UINT16 DepthOfDisable; + BOOLEAN OpCodeDisabled; + BOOLEAN SingleOpCodeExpression; + BOOLEAN InScopeDefault; + EFI_HII_VALUE *Value; + EFI_IFR_FORM_MAP_METHOD *MapMethod; + UINT8 MapScopeDepth; + LIST_ENTRY *Link; + FORMSET_STORAGE *VarStorage; + LIST_ENTRY *MapExpressionList; + EFI_VARSTORE_ID TempVarstoreId; + BOOLEAN InScopeDisable; + INTN ConditionalExprCount; + BOOLEAN InUnknownScope; + UINT8 UnknownDepth; + FORMSET_DEFAULTSTORE *PreDefaultStore; + LIST_ENTRY *DefaultLink; + BOOLEAN HaveInserted; + UINT16 TotalBits; + BOOLEAN QuestionReferBitField; + + SuppressForQuestion = FALSE; + SuppressForOption = FALSE; + InScopeDisable = FALSE; + DepthOfDisable = 0; + OpCodeDisabled = FALSE; + SingleOpCodeExpression = FALSE; + InScopeDefault = FALSE; + CurrentExpression = NULL; + CurrentDefault = NULL; + CurrentOption = NULL; + ImageId = NULL; + MapMethod = NULL; + MapScopeDepth = 0; + Link = NULL; + VarStorage = NULL; + MapExpressionList = NULL; + TempVarstoreId = 0; + ConditionalExprCount = 0; + InUnknownScope = FALSE; + UnknownDepth = 0; + QuestionReferBitField = FALSE; + + // + // Get the number of Statements and Expressions + // + CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression); + + mStatementIndex = 0; + mUsedQuestionId = 1; + 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; + } + + InitializeListHead (&FormSet->StatementListOSF); + InitializeListHead (&FormSet->StorageListHead); + InitializeListHead (&FormSet->SaveFailStorageListHead); + InitializeListHead (&FormSet->DefaultStoreListHead); + InitializeListHead (&FormSet->FormListHead); + InitializeListHead (&FormSet->ExpressionListHead); + ResetCurrentExpressionStack (); + ResetMapExpressionListStack (); + + CurrentForm = NULL; + CurrentStatement = NULL; + ParentStatement = 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 (InUnknownScope) { + if (Operand == EFI_IFR_END_OP) { + UnknownDepth --; + + if (UnknownDepth == 0) { + InUnknownScope = FALSE; + } + } else { + if (Scope != 0) { + UnknownDepth ++; + } + } + + continue; + } + + if (IsUnKnownOpCode(Operand)) { + if (Scope != 0) { + InUnknownScope = TRUE; + UnknownDepth ++; + } + + continue; + } + + // + // 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) { + InScopeDisable = 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 = AllocateCopyPool (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 (ParentStatement != NULL); + ExpressionOpCode->QuestionId = ParentStatement->QuestionId; + break; + + case EFI_IFR_SECURITY_OP: + CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID)); + break; + + case EFI_IFR_MATCH2_OP: + CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_MATCH2 *) OpCodeData)->SyntaxType, 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->BrowserStorage; + 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_HII_VARSTORE_EFI_VARIABLE)) { + ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle); + 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; + Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION; + break; + + default: + break; + } + // + // Create sub expression nested in MAP opcode + // + if (CurrentExpression == NULL && MapScopeDepth > 0) { + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); + 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 (InScopeDisable && CurrentForm == NULL) { + // + // This is DisableIf expression for Form, it should be a constant expression + // + Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression); + if (EFI_ERROR (Status)) { + return Status; + } + + OpCodeDisabled = IsTrue(&CurrentExpression->Result); + } + + CurrentExpression = NULL; + } + + continue; + } + + // + // Parse the Opcode + // + switch (Operand) { + + case EFI_IFR_FORM_SET_OP: + // + // Check the formset GUID + // + if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) { + return EFI_INVALID_PARAMETER; + } + + 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)); + FormSet->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData;//save the opcode address of formset + + 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)); + } + break; + + case EFI_IFR_FORM_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); + InitializeListHead (&CurrentForm->ConfigRequestHead); + InitializeListHead (&CurrentForm->FormViewListHead); + + 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)); + + ConditionalExprCount = GetConditionalExpressionCount(ExpressForm); + if ( ConditionalExprCount > 0) { + // + // Form is inside of suppressif + // + CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool( + (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *)))); + ASSERT (CurrentForm->SuppressExpression != NULL); + CurrentForm->SuppressExpression->Count = (UINTN) ConditionalExprCount; + CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE; + CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount)); + } + + 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; + + 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); + InitializeListHead (&CurrentForm->ConfigRequestHead); + InitializeListHead (&CurrentForm->FormViewListHead); + + CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16)); + + MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP)); + // + // FormMap Form must contain at least one Map Method. + // + if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) { + return EFI_INVALID_PARAMETER; + } + // + // Try to find the standard form map method. + // + while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) { + if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) { + CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID)); + CurrentForm->FormType = STANDARD_MAP_FORM_TYPE; + break; + } + MapMethod ++; + } + // + // If the standard form map method is not found, the first map method title will be used. + // + if (CurrentForm->FormTitle == 0) { + MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP)); + CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID)); + } + + ConditionalExprCount = GetConditionalExpressionCount(ExpressForm); + if ( ConditionalExprCount > 0) { + // + // Form is inside of suppressif + // + CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool( + (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *)))); + ASSERT (CurrentForm->SuppressExpression != NULL); + CurrentForm->SuppressExpression->Count = (UINTN) ConditionalExprCount; + CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE; + CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount)); + } + + 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, EFI_HII_VARSTORE_BUFFER, OpCodeData); + CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID)); + break; + + case EFI_IFR_VARSTORE_NAME_VALUE_OP: + // + // Create a name/value Storage for this FormSet + // + Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData); + CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID)); + break; + + case EFI_IFR_VARSTORE_EFI_OP: + // + // Create a EFI variable Storage for this FormSet + // + if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) { + // + // Create efi varstore with format follow UEFI spec before 2.3.1. + // + Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData); + } else { + // + // Create efi varstore with format follow UEFI spec 2.3.1 and later. + // + Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData); + } + CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID)); + 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; + CurrentStatement->FakeQuestionId = mUsedQuestionId++; + break; + + case EFI_IFR_TEXT_OP: + CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm); + ASSERT (CurrentStatement != NULL); + CurrentStatement->FakeQuestionId = mUsedQuestionId++; + 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); + CurrentStatement->FakeQuestionId = mUsedQuestionId++; + 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; + + if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) { + // + // No QuestionConfig present, so no configuration string will be processed + // + CurrentStatement->QuestionConfig = 0; + } else { + CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID)); + } + 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); + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm); + 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 (QuestionReferBitField) { + // + // 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; + + // + // Update the Flag and type of Minimum/Maximum/Step according to the actual width of bit field, + // in order to make Browser handle these question with bit varstore correctly. + // + ((EFI_IFR_NUMERIC *) OpCodeData)->Flags &= EDKII_IFR_DISPLAY_BIT; + ((EFI_IFR_NUMERIC *) OpCodeData)->Flags >>= 2; + switch (CurrentStatement->StorageWidth) { + case 1: + ((EFI_IFR_NUMERIC *) OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_8; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue = (UINT8)CurrentStatement->Minimum; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue = (UINT8)CurrentStatement->Maximum; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step = (UINT8)CurrentStatement->Step; + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + break; + case 2: + ((EFI_IFR_NUMERIC *) OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_16; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue = (UINT16)CurrentStatement->Minimum; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue = (UINT16)CurrentStatement->Maximum; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step = (UINT16)CurrentStatement->Step; + Value->Type = EFI_IFR_TYPE_NUM_SIZE_16; + break; + case 3: + case 4: + ((EFI_IFR_NUMERIC *) OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_32; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue = (UINT32)CurrentStatement->Minimum; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue = (UINT32)CurrentStatement->Maximum; + ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step = (UINT32)CurrentStatement->Step; + Value->Type = EFI_IFR_TYPE_NUM_SIZE_32; + break; + default: + break; + } + } 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; + } + } + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm); + + if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) { + SuppressForOption = TRUE; + } + 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; + } + 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 (QuestionReferBitField) { + // + // Get the bit var store info (bit/byte offset, bit/byte offset) + // + 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); + } + + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm); + + 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)); + CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle); + + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm); + 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))); + CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle); + + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm); + 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); + + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm); + } 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); + + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm); + } 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 = AllocateCopyPool (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 (&ParentStatement->DefaultListHead, &CurrentDefault->Link); + + if (Scope != 0) { + InScopeDefault = TRUE; + } + break; + + // + // Option + // + case EFI_IFR_ONE_OF_OPTION_OP: + ASSERT (ParentStatement != NULL); + if (ParentStatement->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 = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value); + ASSERT (CurrentDefault->Value.Buffer != NULL); + + // + // Insert to Default Value list of current Question + // + InsertTailList (&ParentStatement->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->OpCode = (EFI_IFR_ONE_OF_OPTION *) OpCodeData; + + 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); + + ConditionalExprCount = GetConditionalExpressionCount(ExpressOption); + if ( ConditionalExprCount > 0) { + // + // Form is inside of suppressif + // + CurrentOption->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool( + (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *)))); + ASSERT (CurrentOption->SuppressExpression != NULL); + CurrentOption->SuppressExpression->Count = (UINTN) ConditionalExprCount; + CurrentOption->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE; + CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList(ExpressOption), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount)); + } + + // + // Insert to Option list of current Question + // + InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link); + // + // Now we know the Storage width of nested Ordered List + // + if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->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; + } + + ParentStatement->StorageWidth = (UINT16) (ParentStatement->MaxContainers * Width); + ParentStatement->BufferValue = AllocateZeroPool (ParentStatement->StorageWidth); + ParentStatement->ValueType = CurrentOption->Value.Type; + if (ParentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) { + ParentStatement->HiiValue.Buffer = ParentStatement->BufferValue; + ParentStatement->HiiValue.BufferLen = ParentStatement->StorageWidth; + } + + InitializeRequestElement (FormSet, ParentStatement, CurrentForm); + } + break; + + // + // Conditional + // + case EFI_IFR_NO_SUBMIT_IF_OP: + case EFI_IFR_INCONSISTENT_IF_OP: + // + // Create an Expression node + // + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); + 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 (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link); + } else { + CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF; + InsertTailList (&ParentStatement->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, OpCodeData); + 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 (&ParentStatement->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, OpCodeData); + CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF; + + if (CurrentForm == NULL) { + InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link); + } else { + InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); + } + + if (SuppressForOption) { + PushConditionalExpression(CurrentExpression, ExpressOption); + } else if (SuppressForQuestion) { + PushConditionalExpression(CurrentExpression, ExpressStatement); + } else { + PushConditionalExpression(CurrentExpression, ExpressForm); + } + + // + // 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, OpCodeData); + CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF; + InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); + PushConditionalExpression(CurrentExpression, ExpressStatement); + + // + // 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); + PushConditionalExpression(CurrentExpression, ExpressStatement); + } + + OpCodeDisabled = FALSE; + InScopeDisable = TRUE; + // + // 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, OpCodeData); + 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 (ParentStatement != NULL); + ParentStatement->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, OpCodeData); + 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, OpCodeData); + 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 (ParentStatement != NULL); + ParentStatement->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, OpCodeData); + 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 (ParentStatement != NULL); + ParentStatement->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: + ImageId = &FormSet->ImageId; + break; + + case EFI_IFR_FORM_OP: + case EFI_IFR_FORM_MAP_OP: + ASSERT (CurrentForm != NULL); + ImageId = &CurrentForm->ImageId; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + ASSERT (CurrentOption != NULL); + ImageId = &CurrentOption->ImageId; + 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 (ParentStatement != NULL); + ImageId = &ParentStatement->ImageId; + break; + } + + ASSERT (ImageId != NULL); + CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID)); + break; + + // + // Refresh + // + case EFI_IFR_REFRESH_OP: + ASSERT (ParentStatement != NULL); + ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval; + break; + + // + // Refresh guid. + // + case EFI_IFR_REFRESH_ID_OP: + // + // Get ScopeOpcode from top of stack + // + PopScope (&ScopeOpCode); + PushScope (ScopeOpCode); + + switch (ScopeOpCode) { + case EFI_IFR_FORM_OP: + case EFI_IFR_FORM_MAP_OP: + ASSERT (CurrentForm != NULL); + CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID)); + break; + + default: + ASSERT (ParentStatement != NULL); + CopyMem (&ParentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID)); + break; + } + break; + + // + // Modal tag + // + case EFI_IFR_MODAL_TAG_OP: + ASSERT (CurrentForm != NULL); + CurrentForm->ModalForm = TRUE; + break; + + // + // Lock tag, used by form and statement. + // + case EFI_IFR_LOCKED_OP: + // + // Get ScopeOpcode from top of stack + // + PopScope (&ScopeOpCode); + PushScope (ScopeOpCode); + switch (ScopeOpCode) { + case EFI_IFR_FORM_OP: + case EFI_IFR_FORM_MAP_OP: + ASSERT (CurrentForm != NULL); + CurrentForm->Locked = TRUE; + break; + + default: + ASSERT (ParentStatement != NULL); + ParentStatement->Locked = TRUE; + } + break; + + // + // Vendor specific + // + case EFI_IFR_GUID_OP: + CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm); + if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) { + Scope = 0; + QuestionReferBitField = TRUE; + } + break; + + // + // Scope End + // + case EFI_IFR_END_OP: + QuestionReferBitField = FALSE; + Status = PopScope (&ScopeOpCode); + if (EFI_ERROR (Status)) { + ResetScopeStack (); + return Status; + } + + // + // Parent statement end tag found, update ParentStatement info. + // + if (IsStatementOpCode(ScopeOpCode) && (ParentStatement != NULL) && (ParentStatement->Operand == ScopeOpCode)) { + ParentStatement = ParentStatement->ParentStatement; + } + + 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_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) { + PopConditionalExpression(ExpressOption); + } else if (SuppressForQuestion) { + PopConditionalExpression(ExpressStatement); + } else { + PopConditionalExpression(ExpressForm); + } + break; + + case EFI_IFR_GRAY_OUT_IF_OP: + PopConditionalExpression(ExpressStatement); + break; + + case EFI_IFR_DISABLE_IF_OP: + if (CurrentForm != NULL) { + PopConditionalExpression(ExpressStatement); + } + InScopeDisable = 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 (InScopeDisable && CurrentForm == NULL) { + // + // This is DisableIf expression for Form, it should be a constant expression + // + ASSERT (CurrentExpression != NULL); + Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression); + if (EFI_ERROR (Status)) { + return Status; + } + + OpCodeDisabled = IsTrue (&CurrentExpression->Result); + + // + // DisableIf Expression is only used once and not queued, free it + // + DestroyExpression (CurrentExpression); + } + + // + // End of current Expression + // + CurrentExpression = NULL; + } + break; + } + break; + + default: + break; + } + + if (IsStatementOpCode(Operand)) { + CurrentStatement->ParentStatement = ParentStatement; + if (Scope != 0) { + // + // Scope != 0, other statements or options may nest in this statement. + // Update the ParentStatement info. + // + ParentStatement = CurrentStatement; + } + } + } + + return EFI_SUCCESS; +} |