X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FSetupBrowserDxe%2FIfrParse.c;h=e806b504b2934fdc4079d02b928dd862f48db7ca;hb=4f467fd33b2fc682ed5f1932453d47110345534e;hp=1c3ab2bedca4e1e45b6160c7b1ce027827a4501e;hpb=b9feb4bdf281bcd9c61d9b089c379f265664674b;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c index 1c3ab2bedc..e806b504b2 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c @@ -17,7 +17,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. UINT16 mStatementIndex; UINT16 mExpressionOpCodeIndex; EFI_QUESTION_ID mUsedQuestionId; -BOOLEAN mInScopeSubtitle; extern LIST_ENTRY gBrowserStorageList; /** Initialize Statement header members. @@ -54,6 +53,7 @@ CreateStatement ( InitializeListHead (&Statement->OptionListHead); InitializeListHead (&Statement->InconsistentListHead); InitializeListHead (&Statement->NoSubmitListHead); + InitializeListHead (&Statement->WarningListHead); Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE; @@ -78,8 +78,6 @@ CreateStatement ( CopyMem (Statement->Expression->Expression, GetConditionalExpressionList(ExpressStatement), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount)); } - Statement->InSubtitle = mInScopeSubtitle; - // // Insert this Statement into current Form // @@ -288,13 +286,15 @@ CreateQuestion ( 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; @@ -303,6 +303,7 @@ CreateExpression ( ASSERT (Expression != NULL); Expression->Signature = FORM_EXPRESSION_SIGNATURE; InitializeListHead (&Expression->OpCodeListHead); + Expression->OpCode = (EFI_IFR_OP_HEADER *) OpCode; return Expression; } @@ -347,9 +348,19 @@ InitializeConfigHdr ( /** 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. @@ -358,7 +369,8 @@ BROWSER_STORAGE * FindStorageInList ( IN UINT8 StorageType, IN EFI_GUID *StorageGuid, - IN CHAR16 *StorageName + IN CHAR16 *StorageName, + IN EFI_HII_HANDLE HiiHandle ) { LIST_ENTRY *Link; @@ -367,21 +379,26 @@ FindStorageInList ( 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) { - return BrowserStorage; + if (BrowserStorage->HiiHandle == HiiHandle) { + return BrowserStorage; + } + + continue; } + ASSERT (StorageName != NULL); if (StrCmp (BrowserStorage->Name, StorageName) == 0) { - return BrowserStorage; + 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; + } } } - - // - // Get Next Storage. - // - Link = GetNextNode (&gBrowserStorageList, Link); } return NULL; @@ -493,7 +510,7 @@ CreateStorage ( Storage->Signature = FORMSET_STORAGE_SIGNATURE; InsertTailList (&FormSet->StorageListHead, &Storage->Link); - BrowserStorage = FindStorageInList(StorageType, StorageGuid, UnicodeString); + BrowserStorage = FindStorageInList(StorageType, StorageGuid, UnicodeString, FormSet->HiiHandle); if (BrowserStorage == NULL) { BrowserStorage = AllocateZeroPool (sizeof (BROWSER_STORAGE)); ASSERT (BrowserStorage != NULL); @@ -507,12 +524,11 @@ CreateStorage ( BrowserStorage->Name = UnicodeString; } + BrowserStorage->HiiHandle = FormSet->HiiHandle; InitializeConfigHdr (FormSet, BrowserStorage); + + BrowserStorage->Initialized = FALSE; } - // - // Add count because one formset storage use this global storage. - // - BrowserStorage->ReferenceCount++; Storage->BrowserStorage = BrowserStorage; Storage->ConfigRequest = AllocateCopyPool (StrSize (BrowserStorage->ConfigHdr), BrowserStorage->ConfigHdr); @@ -741,12 +757,6 @@ DestroyStorage ( FreePool (Storage->ConfigRequest); } - // - // Minus the reference to the global storage. - // - ASSERT (Storage->BrowserStorage->ReferenceCount > 0); - Storage->BrowserStorage->ReferenceCount--; - FreePool (Storage); } @@ -816,6 +826,17 @@ DestroyStatement ( 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); } @@ -1018,6 +1039,56 @@ IsExpressionOpCode ( } } +/** + 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_WARNING_IF_OP ? TRUE : FALSE; +} /** Calculate number of Statemens(Questions) and Expression OpCodes. @@ -1079,6 +1150,7 @@ ParseOpCodes ( EFI_STATUS Status; FORM_BROWSER_FORM *CurrentForm; FORM_BROWSER_STATEMENT *CurrentStatement; + FORM_BROWSER_STATEMENT *ParentStatement; EXPRESSION_OPCODE *ExpressionOpCode; FORM_EXPRESSION *CurrentExpression; UINT8 Operand; @@ -1110,8 +1182,9 @@ ParseOpCodes ( EFI_VARSTORE_ID TempVarstoreId; BOOLEAN InScopeDisable; INTN ConditionalExprCount; + BOOLEAN InUnknownScope; + UINT8 UnknownDepth; - mInScopeSubtitle = FALSE; SuppressForQuestion = FALSE; SuppressForOption = FALSE; InScopeDisable = FALSE; @@ -1130,6 +1203,8 @@ ParseOpCodes ( MapExpressionList = NULL; TempVarstoreId = 0; ConditionalExprCount = 0; + InUnknownScope = FALSE; + UnknownDepth = 0; // // Get the number of Statements and Expressions @@ -1159,6 +1234,7 @@ ParseOpCodes ( CurrentForm = NULL; CurrentStatement = NULL; + ParentStatement = NULL; ResetScopeStack (); @@ -1171,6 +1247,31 @@ ParseOpCodes ( 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 // @@ -1249,8 +1350,8 @@ ParseOpCodes ( break; case EFI_IFR_THIS_OP: - ASSERT (CurrentStatement != NULL); - ExpressionOpCode->QuestionId = CurrentStatement->QuestionId; + ASSERT (ParentStatement != NULL); + ExpressionOpCode->QuestionId = ParentStatement->QuestionId; break; case EFI_IFR_SECURITY_OP: @@ -1414,7 +1515,7 @@ ParseOpCodes ( // Create sub expression nested in MAP opcode // if (CurrentExpression == NULL && MapScopeDepth > 0) { - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); ASSERT (MapExpressionList != NULL); InsertTailList (MapExpressionList, &CurrentExpression->Link); if (Scope == 0) { @@ -1458,11 +1559,7 @@ ParseOpCodes ( return Status; } - if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; - } - - OpCodeDisabled = CurrentExpression->Result.Value.b; + OpCodeDisabled = IsTrue(&CurrentExpression->Result); } CurrentExpression = NULL; @@ -1625,8 +1722,14 @@ ParseOpCodes ( // 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)); @@ -1658,9 +1761,6 @@ ParseOpCodes ( CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags; CurrentStatement->FakeQuestionId = mUsedQuestionId++; - if (Scope != 0) { - mInScopeSubtitle = TRUE; - } break; case EFI_IFR_TEXT_OP: @@ -1900,7 +2000,7 @@ ParseOpCodes ( // // Insert to Default Value list of current Question // - InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link); + InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link); if (Scope != 0) { InScopeDefault = TRUE; @@ -1939,16 +2039,15 @@ ParseOpCodes ( CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList(ExpressOption), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount)); } + ASSERT (ParentStatement != NULL); // // Insert to Option list of current Question // - InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link); - + InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link); // // Now we know the Storage width of nested Ordered List // - ASSERT (CurrentStatement != NULL); - if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) { + if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->BufferValue == NULL)) { Width = 1; switch (CurrentOption->Value.Type) { case EFI_IFR_TYPE_NUM_SIZE_8: @@ -1974,15 +2073,15 @@ ParseOpCodes ( break; } - CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width); - CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth); - CurrentStatement->ValueType = CurrentOption->Value.Type; - if (CurrentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) { - CurrentStatement->HiiValue.Buffer = CurrentStatement->BufferValue; - CurrentStatement->HiiValue.BufferLen = CurrentStatement->StorageWidth; + 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, CurrentStatement, CurrentForm); + InitializeRequestElement (FormSet, ParentStatement, CurrentForm); } break; @@ -1994,15 +2093,15 @@ ParseOpCodes ( // // Create an Expression node // - CurrentExpression = CreateExpression (CurrentForm); + 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 (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link); + InsertTailList (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link); } else { CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF; - InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link); + InsertTailList (&ParentStatement->InconsistentListHead, &CurrentExpression->Link); } // @@ -2014,11 +2113,30 @@ ParseOpCodes ( } 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); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF; if (CurrentForm == NULL) { @@ -2048,7 +2166,7 @@ ParseOpCodes ( // // Questions will appear in scope of this OpCode // - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); PushConditionalExpression(CurrentExpression, ExpressStatement); @@ -2096,7 +2214,7 @@ ParseOpCodes ( // Expression // case EFI_IFR_VALUE_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); @@ -2114,8 +2232,8 @@ ParseOpCodes ( // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler. // - ASSERT (CurrentStatement != NULL); - CurrentStatement->ValueExpression = CurrentExpression; + ASSERT (ParentStatement != NULL); + ParentStatement->ValueExpression = CurrentExpression; } // @@ -2128,7 +2246,7 @@ ParseOpCodes ( break; case EFI_IFR_RULE_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_RULE; CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId; @@ -2144,7 +2262,7 @@ ParseOpCodes ( break; case EFI_IFR_READ_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_READ; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); @@ -2153,8 +2271,8 @@ ParseOpCodes ( // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler. // - ASSERT (CurrentStatement != NULL); - CurrentStatement->ReadExpression = CurrentExpression; + ASSERT (ParentStatement != NULL); + ParentStatement->ReadExpression = CurrentExpression; // // Take a look at next OpCode to see whether current expression consists @@ -2166,7 +2284,7 @@ ParseOpCodes ( break; case EFI_IFR_WRITE_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); @@ -2175,8 +2293,8 @@ ParseOpCodes ( // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler. // - ASSERT (CurrentStatement != NULL); - CurrentStatement->WriteExpression = CurrentExpression; + ASSERT (ParentStatement != NULL); + ParentStatement->WriteExpression = CurrentExpression; // // Take a look at next OpCode to see whether current expression consists @@ -2218,8 +2336,8 @@ ParseOpCodes ( // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR // file is wrongly generated by tools such as VFR Compiler. // - ASSERT (CurrentStatement != NULL); - ImageId = &CurrentStatement->ImageId; + ASSERT (ParentStatement != NULL); + ImageId = &ParentStatement->ImageId; break; } @@ -2231,16 +2349,16 @@ ParseOpCodes ( // Refresh // case EFI_IFR_REFRESH_OP: - ASSERT (CurrentStatement != NULL); - CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval; + ASSERT (ParentStatement != NULL); + ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval; break; // // Refresh guid. // case EFI_IFR_REFRESH_ID_OP: - ASSERT (CurrentStatement != NULL); - CopyMem (&CurrentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID)); + ASSERT (ParentStatement != NULL); + CopyMem (&ParentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID)); break; // @@ -2268,8 +2386,8 @@ ParseOpCodes ( break; default: - ASSERT (CurrentStatement != NULL); - CurrentStatement->Locked = TRUE; + ASSERT (ParentStatement != NULL); + ParentStatement->Locked = TRUE; } break; @@ -2289,6 +2407,13 @@ ParseOpCodes ( 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: @@ -2315,12 +2440,9 @@ ParseOpCodes ( CurrentOption = NULL; break; - case EFI_IFR_SUBTITLE_OP: - mInScopeSubtitle = FALSE; - break; - case EFI_IFR_NO_SUBMIT_IF_OP: case EFI_IFR_INCONSISTENT_IF_OP: + case EFI_IFR_WARNING_IF_OP: // // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF // @@ -2386,11 +2508,8 @@ ParseOpCodes ( return Status; } - if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; - } + OpCodeDisabled = IsTrue (&CurrentExpression->Result); - OpCodeDisabled = CurrentExpression->Result.Value.b; // // DisableIf Expression is only used once and not queued, free it // @@ -2409,6 +2528,17 @@ ParseOpCodes ( 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;