X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FSetupBrowserDxe%2FIfrParse.c;h=edb6a0fc4ced2aac35e0249b9394197861dbd416;hb=HEAD;hp=745e20d9eaa27be572e709e14a3dab884d9f38cf;hpb=945e3aed0f238c5c3e401a7793d1e8133c85d7c7;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c index 745e20d9ea..ed8f9965be 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c @@ -1,36 +1,23 @@ /** @file Parser for IFR binary encoding. -Copyright (c) 2007 - 2009, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Setup.h" -#include "Ui.h" - -UINT16 mStatementIndex; -UINT16 mExpressionOpCodeIndex; -BOOLEAN mInScopeSubtitle; -BOOLEAN mInScopeSuppress; -BOOLEAN mInScopeGrayOut; -BOOLEAN mInScopeDisable; -FORM_EXPRESSION *mSuppressExpression; -FORM_EXPRESSION *mGrayOutExpression; -FORM_EXPRESSION *mDisableExpression; +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 FormSe. + @param FormSet Pointer of the current FormSet. @param Form Pointer of the current Form. @return The Statement. @@ -38,19 +25,20 @@ FORM_EXPRESSION *mDisableExpression; **/ FORM_BROWSER_STATEMENT * CreateStatement ( - IN UINT8 *OpCodeData, - IN OUT FORM_BROWSER_FORMSET *FormSet, - IN OUT FORM_BROWSER_FORM *Form + 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) { // - // We are currently not in a Form Scope, so just skip this Statement + // Only guid op may out side the form level. // - return NULL; + ASSERT (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_GUID_OP); } Statement = &FormSet->StatementBuffer[mStatementIndex]; @@ -60,106 +48,43 @@ CreateStatement ( 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->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)); + 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; - } - + ConditionalExprCount = GetConditionalExpressionCount (ExpressStatement); + if (ConditionalExprCount > 0) { + // + // Form is inside of suppressif + // - if (mInScopeDisable) { - Statement->DisableExpression = mDisableExpression; + 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)); } - Statement->InSubtitle = mInScopeSubtitle; - // // Insert this Statement into current Form // - InsertTailList (&Form->StatementListHead, &Statement->Link); - - return Statement; -} - -/** - Convert a numeric value to a Unicode String and insert it to String Package. - This string is used as the Unicode Name for the EFI Variable. This is to support - the deprecated vareqval opcode. - - @param FormSet The FormSet. - @param Statement The numeric question whose VarStoreInfo.VarName is the - numeric value which is used to produce the Unicode Name - for the EFI Variable. - - If the Statement is NULL, the ASSERT. - If the opcode is not Numeric, then ASSERT. - - @retval EFI_SUCCESS The funtion always succeeds. -**/ -EFI_STATUS -UpdateCheckBoxStringToken ( - IN CONST FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_STATEMENT *Statement - ) -{ - CHAR16 Str[MAXIMUM_VALUE_CHARACTERS]; - EFI_STRING_ID Id; - - ASSERT (Statement != NULL); - ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP); - - UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1); - - Id = HiiSetString (FormSet->HiiHandle, 0, Str, NULL); - if (Id == 0) { - return EFI_OUT_OF_RESOURCES; - } - - Statement->VarStoreInfo.VarName = Id; - - return EFI_SUCCESS; -} - -/** - Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME. - - @param OpCodeData The current opcode. - - @retval TRUE Yes. - @retval FALSE No. -**/ -BOOLEAN -IsNextOpCodeGuidedVarEqName ( - UINT8 *OpCodeData - ) -{ - // - // Get next opcode - // - OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - if (*OpCodeData == EFI_IFR_GUID_OP) { - if (CompareGuid (&gEfiIfrFrameworkGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { - // - // Specific GUIDed opcodes to support IFR generated from Framework HII VFR - // - if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) { - return TRUE; - } - } + if (Form == NULL) { + InsertTailList (&FormSet->StatementListOSF, &Statement->Link); + } else { + InsertTailList (&Form->StatementListHead, &Statement->Link); } - return FALSE; + return Statement; } /** @@ -174,9 +99,9 @@ IsNextOpCodeGuidedVarEqName ( **/ FORM_BROWSER_STATEMENT * CreateQuestion ( - IN UINT8 *OpCodeData, - IN OUT FORM_BROWSER_FORMSET *FormSet, - IN OUT FORM_BROWSER_FORM *Form + IN UINT8 *OpCodeData, + IN OUT FORM_BROWSER_FORMSET *FormSet, + IN OUT FORM_BROWSER_FORM *Form ) { FORM_BROWSER_STATEMENT *Statement; @@ -184,14 +109,14 @@ CreateQuestion ( LIST_ENTRY *Link; FORMSET_STORAGE *Storage; NAME_VALUE_NODE *NameValueNode; - EFI_STATUS Status; + BOOLEAN Find; Statement = CreateStatement (OpCodeData, FormSet, Form); if (Statement == NULL) { return NULL; } - QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); + 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)); @@ -205,19 +130,6 @@ CreateQuestion ( return Statement; } - // - // Take a look at next OpCode to see whether it is a GUIDed opcode to support - // Framework Compatibility - // - if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) { - if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) { - Status = UpdateCheckBoxStringToken (FormSet, Statement); - if (EFI_ERROR (Status)) { - return NULL; - } - } - } - // // Find Storage for this Question // @@ -226,55 +138,78 @@ CreateQuestion ( Storage = FORMSET_STORAGE_FROM_LINK (Link); if (Storage->VarStoreId == Statement->VarStoreId) { - Statement->Storage = Storage; + 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->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) { // - // Insert to Name/Value varstore list + // Check whether old string node already exist. // - 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); + 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 OUT FORM_BROWSER_FORM *Form, + IN UINT8 *OpCode ) { FORM_EXPRESSION *Expression; @@ -283,81 +218,338 @@ CreateExpression ( 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 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 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; - InitializeListHead (&Storage->NameValueListHead); 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; } - /** - Create ConfigHdr string for a storage. + Get Formset_storage base on the input varstoreid info. - @param FormSet Pointer of the current FormSet - @param Storage Pointer of the storage + @param FormSet Pointer of the current FormSet. + @param VarStoreId Varstore ID info. - @retval EFI_SUCCESS Initialize ConfigHdr success + @return Pointer to a FORMSET_STORAGE data structure. **/ -EFI_STATUS -InitializeConfigHdr ( +FORMSET_STORAGE * +GetFstStgFromVarId ( IN FORM_BROWSER_FORMSET *FormSet, - IN OUT FORMSET_STORAGE *Storage + IN EFI_VARSTORE_ID VarStoreId ) { - CHAR16 *Name; - - if (Storage->Type == EFI_HII_VARSTORE_BUFFER) { - Name = Storage->Name; - } else { - Name = NULL; - } - - Storage->ConfigHdr = HiiConstructConfigHdr ( - &Storage->Guid, - Name, - FormSet->DriverHandle - ); - - if (Storage->ConfigHdr == NULL) { - return EFI_NOT_FOUND; - } + FORMSET_STORAGE *FormsetStorage; + LIST_ENTRY *Link; + BOOLEAN Found; - Storage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr); - Storage->SpareStrLen = 0; + 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); - return EFI_SUCCESS; + 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. ::= '&' | '&'