X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=EdkCompatibilityPkg%2FCompatibility%2FFrameworkHiiOnUefiHiiThunk%2FUefiIfrParser.c;fp=EdkCompatibilityPkg%2FCompatibility%2FFrameworkHiiOnUefiHiiThunk%2FUefiIfrParser.c;h=050c3c29b8ee0f737d09024e9919eeee9d455905;hb=4c9c0f719df00f211790eadf04d21a93a0cdf76c;hp=0000000000000000000000000000000000000000;hpb=96827f17562a5f055b7e14817f3388e881f33020;p=mirror_edk2.git diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.c new file mode 100644 index 0000000000..050c3c29b8 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.c @@ -0,0 +1,1089 @@ +/** @file +Parser for IFR binary encoding. + +Copyright (c) 2008, 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. + +**/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "UefiIfrParser.h" + +#include "UefiIfrParserExpression.h" + +UINT16 mStatementIndex; + +BOOLEAN mInScopeSubtitle; +BOOLEAN mInScopeSuppress; +BOOLEAN mInScopeGrayOut; + +EFI_GUID mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID; +extern EFI_GUID mTianoHiiIfrGuid; + +LIST_ENTRY * +GetOneOfOptionMapEntryListHead ( + IN CONST FORM_BROWSER_FORMSET *FormSet, + IN UINT16 QuestionId + ) +{ + LIST_ENTRY *Link; + ONE_OF_OPTION_MAP *Map; + + Link = GetFirstNode (&FormSet->OneOfOptionMapListHead); + + while (!IsNull (&FormSet->OneOfOptionMapListHead, Link)) { + Map = ONE_OF_OPTION_MAP_FROM_LINK (Link); + if (QuestionId == Map->QuestionId) { + return &Map->OneOfOptionMapEntryListHead; + } + Link = GetNextNode (&FormSet->OneOfOptionMapListHead, Link); + } + + return NULL; +} + +VOID +DestoryOneOfOptionMap ( + IN LIST_ENTRY *OneOfOptionMapListHead + ) +{ + ONE_OF_OPTION_MAP *Map; + ONE_OF_OPTION_MAP_ENTRY *MapEntry; + LIST_ENTRY *Link; + LIST_ENTRY *Link2; + + while (!IsListEmpty (OneOfOptionMapListHead)) { + Link = GetFirstNode (OneOfOptionMapListHead); + + Map = ONE_OF_OPTION_MAP_FROM_LINK (Link); + + while (!IsListEmpty (&Map->OneOfOptionMapEntryListHead)) { + Link2 = GetFirstNode (&Map->OneOfOptionMapEntryListHead); + + MapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2); + + RemoveEntryList (Link2); + + FreePool (MapEntry); + } + + RemoveEntryList (Link); + FreePool (Map); + } +} + + +/** + Initialize Statement header members. + + @param OpCodeData Pointer of the raw OpCode data. + @param FormSet Pointer of the current FormSe. + @param Form Pointer of the current Form. + + @return The Statement. + +**/ +FORM_BROWSER_STATEMENT * +CreateStatement ( + IN UINT8 *OpCodeData, + IN OUT FORM_BROWSER_FORMSET *FormSet, + IN OUT FORM_BROWSER_FORM *Form + ) +{ + FORM_BROWSER_STATEMENT *Statement; + EFI_IFR_STATEMENT_HEADER *StatementHdr; + + if (Form == NULL) { + // + // We are currently not in a Form Scope, so just skip this Statement + // + return NULL; + } + + Statement = &FormSet->StatementBuffer[mStatementIndex]; + mStatementIndex++; + + InitializeListHead (&Statement->DefaultListHead); + InitializeListHead (&Statement->OptionListHead); + + Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE; + + Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; + + 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)); + + Statement->InSubtitle = mInScopeSubtitle; + + // + // Insert this Statement into current Form + // + InsertTailList (&Form->StatementListHead, &Statement->Link); + + return Statement; +} + +/** + Initialize Question's members. + + @param OpCodeData Pointer of the raw OpCode data. + @param FormSet Pointer of the current FormSet. + @param Form Pointer of the current Form. + + @return The Question. + +**/ +FORM_BROWSER_STATEMENT * +CreateQuestion ( + IN UINT8 *OpCodeData, + IN OUT FORM_BROWSER_FORMSET *FormSet, + IN OUT FORM_BROWSER_FORM *Form + ) +{ + FORM_BROWSER_STATEMENT *Statement; + EFI_IFR_QUESTION_HEADER *QuestionHdr; + LIST_ENTRY *Link; + FORMSET_STORAGE *Storage; + + 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)); + + if (FormSet->MaxQuestionId < QuestionHdr->QuestionId) { + FormSet->MaxQuestionId = QuestionHdr->QuestionId; + } + + 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; + break; + } + + Link = GetNextNode (&FormSet->StorageListHead, Link); + } + ASSERT (Statement->Storage != NULL); + + return Statement; +} + +/** + Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List. + + @param FormSet Pointer of the current FormSet + + @return Pointer to a FORMSET_STORAGE data structure. + +**/ +FORMSET_STORAGE * +CreateStorage ( + IN FORM_BROWSER_FORMSET *FormSet + ) +{ + FORMSET_STORAGE *Storage; + + Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE)); + Storage->Signature = FORMSET_STORAGE_SIGNATURE; + InsertTailList (&FormSet->StorageListHead, &Storage->Link); + + return Storage; +} + +/** + Free resources of a storage + + @param Storage Pointer of the storage + + @return None. + +**/ +VOID +DestroyStorage ( + IN FORMSET_STORAGE *Storage + ) +{ + if (Storage == NULL) { + return; + } + + if (Storage->Name!= NULL) { + FreePool (Storage->Name); + } + + FreePool (Storage); +} + + +/** + Free resources of a Statement + + @param Statement Pointer of the Statement + + @return None. + +**/ +VOID +DestroyStatement ( + IN OUT FORM_BROWSER_STATEMENT *Statement + ) +{ + LIST_ENTRY *Link; + QUESTION_DEFAULT *Default; + QUESTION_OPTION *Option; + + // + // Free Default value List + // + while (!IsListEmpty (&Statement->DefaultListHead)) { + Link = GetFirstNode (&Statement->DefaultListHead); + Default = QUESTION_DEFAULT_FROM_LINK (Link); + RemoveEntryList (&Default->Link); + + gBS->FreePool (Default); + } + + // + // Free Options List + // + while (!IsListEmpty (&Statement->OptionListHead)) { + Link = GetFirstNode (&Statement->OptionListHead); + Option = QUESTION_OPTION_FROM_LINK (Link); + RemoveEntryList (&Option->Link); + + gBS->FreePool (Option); + } + +} + + + +/** + Free resources of a Form + + @param Form Pointer of the Form + + @return None. + +**/ +VOID +DestroyForm ( + IN OUT FORM_BROWSER_FORM *Form + ) +{ + LIST_ENTRY *Link; + FORM_BROWSER_STATEMENT *Statement; + + // + // Free Statements/Questions + // + while (!IsListEmpty (&Form->StatementListHead)) { + Link = GetFirstNode (&Form->StatementListHead); + Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); + RemoveEntryList (&Statement->Link); + + DestroyStatement (Statement); + } + + // + // Free this Form + // + gBS->FreePool (Form); +} + + +/** + Free resources allocated for a FormSet + + @param FormSet Pointer of the FormSet + + @return None. + +**/ +VOID +DestroyFormSet ( + IN OUT FORM_BROWSER_FORMSET *FormSet + ) +{ + LIST_ENTRY *Link; + FORMSET_STORAGE *Storage; + FORMSET_DEFAULTSTORE *DefaultStore; + FORM_BROWSER_FORM *Form; + + // + // 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); + + gBS->FreePool (DefaultStore); + } + } + + // + // 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 (Form); + } + } + + if (FormSet->StatementBuffer != NULL) { + FreePool (FormSet->StatementBuffer); + } + + DestoryOneOfOptionMap (&FormSet->OneOfOptionMapListHead); + + if (FormSet->OriginalDefaultVarStoreName != NULL) { + FreePool (FormSet->OriginalDefaultVarStoreName); + } + + 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_SPAN_OP)) || + (Operand == EFI_IFR_CATENATE_OP) + ) { + return TRUE; + } else { + return FALSE; + } +} + + +/** + Calculate number of Statemens(Questions) and Expression OpCodes. + + @param FormSet The FormSet to be counted. + @param NumberOfStatement Number of Statemens(Questions) + @param NumberOfExpression Number of Expression OpCodes + + @return None. + +**/ +VOID +CountOpCodes ( + IN FORM_BROWSER_FORMSET *FormSet, + IN OUT UINT16 *NumberOfStatement, + IN OUT UINT16 *NumberOfExpression + ) +{ + UINT16 StatementCount; + UINT16 ExpressionCount; + UINT8 *OpCodeData; + UINTN Offset; + UINTN OpCodeLen; + + Offset = 0; + StatementCount = 0; + ExpressionCount = 0; + + while (Offset < FormSet->IfrBinaryLength) { + OpCodeData = FormSet->IfrBinaryData + Offset; + OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + Offset += OpCodeLen; + + if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) { + ExpressionCount++; + } else { + StatementCount++; + } + } + + *NumberOfStatement = StatementCount; + *NumberOfExpression = ExpressionCount; +} + + +/** + Parse opcodes in the formset IFR binary. + + @param FormSet Pointer of the FormSet data structure. + + @retval EFI_SUCCESS Opcode parse success. + @retval Other Opcode parse fail. + +**/ +EFI_STATUS +ParseOpCodes ( + IN FORM_BROWSER_FORMSET *FormSet + ) +{ + EFI_STATUS Status; + UINT16 Index; + FORM_BROWSER_FORM *CurrentForm; + FORM_BROWSER_STATEMENT *CurrentStatement; + UINT8 Operand; + UINT8 Scope; + UINTN OpCodeOffset; + UINTN OpCodeLength; + UINT8 *OpCodeData; + UINT8 ScopeOpCode; + FORMSET_STORAGE *Storage; + FORMSET_DEFAULTSTORE *DefaultStore; + QUESTION_DEFAULT *CurrentDefault; + QUESTION_OPTION *CurrentOption; + CHAR8 *AsciiString; + UINT16 NumberOfStatement; + UINT16 NumberOfExpression; + EFI_IMAGE_ID *ImageId; + EFI_HII_VALUE *Value; + LIST_ENTRY *OneOfOptinMapEntryListHead; + EFI_IFR_GUID_OPTIONKEY *OptionMap; + ONE_OF_OPTION_MAP *OneOfOptionMap; + ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry; + UINT8 OneOfType; + EFI_IFR_ONE_OF *OneOfOpcode; + + mInScopeSubtitle = FALSE; + mInScopeSuppress = FALSE; + mInScopeGrayOut = FALSE; + CurrentDefault = NULL; + CurrentOption = NULL; + + // + // Set to a invalid value. + // + OneOfType = (UINT8) -1; + + // + // Get the number of Statements and Expressions + // + CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression); + FormSet->NumberOfStatement = NumberOfStatement; + + mStatementIndex = 0; + FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT)); + if (FormSet->StatementBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + InitializeListHead (&FormSet->StorageListHead); + InitializeListHead (&FormSet->DefaultStoreListHead); + InitializeListHead (&FormSet->FormListHead); + InitializeListHead (&FormSet->OneOfOptionMapListHead); + + CurrentForm = NULL; + CurrentStatement = NULL; + + ResetScopeStack (); + + OpCodeOffset = 0; + while (OpCodeOffset < FormSet->IfrBinaryLength) { + OpCodeData = FormSet->IfrBinaryData + OpCodeOffset; + + OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + OpCodeOffset += OpCodeLength; + Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; + Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope; + + // + // If scope bit set, push onto scope stack + // + if (Scope) { + PushScope (Operand); + } + + if (IsExpressionOpCode (Operand)) { + continue; + } + + // + // Parse the Opcode + // + switch (Operand) { + + case EFI_IFR_FORM_SET_OP: + // + // check the formset GUID + // + if (!CompareGuid ((EFI_GUID *)(VOID *)&FormSet->Guid, (EFI_GUID *)(VOID *)&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)) { + 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)); + break; + + case EFI_IFR_FORM_OP: + // + // Create a new Form for this FormSet + // + CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM)); + CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE; + + InitializeListHead (&CurrentForm->StatementListHead); + + CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16)); + CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID)); + + // + // Insert into Form list of this FormSet + // + InsertTailList (&FormSet->FormListHead, &CurrentForm->Link); + break; + + // + // Storage + // + case EFI_IFR_VARSTORE_OP: + // + // Create a buffer Storage for this FormSet + // + Storage = CreateStorage (FormSet); + Storage->Type = EFI_HII_VARSTORE_BUFFER; + + CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID)); + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID)); + CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16)); + + AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name; + Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2); + ASSERT (Storage->Name != NULL); + for (Index = 0; AsciiString[Index] != 0; Index++) { + Storage->Name[Index] = (CHAR16) AsciiString[Index]; + } + + break; + + case EFI_IFR_VARSTORE_NAME_VALUE_OP: + ASSERT (FALSE); + + break; + + case EFI_IFR_VARSTORE_EFI_OP: + // + // Create a EFI variable Storage for this FormSet + // + Storage = CreateStorage (FormSet); + Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE; + + CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID)); + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID)); + CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32)); + break; + + // + // DefaultStore + // + case EFI_IFR_DEFAULTSTORE_OP: + DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE)); + 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 to DefaultStore list of this Formset + // + InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link); + break; + + // + // Statements + // + case EFI_IFR_SUBTITLE_OP: + CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm); + CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags; + + if (Scope) { + mInScopeSubtitle = TRUE; + } + break; + + case EFI_IFR_TEXT_OP: + CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm); + + CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID)); + break; + + // + // Questions + // + case EFI_IFR_ACTION_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + 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_RESET_BUTTON_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID)); + break; + + case EFI_IFR_REF_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID)); + if (OpCodeLength >= sizeof (EFI_IFR_REF2)) { + CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID)); + + if (OpCodeLength >= sizeof (EFI_IFR_REF3)) { + CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID)); + + if (OpCodeLength >= sizeof (EFI_IFR_REF4)) { + CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID)); + } + } + } + break; + + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_NUMERIC_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags; + Value = &CurrentStatement->HiiValue; + + 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 = 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 = 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 = 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 = sizeof (UINT64); + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; + break; + + default: + break; + } + + if (Operand == EFI_IFR_ONE_OF_OP) { + OneOfOpcode = (EFI_IFR_ONE_OF *) OpCodeData; + OneOfType = (UINT8) (OneOfOpcode->Flags & EFI_IFR_NUMERIC_SIZE); + } + break; + + case EFI_IFR_ORDERED_LIST_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags; + CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers; + CurrentStatement->StorageWidth = (UINT16)(CurrentStatement->MaxContainers * sizeof (UINT8)); + + // + // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver + // has to use FormBrowser2.Callback() to retrieve the uncommited data for + // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set). + // + CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER; + CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth); + + break; + + case EFI_IFR_CHECKBOX_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags; + CurrentStatement->StorageWidth = sizeof (BOOLEAN); + CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN; + + break; + + case EFI_IFR_STRING_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + // + // 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 (UINT16)); + CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags; + + CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING; + CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth); + + break; + + case EFI_IFR_PASSWORD_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + // + // 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 (UINT16)); + + CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING; + CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth); + + break; + + case EFI_IFR_DATE_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags; + CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE; + + break; + + case EFI_IFR_TIME_OP: + CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm); + + CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags; + CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME; + + 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)); + CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE; + + CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type; + CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16)); + CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE)); + ExtendValueToU64 (&CurrentDefault->Value); + + // + // Insert to Default Value list of current Question + // + InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link); + + break; + + // + // Option + // + case EFI_IFR_ONE_OF_OPTION_OP: + // + // 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)); + CurrentOption->Signature = QUESTION_OPTION_SIGNATURE; + + CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags; + CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type; + CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID)); + CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE)); + ExtendValueToU64 (&CurrentOption->Value); + + // + // Insert to Option list of current Question + // + InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link); + break; + + // + // Conditional + // + case EFI_IFR_NO_SUBMIT_IF_OP: + case EFI_IFR_INCONSISTENT_IF_OP: + break; + + case EFI_IFR_SUPPRESS_IF_OP: + break; + + case EFI_IFR_GRAY_OUT_IF_OP: + break; + + case EFI_IFR_DISABLE_IF_OP: + ASSERT (FALSE); + + + // + // Expression + // + case EFI_IFR_VALUE_OP: + break; + + case EFI_IFR_RULE_OP: + 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: + ImageId = &CurrentForm->ImageId; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + ImageId = &CurrentOption->ImageId; + break; + + default: + ImageId = &CurrentStatement->ImageId; + break; + } + + CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID)); + break; + + // + // Refresh + // + case EFI_IFR_REFRESH_OP: + CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval; + break; + + // + // Vendor specific + // + case EFI_IFR_GUID_OP: + OptionMap = (EFI_IFR_GUID_OPTIONKEY *) OpCodeData; + + if (CompareGuid (&mTianoHiiIfrGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { + // + // Tiano specific GUIDed opcodes + // + switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) { + case EFI_IFR_EXTEND_OP_LABEL: + // + // just ignore label + // + break; + + + case EFI_IFR_EXTEND_OP_CLASS: + CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16)); + break; + + case EFI_IFR_EXTEND_OP_SUBCLASS: + CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16)); + break; + + default: + break; + } + } + else if (CompareGuid ((EFI_GUID *)(VOID *)&OptionMap->Guid, &mFrameworkHiiCompatibilityGuid)) { + if (OptionMap->ExtendOpCode == EFI_IFR_EXTEND_OP_OPTIONKEY) { + OneOfOptinMapEntryListHead = GetOneOfOptionMapEntryListHead (FormSet, OptionMap->QuestionId); + if (OneOfOptinMapEntryListHead == NULL) { + OneOfOptionMap = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP)); + ASSERT (OneOfOptionMap != NULL); + + OneOfOptionMap->Signature = ONE_OF_OPTION_MAP_SIGNATURE; + OneOfOptionMap->QuestionId = OptionMap->QuestionId; + + // + // Make sure OneOfType is initialized. + // + ASSERT (OneOfType != (UINT8) -1); + OneOfOptionMap->ValueType = OneOfType; + InitializeListHead (&OneOfOptionMap->OneOfOptionMapEntryListHead); + OneOfOptinMapEntryListHead = &OneOfOptionMap->OneOfOptionMapEntryListHead; + InsertTailList (&FormSet->OneOfOptionMapListHead, &OneOfOptionMap->Link); + } + OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY)); + ASSERT (OneOfOptionMapEntry != NULL); + + OneOfOptionMapEntry->Signature = ONE_OF_OPTION_MAP_ENTRY_SIGNATURE; + OneOfOptionMapEntry->FwKey = OptionMap->KeyValue; + CopyMem (&OneOfOptionMapEntry->Value, &OptionMap->OptionValue, sizeof (EFI_IFR_TYPE_VALUE)); + + InsertTailList (OneOfOptinMapEntryListHead, &OneOfOptionMapEntry->Link); + } + } + break; + + // + // Scope End + // + case EFI_IFR_END_OP: + Status = PopScope (&ScopeOpCode); + if (EFI_ERROR (Status)) { + ResetScopeStack (); + return Status; + } + + switch (ScopeOpCode) { + case EFI_IFR_FORM_SET_OP: + // + // End of FormSet, update FormSet IFR binary length + // to stop parsing substantial OpCodes + // + FormSet->IfrBinaryLength = OpCodeOffset; + break; + + case EFI_IFR_FORM_OP: + // + // End of Form + // + CurrentForm = NULL; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + // + // End of Option + // + CurrentOption = NULL; + break; + + case EFI_IFR_SUBTITLE_OP: + mInScopeSubtitle = FALSE; + break; + + case EFI_IFR_NO_SUBMIT_IF_OP: + case EFI_IFR_INCONSISTENT_IF_OP: + // + // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF + // + break; + + case EFI_IFR_GRAY_OUT_IF_OP: + mInScopeGrayOut = FALSE; + break; + + default: + if (IsExpressionOpCode (ScopeOpCode)) { + } + break; + } + break; + + default: + break; + } + } + + return EFI_SUCCESS; +} + + + +