diff options
Diffstat (limited to 'MdeModulePkg')
-rw-r--r-- | MdeModulePkg/Universal/SetupBrowserDxe/Colors.h | 96 | ||||
-rw-r--r-- | MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c | 3430 | ||||
-rw-r--r-- | MdeModulePkg/Universal/SetupBrowserDxe/Print.h | 60 | ||||
-rw-r--r-- | MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c | 1942 |
4 files changed, 2764 insertions, 2764 deletions
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h index 94c3368..aeff29b 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h @@ -1,48 +1,48 @@ -/** @file -MACRO definitions for color used in Setup Browser. - -Copyright (c) 2004, 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. - -**/ -// -// Unicode collation protocol in - -#ifndef _COLORS_H_ -#define _COLORS_H_ - -// -// Screen Color Settings -// -#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE -#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN -#define TITLE_TEXT EFI_WHITE -#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE -#define KEYHELP_TEXT EFI_LIGHTGRAY -#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK -#define SUBTITLE_TEXT EFI_BLUE -#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY -#define BANNER_TEXT EFI_BLUE -#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY -#define FIELD_TEXT EFI_BLACK -#define FIELD_TEXT_GRAYED EFI_DARKGRAY -#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY -#define FIELD_TEXT_HIGHLIGHT EFI_LIGHTGRAY -#define FIELD_BACKGROUND_HIGHLIGHT EFI_BACKGROUND_BLACK -#define POPUP_TEXT EFI_LIGHTGRAY -#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE -#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY -#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK -#define HELP_TEXT EFI_BLUE -#define ERROR_TEXT EFI_RED | EFI_BRIGHT -#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT -#define ARROW_TEXT EFI_RED | EFI_BRIGHT -#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY - -#endif +/** @file
+MACRO definitions for color used in Setup Browser.
+
+Copyright (c) 2004, 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.
+
+**/
+//
+// Unicode collation protocol in
+
+#ifndef _COLORS_H_
+#define _COLORS_H_
+
+//
+// Screen Color Settings
+//
+#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE
+#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN
+#define TITLE_TEXT EFI_WHITE
+#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE
+#define KEYHELP_TEXT EFI_LIGHTGRAY
+#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK
+#define SUBTITLE_TEXT EFI_BLUE
+#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+#define BANNER_TEXT EFI_BLUE
+#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+#define FIELD_TEXT EFI_BLACK
+#define FIELD_TEXT_GRAYED EFI_DARKGRAY
+#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+#define FIELD_TEXT_HIGHLIGHT EFI_LIGHTGRAY
+#define FIELD_BACKGROUND_HIGHLIGHT EFI_BACKGROUND_BLACK
+#define POPUP_TEXT EFI_LIGHTGRAY
+#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE
+#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY
+#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK
+#define HELP_TEXT EFI_BLUE
+#define ERROR_TEXT EFI_RED | EFI_BRIGHT
+#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT
+#define ARROW_TEXT EFI_RED | EFI_BRIGHT
+#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+
+#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c index f640d12..cde8d6f 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c @@ -1,1715 +1,1715 @@ -/** @file -Parser for IFR binary encoding. - -Copyright (c) 2007 - 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 "Setup.h" -#include "Ui.h" - -UINT16 mStatementIndex; -UINT16 mExpressionOpCodeIndex; - -BOOLEAN mInScopeSubtitle; -BOOLEAN mInScopeSuppress; -BOOLEAN mInScopeGrayOut; -FORM_EXPRESSION *mSuppressExpression; -FORM_EXPRESSION *mGrayOutExpression; - -EFI_GUID gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID; -GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID; - - -/** - Initialize Statement header members. - - @param OpCodeData Pointer of the raw OpCode data. - @param FormSet Pointer of the current FormSe. - @param Form Pointer of the current Form. - - @return The Statement. - -**/ -FORM_BROWSER_STATEMENT * -CreateStatement ( - IN UINT8 *OpCodeData, - IN OUT FORM_BROWSER_FORMSET *FormSet, - IN OUT FORM_BROWSER_FORM *Form - ) -{ - FORM_BROWSER_STATEMENT *Statement; - EFI_IFR_STATEMENT_HEADER *StatementHdr; - - if (Form == NULL) { - // - // We are currently not in a Form Scope, so just skip this Statement - // - return NULL; - } - - Statement = &FormSet->StatementBuffer[mStatementIndex]; - mStatementIndex++; - - InitializeListHead (&Statement->DefaultListHead); - InitializeListHead (&Statement->OptionListHead); - InitializeListHead (&Statement->InconsistentListHead); - InitializeListHead (&Statement->NoSubmitListHead); - - 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)); - - if (mInScopeSuppress) { - Statement->SuppressExpression = mSuppressExpression; - } - - if (mInScopeGrayOut) { - Statement->GrayOutExpression = mGrayOutExpression; - } - - Statement->InSubtitle = mInScopeSubtitle; - - // - // Insert this Statement into current Form - // - InsertTailList (&Form->StatementListHead, &Statement->Link); - - return Statement; -} - -EFI_STATUS -UpdateCheckBoxStringToken ( - IN CONST FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_STATEMENT *Statement - ) -{ - CHAR16 Str[MAXIMUM_VALUE_CHARACTERS]; - EFI_STRING_ID Id; - EFI_STATUS Status; - - ASSERT (Statement != NULL); - ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP); - - UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1); - - Status = HiiLibNewString (FormSet->HiiHandle, &Id, Str); - - if (EFI_ERROR (Status)) { - return Status; - } - - Statement->VarStoreInfo.VarName = Id; - - return EFI_SUCCESS; -} - -BOOLEAN -IsNextOpCodeGuidedVarEqName ( - UINT8 *OpCodeData - ) -{ - // - // Get next opcode - // - OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - if (*OpCodeData == EFI_IFR_GUID_OP) { - if (CompareGuid (&mFrameworkHiiCompatibilityGuid, (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; - } - } - } - - return FALSE; -} - -/** - 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; - EFI_STATUS Status; - - 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; - } - - // - // Take a look at next OpCode to see whether it is a GUIDed opcode to support - // Framework Compatibility - // - if (FeaturePcdGet (PcdFrameworkHiiCompatibilitySupport)) { - if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) { - Status = UpdateCheckBoxStringToken (FormSet, Statement); - if (EFI_ERROR (Status)) { - return NULL; - } - } - } - - // - // 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); - - // - // 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) { - // - // 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 - - @return Pointer to a FORM_EXPRESSION data structure. - -**/ -FORM_EXPRESSION * -CreateExpression ( - IN OUT FORM_BROWSER_FORM *Form - ) -{ - FORM_EXPRESSION *Expression; - - Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION)); - Expression->Signature = FORM_EXPRESSION_SIGNATURE; - InitializeListHead (&Expression->OpCodeListHead); - - return Expression; -} - - -/** - Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List. - - @param FormSet Pointer of the current FormSet - - @return Pointer to a FORMSET_STORAGE data structure. - -**/ -FORMSET_STORAGE * -CreateStorage ( - IN FORM_BROWSER_FORMSET *FormSet - ) -{ - FORMSET_STORAGE *Storage; - - Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE)); - Storage->Signature = FORMSET_STORAGE_SIGNATURE; - InitializeListHead (&Storage->NameValueListHead); - InsertTailList (&FormSet->StorageListHead, &Storage->Link); - - return Storage; -} - - -/** - 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 - ) -{ - EFI_STATUS Status; - UINTN StrBufferLen; - CHAR16 *Name; - - if (Storage->Type == EFI_HII_VARSTORE_BUFFER) { - Name = Storage->Name; - } else { - Name = NULL; - } - - StrBufferLen = 0; - Status = ConstructConfigHdr ( - Storage->ConfigHdr, - &StrBufferLen, - &Storage->Guid, - Name, - FormSet->DriverHandle - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - Storage->ConfigHdr = AllocateZeroPool (StrBufferLen); - Status = ConstructConfigHdr ( - Storage->ConfigHdr, - &StrBufferLen, - &Storage->Guid, - Name, - FormSet->DriverHandle - ); - } - - if (EFI_ERROR (Status)) { - return Status; - } - - Storage->ConfigRequest = AllocateCopyPool (StrBufferLen, Storage->ConfigHdr); - Storage->SpareStrLen = 0; - - return EFI_SUCCESS; -} - - -/** - Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label> - - @param FormSet Pointer of the current FormSet. - @param Question The Question to be initialized. - - @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 - ) -{ - FORMSET_STORAGE *Storage; - UINTN StrLen; - UINTN StringSize; - CHAR16 *NewStr; - CHAR16 RequestElement[30]; - - 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) { - StrLen = UnicodeSPrint ( - RequestElement, - 30 * sizeof (CHAR16), - L"&OFFSET=%x&WIDTH=%x", - Question->VarStoreInfo.VarOffset, - Question->StorageWidth - ); - 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; - } - - // - // Append <RequestElement> to <ConfigRequest> - // - if (StrLen > Storage->SpareStrLen) { - // - // Old String buffer is not sufficient for RequestElement, allocate a new one - // - StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16); - NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16)); - if (Storage->ConfigRequest != NULL) { - CopyMem (NewStr, Storage->ConfigRequest, StringSize); - gBS->FreePool (Storage->ConfigRequest); - } - Storage->ConfigRequest = NewStr; - Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL; - } - - StrCat (Storage->ConfigRequest, RequestElement); - Storage->ElementCount++; - Storage->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; - - while (!IsListEmpty (&Expression->OpCodeListHead)) { - Link = GetFirstNode (&Expression->OpCodeListHead); - OpCode = EXPRESSION_OPCODE_FROM_LINK (Link); - RemoveEntryList (&OpCode->Link); - - if (OpCode->ValueList != NULL) { - FreePool (OpCode->ValueList); - } - } - - // - // Free this Expression - // - gBS->FreePool (Expression); -} - - -/** - Free resources of a storage. - - @param Storage Pointer of the storage - -**/ -VOID -DestroyStorage ( - IN FORMSET_STORAGE *Storage - ) -{ - LIST_ENTRY *Link; - NAME_VALUE_NODE *NameValueNode; - - if (Storage == NULL) { - return; - } - - if (Storage->Name != NULL) { - FreePool (Storage->Name); - } - if (Storage->Buffer != NULL) { - FreePool (Storage->Buffer); - } - if (Storage->EditBuffer != NULL) { - FreePool (Storage->EditBuffer); - } - - while (!IsListEmpty (&Storage->NameValueListHead)) { - Link = GetFirstNode (&Storage->NameValueListHead); - NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link); - RemoveEntryList (&NameValueNode->Link); - - if (NameValueNode->Name != NULL) { - FreePool (NameValueNode->Name); - } - if (NameValueNode->Value != NULL) { - FreePool (NameValueNode->Value); - } - if (NameValueNode->EditValue != NULL) { - FreePool (NameValueNode->EditValue); - } - FreePool (NameValueNode); - } - - if (Storage->ConfigHdr != NULL) { - FreePool (Storage->ConfigHdr); - } - if (Storage->ConfigRequest != NULL) { - FreePool (Storage->ConfigRequest); - } - - FreePool (Storage); -} - - -/** - Free resources of a Statement. - - @param Statement Pointer of the Statement - -**/ -VOID -DestroyStatement ( - 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); - - 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 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); - } - - if (Statement->VariableName != NULL) { - FreePool (Statement->VariableName); - } - if (Statement->BlockName != NULL) { - FreePool (Statement->BlockName); - } -} - - -/** - Free resources of a Form. - - @param Form Pointer of the Form. - -**/ -VOID -DestroyForm ( - IN OUT FORM_BROWSER_FORM *Form - ) -{ - LIST_ENTRY *Link; - FORM_EXPRESSION *Expression; - FORM_BROWSER_STATEMENT *Statement; - - // - // Free Form Expressions - // - while (!IsListEmpty (&Form->ExpressionListHead)) { - Link = GetFirstNode (&Form->ExpressionListHead); - Expression = FORM_EXPRESSION_FROM_LINK (Link); - RemoveEntryList (&Expression->Link); - - DestroyExpression (Expression); - } - - // - // Free Statements/Questions - // - while (!IsListEmpty (&Form->StatementListHead)) { - Link = GetFirstNode (&Form->StatementListHead); - Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - RemoveEntryList (&Statement->Link); - - DestroyStatement (Statement); - } - - // - // Free this Form - // - gBS->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_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); - } - 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_SPAN_OP)) || - (Operand == EFI_IFR_CATENATE_OP) || - (Operand == EFI_IFR_TO_LOWER_OP) || - (Operand == EFI_IFR_TO_UPPER_OP) || - (Operand == EFI_IFR_VERSION_OP) - ) { - return TRUE; - } else { - return FALSE; - } -} - - -/** - Calculate number of Statemens(Questions) and Expression OpCodes. - - @param FormSet The FormSet to be counted. - @param NumberOfStatement Number of Statemens(Questions) - @param NumberOfExpression Number of Expression OpCodes - -**/ -VOID -CountOpCodes ( - IN FORM_BROWSER_FORMSET *FormSet, - IN OUT UINT16 *NumberOfStatement, - IN OUT UINT16 *NumberOfExpression - ) -{ - UINT16 StatementCount; - UINT16 ExpressionCount; - UINT8 *OpCodeData; - UINTN Offset; - UINTN OpCodeLen; - - Offset = 0; - StatementCount = 0; - ExpressionCount = 0; - - while (Offset < FormSet->IfrBinaryLength) { - OpCodeData = FormSet->IfrBinaryData + Offset; - OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - Offset += OpCodeLen; - - if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) { - ExpressionCount++; - } else { - StatementCount++; - } - } - - *NumberOfStatement = StatementCount; - *NumberOfExpression = ExpressionCount; -} - - - -/** - Parse opcodes in the formset IFR binary. - - @param FormSet Pointer of the FormSet data structure. - - @retval EFI_SUCCESS Opcode parse success. - @retval Other Opcode parse fail. - -**/ -EFI_STATUS -ParseOpCodes ( - IN FORM_BROWSER_FORMSET *FormSet - ) -{ - EFI_STATUS Status; - UINT16 Index; - FORM_BROWSER_FORM *CurrentForm; - FORM_BROWSER_STATEMENT *CurrentStatement; - EXPRESSION_OPCODE *ExpressionOpCode; - FORM_EXPRESSION *CurrentExpression; - UINT8 Operand; - UINT8 Scope; - UINTN OpCodeOffset; - UINTN OpCodeLength; - UINT8 *OpCodeData; - UINT8 ScopeOpCode; - FORMSET_STORAGE *Storage; - FORMSET_DEFAULTSTORE *DefaultStore; - QUESTION_DEFAULT *CurrentDefault; - QUESTION_OPTION *CurrentOption; - CHAR8 *AsciiString; - UINT16 NumberOfStatement; - UINT16 NumberOfExpression; - EFI_IMAGE_ID *ImageId; - BOOLEAN SuppressForOption; - BOOLEAN InScopeOptionSuppress; - FORM_EXPRESSION *OptionSuppressExpression; - BOOLEAN InScopeDisable; - UINT16 DepthOfDisable; - BOOLEAN OpCodeDisabled; - BOOLEAN SingleOpCodeExpression; - BOOLEAN InScopeDefault; - EFI_HII_VALUE *Value; - - mInScopeSubtitle = FALSE; - SuppressForOption = FALSE; - mInScopeSuppress = FALSE; - InScopeOptionSuppress = FALSE; - mInScopeGrayOut = FALSE; - InScopeDisable = FALSE; - DepthOfDisable = 0; - OpCodeDisabled = FALSE; - SingleOpCodeExpression = FALSE; - InScopeDefault = FALSE; - CurrentExpression = NULL; - CurrentDefault = NULL; - CurrentOption = NULL; - OptionSuppressExpression = NULL; - - // - // Get the number of Statements and Expressions - // - CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression); - - mStatementIndex = 0; - FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT)); - if (FormSet->StatementBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - mExpressionOpCodeIndex = 0; - FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE)); - if (FormSet->ExpressionBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - InitializeListHead (&FormSet->StorageListHead); - InitializeListHead (&FormSet->DefaultStoreListHead); - InitializeListHead (&FormSet->FormListHead); - - CurrentForm = NULL; - CurrentStatement = NULL; - - ResetScopeStack (); - - OpCodeOffset = 0; - while (OpCodeOffset < FormSet->IfrBinaryLength) { - OpCodeData = FormSet->IfrBinaryData + OpCodeOffset; - - OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - OpCodeOffset += OpCodeLength; - Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; - Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope; - - // - // If scope bit set, push onto scope stack - // - if (Scope != 0) { - PushScope (Operand); - } - - if (OpCodeDisabled) { - // - // DisableIf Expression is evaluated to be TRUE, try to find its end. - // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END - // - if (Operand == EFI_IFR_DISABLE_IF_OP) { - DepthOfDisable++; - } else if (Operand == EFI_IFR_END_OP) { - Status = PopScope (&ScopeOpCode); - if (EFI_ERROR (Status)) { - return Status; - } - - if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) { - if (DepthOfDisable == 0) { - 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_LIST_OP: - CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID)); - CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ListLength, sizeof (UINT16)); - ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_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: - ExpressionOpCode->QuestionId = CurrentStatement->QuestionId; - break; - - case EFI_IFR_QUESTION_REF1_OP: - CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_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_OTHER; - break; - - case EFI_IFR_VERSION_OP: - Value->Type = EFI_IFR_TYPE_NUM_SIZE_16; - Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION; - break; - - default: - break; - } - - InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link); - - 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) { - // - // Evaluate DisableIf expression - // - Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression); - if (EFI_ERROR (Status)) { - return Status; - } - if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; - } - - OpCodeDisabled = CurrentExpression->Result.Value.b; - } - - 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)); - 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->ExpressionListHead); - 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)); - - Storage->Buffer = AllocateZeroPool (Storage->Size); - Storage->EditBuffer = AllocateZeroPool (Storage->Size); - - 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]; - } - - // - // Initialize <ConfigHdr> - // - InitializeConfigHdr (FormSet, Storage); - break; - - case EFI_IFR_VARSTORE_NAME_VALUE_OP: - // - // Create a name/value Storage for this FormSet - // - Storage = CreateStorage (FormSet); - Storage->Type = EFI_HII_VARSTORE_NAME_VALUE; - - CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID)); - CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID)); - - // - // Initialize <ConfigHdr> - // - InitializeConfigHdr (FormSet, Storage); - 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 != 0) { - 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; - } - - InitializeRequestElement (FormSet, CurrentStatement); - - if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) { - SuppressForOption = TRUE; - } - 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)); - InitializeRequestElement (FormSet, CurrentStatement); - - // - // 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); - - if (Scope != 0) { - SuppressForOption = TRUE; - } - 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; - - InitializeRequestElement (FormSet, CurrentStatement); - - 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 (CHAR16)); - CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags; - - CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING; - CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16)); - - InitializeRequestElement (FormSet, CurrentStatement); - 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 (CHAR16)); - - CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING; - CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16))); - - InitializeRequestElement (FormSet, CurrentStatement); - 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; - - if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) { - CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE); - - InitializeRequestElement (FormSet, CurrentStatement); - } 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); - - 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 = sizeof (EFI_IFR_TIME); - - InitializeRequestElement (FormSet, CurrentStatement); - } 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)); - 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); - - if (Scope != 0) { - InScopeDefault = TRUE; - } - 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); - - if (InScopeOptionSuppress) { - CurrentOption->SuppressExpression = OptionSuppressExpression; - } - - // - // 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: - // - // Create an Expression node - // - CurrentExpression = CreateExpression (CurrentForm); - CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID)); - - if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) { - CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF; - InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link); - } else { - CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF; - InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link); - } - break; - - case EFI_IFR_SUPPRESS_IF_OP: - // - // Question and Option will appear in scope of this OpCode - // - CurrentExpression = CreateExpression (CurrentForm); - CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF; - InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); - - if (SuppressForOption) { - InScopeOptionSuppress = TRUE; - OptionSuppressExpression = CurrentExpression; - } else { - mInScopeSuppress = TRUE; - mSuppressExpression = CurrentExpression; - } - break; - - case EFI_IFR_GRAY_OUT_IF_OP: - // - // Questions will appear in scope of this OpCode - // - CurrentExpression = CreateExpression (CurrentForm); - CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF; - InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); - - mInScopeGrayOut = TRUE; - mGrayOutExpression = CurrentExpression; - 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)); - CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE; - CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF; - InitializeListHead (&CurrentExpression->OpCodeListHead); - - InScopeDisable = TRUE; - OpCodeDisabled = FALSE; - - // - // Take a look at next OpCode to see whether current expression consists - // of single OpCode - // - if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) { - SingleOpCodeExpression = TRUE; - } - break; - - // - // Expression - // - case EFI_IFR_VALUE_OP: - CurrentExpression = CreateExpression (CurrentForm); - CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE; - InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); - - if (InScopeDefault) { - // - // Used for default (EFI_IFR_DEFAULT) - // - CurrentDefault->ValueExpression = CurrentExpression; - } else { - // - // If used for a question, then the question will be read-only - // - CurrentStatement->ValueExpression = CurrentExpression; - } - break; - - case EFI_IFR_RULE_OP: - CurrentExpression = CreateExpression (CurrentForm); - CurrentExpression->Type = EFI_HII_EXPRESSION_RULE; - - CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId; - InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); - 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: - if (CompareGuid (&gTianoHiiIfrGuid, (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_BANNER: - if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) { - CopyMem ( - &BannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][ - ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment], - &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title, - sizeof (EFI_STRING_ID) - ); - } - 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; - } - } - - 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_SUPPRESS_IF_OP: - if (SuppressForOption) { - InScopeOptionSuppress = FALSE; - } else { - mInScopeSuppress = FALSE; - } - break; - - case EFI_IFR_GRAY_OUT_IF_OP: - mInScopeGrayOut = FALSE; - break; - - case EFI_IFR_DISABLE_IF_OP: - 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; - - default: - if (IsExpressionOpCode (ScopeOpCode)) { - if (InScopeDisable) { - // - // Evaluate DisableIf expression - // - Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression); - if (EFI_ERROR (Status)) { - return Status; - } - if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; - } - - OpCodeDisabled = CurrentExpression->Result.Value.b; - // - // DisableIf Expression is only used once and not quequed, free it - // - DestroyExpression (CurrentExpression); - } - - // - // End of current Expression - // - CurrentExpression = NULL; - } - break; - } - break; - - default: - break; - } - } - - return EFI_SUCCESS; -} +/** @file
+Parser for IFR binary encoding.
+
+Copyright (c) 2007 - 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 "Setup.h"
+#include "Ui.h"
+
+UINT16 mStatementIndex;
+UINT16 mExpressionOpCodeIndex;
+
+BOOLEAN mInScopeSubtitle;
+BOOLEAN mInScopeSuppress;
+BOOLEAN mInScopeGrayOut;
+FORM_EXPRESSION *mSuppressExpression;
+FORM_EXPRESSION *mGrayOutExpression;
+
+EFI_GUID gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID;
+
+
+/**
+ Initialize Statement header members.
+
+ @param OpCodeData Pointer of the raw OpCode data.
+ @param FormSet Pointer of the current FormSe.
+ @param Form Pointer of the current Form.
+
+ @return The Statement.
+
+**/
+FORM_BROWSER_STATEMENT *
+CreateStatement (
+ IN UINT8 *OpCodeData,
+ IN OUT FORM_BROWSER_FORMSET *FormSet,
+ IN OUT FORM_BROWSER_FORM *Form
+ )
+{
+ FORM_BROWSER_STATEMENT *Statement;
+ EFI_IFR_STATEMENT_HEADER *StatementHdr;
+
+ if (Form == NULL) {
+ //
+ // We are currently not in a Form Scope, so just skip this Statement
+ //
+ return NULL;
+ }
+
+ Statement = &FormSet->StatementBuffer[mStatementIndex];
+ mStatementIndex++;
+
+ InitializeListHead (&Statement->DefaultListHead);
+ InitializeListHead (&Statement->OptionListHead);
+ InitializeListHead (&Statement->InconsistentListHead);
+ InitializeListHead (&Statement->NoSubmitListHead);
+
+ 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));
+
+ if (mInScopeSuppress) {
+ Statement->SuppressExpression = mSuppressExpression;
+ }
+
+ if (mInScopeGrayOut) {
+ Statement->GrayOutExpression = mGrayOutExpression;
+ }
+
+ Statement->InSubtitle = mInScopeSubtitle;
+
+ //
+ // Insert this Statement into current Form
+ //
+ InsertTailList (&Form->StatementListHead, &Statement->Link);
+
+ return Statement;
+}
+
+EFI_STATUS
+UpdateCheckBoxStringToken (
+ IN CONST FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_STATEMENT *Statement
+ )
+{
+ CHAR16 Str[MAXIMUM_VALUE_CHARACTERS];
+ EFI_STRING_ID Id;
+ EFI_STATUS Status;
+
+ ASSERT (Statement != NULL);
+ ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP);
+
+ UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1);
+
+ Status = HiiLibNewString (FormSet->HiiHandle, &Id, Str);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Statement->VarStoreInfo.VarName = Id;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsNextOpCodeGuidedVarEqName (
+ UINT8 *OpCodeData
+ )
+{
+ //
+ // Get next opcode
+ //
+ OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ if (*OpCodeData == EFI_IFR_GUID_OP) {
+ if (CompareGuid (&mFrameworkHiiCompatibilityGuid, (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;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ 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;
+ EFI_STATUS Status;
+
+ 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;
+ }
+
+ //
+ // Take a look at next OpCode to see whether it is a GUIDed opcode to support
+ // Framework Compatibility
+ //
+ if (FeaturePcdGet (PcdFrameworkHiiCompatibilitySupport)) {
+ if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {
+ Status = UpdateCheckBoxStringToken (FormSet, Statement);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ }
+ }
+
+ //
+ // 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);
+
+ //
+ // 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) {
+ //
+ // 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
+
+ @return Pointer to a FORM_EXPRESSION data structure.
+
+**/
+FORM_EXPRESSION *
+CreateExpression (
+ IN OUT FORM_BROWSER_FORM *Form
+ )
+{
+ FORM_EXPRESSION *Expression;
+
+ Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
+ Expression->Signature = FORM_EXPRESSION_SIGNATURE;
+ InitializeListHead (&Expression->OpCodeListHead);
+
+ return Expression;
+}
+
+
+/**
+ Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
+
+ @param FormSet Pointer of the current FormSet
+
+ @return Pointer to a FORMSET_STORAGE data structure.
+
+**/
+FORMSET_STORAGE *
+CreateStorage (
+ IN FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ FORMSET_STORAGE *Storage;
+
+ Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
+ Storage->Signature = FORMSET_STORAGE_SIGNATURE;
+ InitializeListHead (&Storage->NameValueListHead);
+ InsertTailList (&FormSet->StorageListHead, &Storage->Link);
+
+ return Storage;
+}
+
+
+/**
+ 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
+ )
+{
+ EFI_STATUS Status;
+ UINTN StrBufferLen;
+ CHAR16 *Name;
+
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+ Name = Storage->Name;
+ } else {
+ Name = NULL;
+ }
+
+ StrBufferLen = 0;
+ Status = ConstructConfigHdr (
+ Storage->ConfigHdr,
+ &StrBufferLen,
+ &Storage->Guid,
+ Name,
+ FormSet->DriverHandle
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Storage->ConfigHdr = AllocateZeroPool (StrBufferLen);
+ Status = ConstructConfigHdr (
+ Storage->ConfigHdr,
+ &StrBufferLen,
+ &Storage->Guid,
+ Name,
+ FormSet->DriverHandle
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Storage->ConfigRequest = AllocateCopyPool (StrBufferLen, Storage->ConfigHdr);
+ Storage->SpareStrLen = 0;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
+
+ @param FormSet Pointer of the current FormSet.
+ @param Question The Question to be initialized.
+
+ @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
+ )
+{
+ FORMSET_STORAGE *Storage;
+ UINTN StrLen;
+ UINTN StringSize;
+ CHAR16 *NewStr;
+ CHAR16 RequestElement[30];
+
+ 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) {
+ StrLen = UnicodeSPrint (
+ RequestElement,
+ 30 * sizeof (CHAR16),
+ L"&OFFSET=%x&WIDTH=%x",
+ Question->VarStoreInfo.VarOffset,
+ Question->StorageWidth
+ );
+ 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;
+ }
+
+ //
+ // Append <RequestElement> to <ConfigRequest>
+ //
+ if (StrLen > Storage->SpareStrLen) {
+ //
+ // Old String buffer is not sufficient for RequestElement, allocate a new one
+ //
+ StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);
+ NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
+ if (Storage->ConfigRequest != NULL) {
+ CopyMem (NewStr, Storage->ConfigRequest, StringSize);
+ gBS->FreePool (Storage->ConfigRequest);
+ }
+ Storage->ConfigRequest = NewStr;
+ Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
+ }
+
+ StrCat (Storage->ConfigRequest, RequestElement);
+ Storage->ElementCount++;
+ Storage->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;
+
+ while (!IsListEmpty (&Expression->OpCodeListHead)) {
+ Link = GetFirstNode (&Expression->OpCodeListHead);
+ OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
+ RemoveEntryList (&OpCode->Link);
+
+ if (OpCode->ValueList != NULL) {
+ FreePool (OpCode->ValueList);
+ }
+ }
+
+ //
+ // Free this Expression
+ //
+ gBS->FreePool (Expression);
+}
+
+
+/**
+ Free resources of a storage.
+
+ @param Storage Pointer of the storage
+
+**/
+VOID
+DestroyStorage (
+ IN FORMSET_STORAGE *Storage
+ )
+{
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *NameValueNode;
+
+ if (Storage == NULL) {
+ return;
+ }
+
+ if (Storage->Name != NULL) {
+ FreePool (Storage->Name);
+ }
+ if (Storage->Buffer != NULL) {
+ FreePool (Storage->Buffer);
+ }
+ if (Storage->EditBuffer != NULL) {
+ FreePool (Storage->EditBuffer);
+ }
+
+ while (!IsListEmpty (&Storage->NameValueListHead)) {
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
+ RemoveEntryList (&NameValueNode->Link);
+
+ if (NameValueNode->Name != NULL) {
+ FreePool (NameValueNode->Name);
+ }
+ if (NameValueNode->Value != NULL) {
+ FreePool (NameValueNode->Value);
+ }
+ if (NameValueNode->EditValue != NULL) {
+ FreePool (NameValueNode->EditValue);
+ }
+ FreePool (NameValueNode);
+ }
+
+ if (Storage->ConfigHdr != NULL) {
+ FreePool (Storage->ConfigHdr);
+ }
+ if (Storage->ConfigRequest != NULL) {
+ FreePool (Storage->ConfigRequest);
+ }
+
+ FreePool (Storage);
+}
+
+
+/**
+ Free resources of a Statement.
+
+ @param Statement Pointer of the Statement
+
+**/
+VOID
+DestroyStatement (
+ 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);
+
+ 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 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);
+ }
+
+ if (Statement->VariableName != NULL) {
+ FreePool (Statement->VariableName);
+ }
+ if (Statement->BlockName != NULL) {
+ FreePool (Statement->BlockName);
+ }
+}
+
+
+/**
+ Free resources of a Form.
+
+ @param Form Pointer of the Form.
+
+**/
+VOID
+DestroyForm (
+ IN OUT FORM_BROWSER_FORM *Form
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_EXPRESSION *Expression;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ //
+ // Free Form Expressions
+ //
+ while (!IsListEmpty (&Form->ExpressionListHead)) {
+ Link = GetFirstNode (&Form->ExpressionListHead);
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+ RemoveEntryList (&Expression->Link);
+
+ DestroyExpression (Expression);
+ }
+
+ //
+ // Free Statements/Questions
+ //
+ while (!IsListEmpty (&Form->StatementListHead)) {
+ Link = GetFirstNode (&Form->StatementListHead);
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ RemoveEntryList (&Statement->Link);
+
+ DestroyStatement (Statement);
+ }
+
+ //
+ // Free this Form
+ //
+ gBS->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_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);
+ }
+ 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_SPAN_OP)) ||
+ (Operand == EFI_IFR_CATENATE_OP) ||
+ (Operand == EFI_IFR_TO_LOWER_OP) ||
+ (Operand == EFI_IFR_TO_UPPER_OP) ||
+ (Operand == EFI_IFR_VERSION_OP)
+ ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/**
+ Calculate number of Statemens(Questions) and Expression OpCodes.
+
+ @param FormSet The FormSet to be counted.
+ @param NumberOfStatement Number of Statemens(Questions)
+ @param NumberOfExpression Number of Expression OpCodes
+
+**/
+VOID
+CountOpCodes (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN OUT UINT16 *NumberOfStatement,
+ IN OUT UINT16 *NumberOfExpression
+ )
+{
+ UINT16 StatementCount;
+ UINT16 ExpressionCount;
+ UINT8 *OpCodeData;
+ UINTN Offset;
+ UINTN OpCodeLen;
+
+ Offset = 0;
+ StatementCount = 0;
+ ExpressionCount = 0;
+
+ while (Offset < FormSet->IfrBinaryLength) {
+ OpCodeData = FormSet->IfrBinaryData + Offset;
+ OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ Offset += OpCodeLen;
+
+ if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
+ ExpressionCount++;
+ } else {
+ StatementCount++;
+ }
+ }
+
+ *NumberOfStatement = StatementCount;
+ *NumberOfExpression = ExpressionCount;
+}
+
+
+
+/**
+ Parse opcodes in the formset IFR binary.
+
+ @param FormSet Pointer of the FormSet data structure.
+
+ @retval EFI_SUCCESS Opcode parse success.
+ @retval Other Opcode parse fail.
+
+**/
+EFI_STATUS
+ParseOpCodes (
+ IN FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ FORM_BROWSER_FORM *CurrentForm;
+ FORM_BROWSER_STATEMENT *CurrentStatement;
+ EXPRESSION_OPCODE *ExpressionOpCode;
+ FORM_EXPRESSION *CurrentExpression;
+ UINT8 Operand;
+ UINT8 Scope;
+ UINTN OpCodeOffset;
+ UINTN OpCodeLength;
+ UINT8 *OpCodeData;
+ UINT8 ScopeOpCode;
+ FORMSET_STORAGE *Storage;
+ FORMSET_DEFAULTSTORE *DefaultStore;
+ QUESTION_DEFAULT *CurrentDefault;
+ QUESTION_OPTION *CurrentOption;
+ CHAR8 *AsciiString;
+ UINT16 NumberOfStatement;
+ UINT16 NumberOfExpression;
+ EFI_IMAGE_ID *ImageId;
+ BOOLEAN SuppressForOption;
+ BOOLEAN InScopeOptionSuppress;
+ FORM_EXPRESSION *OptionSuppressExpression;
+ BOOLEAN InScopeDisable;
+ UINT16 DepthOfDisable;
+ BOOLEAN OpCodeDisabled;
+ BOOLEAN SingleOpCodeExpression;
+ BOOLEAN InScopeDefault;
+ EFI_HII_VALUE *Value;
+
+ mInScopeSubtitle = FALSE;
+ SuppressForOption = FALSE;
+ mInScopeSuppress = FALSE;
+ InScopeOptionSuppress = FALSE;
+ mInScopeGrayOut = FALSE;
+ InScopeDisable = FALSE;
+ DepthOfDisable = 0;
+ OpCodeDisabled = FALSE;
+ SingleOpCodeExpression = FALSE;
+ InScopeDefault = FALSE;
+ CurrentExpression = NULL;
+ CurrentDefault = NULL;
+ CurrentOption = NULL;
+ OptionSuppressExpression = NULL;
+
+ //
+ // Get the number of Statements and Expressions
+ //
+ CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
+
+ mStatementIndex = 0;
+ FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
+ if (FormSet->StatementBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mExpressionOpCodeIndex = 0;
+ FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
+ if (FormSet->ExpressionBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeListHead (&FormSet->StorageListHead);
+ InitializeListHead (&FormSet->DefaultStoreListHead);
+ InitializeListHead (&FormSet->FormListHead);
+
+ CurrentForm = NULL;
+ CurrentStatement = NULL;
+
+ ResetScopeStack ();
+
+ OpCodeOffset = 0;
+ while (OpCodeOffset < FormSet->IfrBinaryLength) {
+ OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
+
+ OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ OpCodeOffset += OpCodeLength;
+ Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+ Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
+
+ //
+ // If scope bit set, push onto scope stack
+ //
+ if (Scope != 0) {
+ PushScope (Operand);
+ }
+
+ if (OpCodeDisabled) {
+ //
+ // DisableIf Expression is evaluated to be TRUE, try to find its end.
+ // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
+ //
+ if (Operand == EFI_IFR_DISABLE_IF_OP) {
+ DepthOfDisable++;
+ } else if (Operand == EFI_IFR_END_OP) {
+ Status = PopScope (&ScopeOpCode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
+ if (DepthOfDisable == 0) {
+ 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_LIST_OP:
+ CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+ CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
+ ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_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:
+ ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
+ break;
+
+ case EFI_IFR_QUESTION_REF1_OP:
+ CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_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_OTHER;
+ break;
+
+ case EFI_IFR_VERSION_OP:
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
+ break;
+
+ default:
+ break;
+ }
+
+ InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
+
+ 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) {
+ //
+ // Evaluate DisableIf expression
+ //
+ Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OpCodeDisabled = CurrentExpression->Result.Value.b;
+ }
+
+ 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));
+ 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->ExpressionListHead);
+ 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));
+
+ Storage->Buffer = AllocateZeroPool (Storage->Size);
+ Storage->EditBuffer = AllocateZeroPool (Storage->Size);
+
+ 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];
+ }
+
+ //
+ // Initialize <ConfigHdr>
+ //
+ InitializeConfigHdr (FormSet, Storage);
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ //
+ // Create a name/value Storage for this FormSet
+ //
+ Storage = CreateStorage (FormSet);
+ Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
+
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+
+ //
+ // Initialize <ConfigHdr>
+ //
+ InitializeConfigHdr (FormSet, Storage);
+ 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 != 0) {
+ 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;
+ }
+
+ InitializeRequestElement (FormSet, CurrentStatement);
+
+ if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
+ SuppressForOption = TRUE;
+ }
+ 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));
+ InitializeRequestElement (FormSet, CurrentStatement);
+
+ //
+ // 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);
+
+ if (Scope != 0) {
+ SuppressForOption = TRUE;
+ }
+ 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;
+
+ InitializeRequestElement (FormSet, CurrentStatement);
+
+ 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 (CHAR16));
+ CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
+
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
+ CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
+
+ InitializeRequestElement (FormSet, CurrentStatement);
+ 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 (CHAR16));
+
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
+ CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
+
+ InitializeRequestElement (FormSet, CurrentStatement);
+ 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;
+
+ if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
+ CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);
+
+ InitializeRequestElement (FormSet, CurrentStatement);
+ } 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);
+
+ 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 = sizeof (EFI_IFR_TIME);
+
+ InitializeRequestElement (FormSet, CurrentStatement);
+ } 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));
+ 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);
+
+ if (Scope != 0) {
+ InScopeDefault = TRUE;
+ }
+ 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);
+
+ if (InScopeOptionSuppress) {
+ CurrentOption->SuppressExpression = OptionSuppressExpression;
+ }
+
+ //
+ // 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:
+ //
+ // Create an Expression node
+ //
+ CurrentExpression = CreateExpression (CurrentForm);
+ CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
+
+ if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
+ CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
+ InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
+ } else {
+ CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
+ InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
+ }
+ break;
+
+ case EFI_IFR_SUPPRESS_IF_OP:
+ //
+ // Question and Option will appear in scope of this OpCode
+ //
+ CurrentExpression = CreateExpression (CurrentForm);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
+ InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+
+ if (SuppressForOption) {
+ InScopeOptionSuppress = TRUE;
+ OptionSuppressExpression = CurrentExpression;
+ } else {
+ mInScopeSuppress = TRUE;
+ mSuppressExpression = CurrentExpression;
+ }
+ break;
+
+ case EFI_IFR_GRAY_OUT_IF_OP:
+ //
+ // Questions will appear in scope of this OpCode
+ //
+ CurrentExpression = CreateExpression (CurrentForm);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
+ InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+
+ mInScopeGrayOut = TRUE;
+ mGrayOutExpression = CurrentExpression;
+ 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));
+ CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
+ CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
+ InitializeListHead (&CurrentExpression->OpCodeListHead);
+
+ InScopeDisable = TRUE;
+ OpCodeDisabled = FALSE;
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+ break;
+
+ //
+ // Expression
+ //
+ case EFI_IFR_VALUE_OP:
+ CurrentExpression = CreateExpression (CurrentForm);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
+ InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+
+ if (InScopeDefault) {
+ //
+ // Used for default (EFI_IFR_DEFAULT)
+ //
+ CurrentDefault->ValueExpression = CurrentExpression;
+ } else {
+ //
+ // If used for a question, then the question will be read-only
+ //
+ CurrentStatement->ValueExpression = CurrentExpression;
+ }
+ break;
+
+ case EFI_IFR_RULE_OP:
+ CurrentExpression = CreateExpression (CurrentForm);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
+
+ CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
+ InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+ 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:
+ if (CompareGuid (&gTianoHiiIfrGuid, (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_BANNER:
+ if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
+ CopyMem (
+ &BannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
+ ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
+ &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
+ sizeof (EFI_STRING_ID)
+ );
+ }
+ 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;
+ }
+ }
+
+ 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_SUPPRESS_IF_OP:
+ if (SuppressForOption) {
+ InScopeOptionSuppress = FALSE;
+ } else {
+ mInScopeSuppress = FALSE;
+ }
+ break;
+
+ case EFI_IFR_GRAY_OUT_IF_OP:
+ mInScopeGrayOut = FALSE;
+ break;
+
+ case EFI_IFR_DISABLE_IF_OP:
+ 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;
+
+ default:
+ if (IsExpressionOpCode (ScopeOpCode)) {
+ if (InScopeDisable) {
+ //
+ // Evaluate DisableIf expression
+ //
+ Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OpCodeDisabled = CurrentExpression->Result.Value.b;
+ //
+ // DisableIf Expression is only used once and not quequed, free it
+ //
+ DestroyExpression (CurrentExpression);
+ }
+
+ //
+ // End of current Expression
+ //
+ CurrentExpression = NULL;
+ }
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Print.h b/MdeModulePkg/Universal/SetupBrowserDxe/Print.h index b75e0ff..ff41aa6 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Print.h +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Print.h @@ -1,30 +1,30 @@ -/** @file -Micro definitions data for Print.c - -Copyright (c) 2004, 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. - -**/ - -#ifndef _PRINT_H_ -#define _PRINT_H_ - -#define LEFT_JUSTIFY 0x01 -#define PREFIX_SIGN 0x02 -#define PREFIX_BLANK 0x04 -#define COMMA_TYPE 0x08 -#define LONG_TYPE 0x10 -#define PREFIX_ZERO 0x20 - -// -// Largest number of characters that can be printed out. -// -#define EFI_DRIVER_LIB_MAX_PRINT_BUFFER (80 * 4) - -#endif +/** @file
+Micro definitions data for Print.c
+
+Copyright (c) 2004, 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.
+
+**/
+
+#ifndef _PRINT_H_
+#define _PRINT_H_
+
+#define LEFT_JUSTIFY 0x01
+#define PREFIX_SIGN 0x02
+#define PREFIX_BLANK 0x04
+#define COMMA_TYPE 0x08
+#define LONG_TYPE 0x10
+#define PREFIX_ZERO 0x20
+
+//
+// Largest number of characters that can be printed out.
+//
+#define EFI_DRIVER_LIB_MAX_PRINT_BUFFER (80 * 4)
+
+#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c index 9329159..eaa832a 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c @@ -1,971 +1,971 @@ -/** @file -Implementation for handling the User Interface option processing. - - -Copyright (c) 2004 - 2007, 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 "Ui.h" -#include "Setup.h" - - -/** - Process Question Config. - - @param Selection The UI menu selection. - @param Question The Question to be peocessed. - - @retval EFI_SUCCESS Question Config process success. - @retval Other Question Config process fail. - -**/ -EFI_STATUS -ProcessQuestionConfig ( - IN UI_MENU_SELECTION *Selection, - IN FORM_BROWSER_STATEMENT *Question - ) -{ - EFI_STATUS Status; - CHAR16 *ConfigResp; - CHAR16 *Progress; - EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; - - if (Question->QuestionConfig == 0) { - return EFI_SUCCESS; - } - - // - // Get <ConfigResp> - // - ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle); - if (ConfigResp == NULL) { - return EFI_NOT_FOUND; - } - - // - // Send config to Configuration Driver - // - ConfigAccess = Selection->FormSet->ConfigAccess; - if (ConfigAccess == NULL) { - return EFI_UNSUPPORTED; - } - Status = ConfigAccess->RouteConfig ( - ConfigAccess, - ConfigResp, - &Progress - ); - - return Status; -} - - -/** - Search an Option of a Question by its value. - - @param Question The Question - @param OptionValue Value for Option to be searched. - - @retval Pointer Pointer to the found Option. - @retval NULL Option not found. - -**/ -QUESTION_OPTION * -ValueToOption ( - IN FORM_BROWSER_STATEMENT *Question, - IN EFI_HII_VALUE *OptionValue - ) -{ - LIST_ENTRY *Link; - QUESTION_OPTION *Option; - - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - Option = QUESTION_OPTION_FROM_LINK (Link); - - if (CompareHiiValue (&Option->Value, OptionValue, NULL) == 0) { - return Option; - } - - Link = GetNextNode (&Question->OptionListHead, Link); - } - - return NULL; -} - - -/** - Print Question Value according to it's storage width and display attributes. - - @param Question The Question to be printed. - @param FormattedNumber Buffer for output string. - @param BufferSize The FormattedNumber buffer size in bytes. - - @retval EFI_SUCCESS Print success. - @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number. - -**/ -EFI_STATUS -PrintFormattedNumber ( - IN FORM_BROWSER_STATEMENT *Question, - IN OUT CHAR16 *FormattedNumber, - IN UINTN BufferSize - ) -{ - INT64 Value; - CHAR16 *Format; - EFI_HII_VALUE *QuestionValue; - - if (BufferSize < (21 * sizeof (CHAR16))) { - return EFI_BUFFER_TOO_SMALL; - } - - QuestionValue = &Question->HiiValue; - - Value = (INT64) QuestionValue->Value.u64; - switch (Question->Flags & EFI_IFR_DISPLAY) { - case EFI_IFR_DISPLAY_INT_DEC: - switch (QuestionValue->Type) { - case EFI_IFR_NUMERIC_SIZE_1: - Value = (INT64) ((INT8) QuestionValue->Value.u8); - break; - - case EFI_IFR_NUMERIC_SIZE_2: - Value = (INT64) ((INT16) QuestionValue->Value.u16); - break; - - case EFI_IFR_NUMERIC_SIZE_4: - Value = (INT64) ((INT32) QuestionValue->Value.u32); - break; - - case EFI_IFR_NUMERIC_SIZE_8: - default: - break; - } - - if (Value < 0) { - Value = -Value; - Format = L"-%ld"; - } else { - Format = L"%ld"; - } - break; - - case EFI_IFR_DISPLAY_UINT_DEC: - Format = L"%ld"; - break; - - case EFI_IFR_DISPLAY_UINT_HEX: - Format = L"%lx"; - break; - - default: - return EFI_UNSUPPORTED; - break; - } - - UnicodeSPrint (FormattedNumber, BufferSize, Format, Value); - - return EFI_SUCCESS; -} - - -/** - Password may be stored as encrypted by Configuration Driver. When change a - password, user will be challenged with old password. To validate user input old - password, we will send the clear text to Configuration Driver via Callback(). - Configuration driver is responsible to check the passed in password and return - the validation result. If validation pass, state machine in password Callback() - will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD. - After user type in new password twice, Callback() will be invoked to send the - new password to Configuration Driver. - - @param Selection Pointer to UI_MENU_SELECTION. - @param MenuOption The MenuOption for this password Question. - @param String The clear text of password. - - @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input. - @return In state of BROWSER_STATE_VALIDATE_PASSWORD: - @retval EFI_SUCCESS Password correct, Browser will prompt for new - password. - @retval EFI_NOT_READY Password incorrect, Browser will show error - message. - @retval Other Browser will do nothing. - @return In state of BROWSER_STATE_SET_PASSWORD: - @retval EFI_SUCCESS Set password success. - @retval Other Set password failed. - -**/ -EFI_STATUS -PasswordCallback ( - IN UI_MENU_SELECTION *Selection, - IN UI_MENU_OPTION *MenuOption, - IN CHAR16 *String - ) -{ - EFI_STATUS Status; - EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; - EFI_BROWSER_ACTION_REQUEST ActionRequest; - EFI_HII_VALUE *QuestionValue; - - QuestionValue = &MenuOption->ThisTag->HiiValue; - ConfigAccess = Selection->FormSet->ConfigAccess; - if (ConfigAccess == NULL) { - return EFI_UNSUPPORTED; - } - - // - // Prepare password string in HII database - // - if (String != NULL) { - QuestionValue->Value.string = NewString (String, Selection->FormSet->HiiHandle); - } else { - QuestionValue->Value.string = 0; - } - - // - // Send password to Configuration Driver for validation - // - Status = ConfigAccess->Callback ( - ConfigAccess, - EFI_BROWSER_ACTION_CHANGING, - MenuOption->ThisTag->QuestionId, - QuestionValue->Type, - &QuestionValue->Value, - &ActionRequest - ); - - // - // Remove password string from HII database - // - if (String != NULL) { - DeleteString (QuestionValue->Value.string, Selection->FormSet->HiiHandle); - } - - return Status; -} - - -/** - Display error message for invalid password. - -**/ -VOID -PasswordInvalid ( - VOID - ) -{ - EFI_INPUT_KEY Key; - - // - // Invalid password, prompt error message - // - do { - CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); -} - - -/** - Process a Question's Option (whether selected or un-selected). - - @param Selection Pointer to UI_MENU_SELECTION. - @param MenuOption The MenuOption for this Question. - @param Selected TRUE: if Question is selected. - @param OptionString Pointer of the Option String to be displayed. - - @retval EFI_SUCCESS Question Option process success. - @retval Other Question Option process fail. - -**/ -EFI_STATUS -ProcessOptions ( - IN UI_MENU_SELECTION *Selection, - IN UI_MENU_OPTION *MenuOption, - IN BOOLEAN Selected, - OUT CHAR16 **OptionString - ) -{ - EFI_STATUS Status; - CHAR16 *StringPtr; - CHAR16 *TempString; - UINTN Index; - FORM_BROWSER_STATEMENT *Question; - CHAR16 FormattedNumber[21]; - UINT16 Number; - CHAR16 Character[2]; - EFI_INPUT_KEY Key; - UINTN BufferSize; - QUESTION_OPTION *OneOfOption; - LIST_ENTRY *Link; - EFI_HII_VALUE HiiValue; - EFI_HII_VALUE *QuestionValue; - BOOLEAN Suppress; - UINT16 Maximum; - - Status = EFI_SUCCESS; - - StringPtr = NULL; - Character[1] = L'\0'; - *OptionString = NULL; - - ZeroMem (FormattedNumber, 21 * sizeof (CHAR16)); - BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow; - - Question = MenuOption->ThisTag; - QuestionValue = &Question->HiiValue; - Maximum = (UINT16) Question->Maximum; - - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - // - // Initialize Option value array - // - - if (Question->BufferValue[0] == 0) { - GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0); - } - - if (Selected) { - // - // Go ask for input - // - Status = GetSelectionInputPopUp (Selection, MenuOption); - } else { - // - // We now know how many strings we will have, so we can allocate the - // space required for the array or strings. - // - *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize); - ASSERT (*OptionString); - - HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8; - HiiValue.Value.u64 = 0; - for (Index = 0; Index < Question->MaxContainers; Index++) { - HiiValue.Value.u8 = Question->BufferValue[Index]; - if (HiiValue.Value.u8 == 0) { - // - // Values for the options in ordered lists should never be a 0 - // - break; - } - - OneOfOption = ValueToOption (Question, &HiiValue); - if (OneOfOption == NULL) { - gBS->FreePool (*OptionString); - return EFI_NOT_FOUND; - } - - Suppress = FALSE; - if ((OneOfOption->SuppressExpression != NULL) && - (OneOfOption->SuppressExpression->Result.Value.b)) { - // - // This option is suppressed - // - Suppress = TRUE; - } - - if (!Suppress) { - Character[0] = LEFT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - StringPtr = GetToken (OneOfOption->Text, Selection->Handle); - NewStrCat (OptionString[0], StringPtr); - Character[0] = RIGHT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - Character[0] = CHAR_CARRIAGE_RETURN; - NewStrCat (OptionString[0], Character); - - gBS->FreePool (StringPtr); - } - } - } - break; - - case EFI_IFR_ONE_OF_OP: - if (Selected) { - // - // Go ask for input - // - Status = GetSelectionInputPopUp (Selection, MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - OneOfOption = ValueToOption (Question, QuestionValue); - if (OneOfOption == NULL) { - gBS->FreePool (*OptionString); - return EFI_NOT_FOUND; - } - - if ((OneOfOption->SuppressExpression != NULL) && - (OneOfOption->SuppressExpression->Result.Value.b)) { - // - // This option is suppressed - // - Suppress = TRUE; - } else { - Suppress = FALSE; - } - - if (Suppress) { - // - // Current selected option happen to be suppressed, - // enforce to select on a non-suppressed option - // - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - OneOfOption = QUESTION_OPTION_FROM_LINK (Link); - - if ((OneOfOption->SuppressExpression == NULL) || - !OneOfOption->SuppressExpression->Result.Value.b) { - Suppress = FALSE; - CopyMem (QuestionValue, &OneOfOption->Value, sizeof (EFI_HII_VALUE)); - SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); - break; - } - - Link = GetNextNode (&Question->OptionListHead, Link); - } - } - - if (!Suppress) { - Character[0] = LEFT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - StringPtr = GetToken (OneOfOption->Text, Selection->Handle); - NewStrCat (OptionString[0], StringPtr); - Character[0] = RIGHT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - - gBS->FreePool (StringPtr); - } - } - break; - - case EFI_IFR_CHECKBOX_OP: - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - *OptionString[0] = LEFT_CHECKBOX_DELIMITER; - - if (Selected) { - // - // Since this is a BOOLEAN operation, flip it upon selection - // - QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE); - - // - // Perform inconsistent check - // - Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); - if (EFI_ERROR (Status)) { - // - // Inconsistent check fail, restore Question Value - // - QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE); - gBS->FreePool (*OptionString); - return Status; - } - - // - // Save Question value - // - Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); - UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); - } - - if (QuestionValue->Value.b) { - *(OptionString[0] + 1) = CHECK_ON; - } else { - *(OptionString[0] + 1) = CHECK_OFF; - } - *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER; - break; - - case EFI_IFR_NUMERIC_OP: - if (Selected) { - // - // Go ask for input - // - Status = GetNumericInput (Selection, MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - *OptionString[0] = LEFT_NUMERIC_DELIMITER; - - // - // Formatted print - // - PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16)); - Number = (UINT16) GetStringWidth (FormattedNumber); - CopyMem (OptionString[0] + 1, FormattedNumber, Number); - - *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER; - } - break; - - case EFI_IFR_DATE_OP: - if (Selected) { - // - // This is similar to numerics - // - Status = GetNumericInput (Selection, MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - switch (MenuOption->Sequence) { - case 0: - *OptionString[0] = LEFT_NUMERIC_DELIMITER; - UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month); - *(OptionString[0] + 3) = DATE_SEPARATOR; - break; - - case 1: - SetUnicodeMem (OptionString[0], 4, L' '); - UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day); - *(OptionString[0] + 6) = DATE_SEPARATOR; - break; - - case 2: - SetUnicodeMem (OptionString[0], 7, L' '); - UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%4d", QuestionValue->Value.date.Year); - *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER; - break; - } - } - break; - - case EFI_IFR_TIME_OP: - if (Selected) { - // - // This is similar to numerics - // - Status = GetNumericInput (Selection, MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - switch (MenuOption->Sequence) { - case 0: - *OptionString[0] = LEFT_NUMERIC_DELIMITER; - UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour); - *(OptionString[0] + 3) = TIME_SEPARATOR; - break; - - case 1: - SetUnicodeMem (OptionString[0], 4, L' '); - UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute); - *(OptionString[0] + 6) = TIME_SEPARATOR; - break; - - case 2: - SetUnicodeMem (OptionString[0], 7, L' '); - UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second); - *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER; - break; - } - } - break; - - case EFI_IFR_STRING_OP: - if (Selected) { - StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); - ASSERT (StringPtr); - - Status = ReadString (MenuOption, gPromptForData, StringPtr); - if (!EFI_ERROR (Status)) { - CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16)); - SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); - - UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); - } - - gBS->FreePool (StringPtr); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) { - *(OptionString[0]) = '_'; - } else { - if ((Maximum * sizeof (CHAR16)) < BufferSize) { - BufferSize = Maximum * sizeof (CHAR16); - } - CopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize); - } - } - break; - - case EFI_IFR_PASSWORD_OP: - if (Selected) { - StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); - ASSERT (StringPtr); - - // - // For interactive passwords, old password is validated by callback - // - if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { - // - // Use a NULL password to test whether old password is required - // - *StringPtr = 0; - Status = PasswordCallback (Selection, MenuOption, StringPtr); - if (Status == EFI_NOT_AVAILABLE_YET) { - // - // Callback request to terminate password input - // - gBS->FreePool (StringPtr); - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - // - // Old password exist, ask user for the old password - // - Status = ReadString (MenuOption, gPromptForPassword, StringPtr); - if (EFI_ERROR (Status)) { - gBS->FreePool (StringPtr); - return Status; - } - - // - // Check user input old password - // - Status = PasswordCallback (Selection, MenuOption, StringPtr); - if (EFI_ERROR (Status)) { - if (Status == EFI_NOT_READY) { - // - // Typed in old password incorrect - // - PasswordInvalid (); - } else { - Status = EFI_SUCCESS; - } - - gBS->FreePool (StringPtr); - return Status; - } - } - } else { - // - // For non-interactive password, validate old password in local - // - if (*((CHAR16 *) Question->BufferValue) != 0) { - // - // There is something there! Prompt for password - // - Status = ReadString (MenuOption, gPromptForPassword, StringPtr); - if (EFI_ERROR (Status)) { - gBS->FreePool (StringPtr); - return Status; - } - - TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue); - TempString[Maximum] = L'\0'; - - if (StrCmp (StringPtr, TempString) != 0) { - // - // Typed in old password incorrect - // - PasswordInvalid (); - - gBS->FreePool (StringPtr); - gBS->FreePool (TempString); - return Status; - } - - gBS->FreePool (TempString); - } - } - - // - // Ask for new password - // - ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16)); - Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr); - if (EFI_ERROR (Status)) { - // - // Reset state machine for interactive password - // - if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { - PasswordCallback (Selection, MenuOption, NULL); - } - - gBS->FreePool (StringPtr); - return Status; - } - - // - // Confirm new password - // - TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); - ASSERT (TempString); - Status = ReadString (MenuOption, gConfirmPassword, TempString); - if (EFI_ERROR (Status)) { - // - // Reset state machine for interactive password - // - if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { - PasswordCallback (Selection, MenuOption, NULL); - } - - gBS->FreePool (StringPtr); - gBS->FreePool (TempString); - return Status; - } - - // - // Compare two typed-in new passwords - // - if (StrCmp (StringPtr, TempString) == 0) { - // - // Two password match, send it to Configuration Driver - // - if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { - PasswordCallback (Selection, MenuOption, StringPtr); - } else { - CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16)); - SetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE); - } - } else { - // - // Reset state machine for interactive password - // - if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { - PasswordCallback (Selection, MenuOption, NULL); - } - - // - // Two password mismatch, prompt error message - // - do { - CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - } - - gBS->FreePool (TempString); - gBS->FreePool (StringPtr); - } - break; - - default: - break; - } - - return Status; -} - - -/** - Process the help string: Split StringPtr to several lines of strings stored in - FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth. - - @param StringPtr The entire help string. - @param FormattedString The oupput formatted string. - @param RowCount TRUE: if Question is selected. - -**/ -VOID -ProcessHelpString ( - IN CHAR16 *StringPtr, - OUT CHAR16 **FormattedString, - IN UINTN RowCount - ) -{ - CONST UINTN BlockWidth = (UINTN) gHelpBlockWidth - 1; - UINTN AllocateSize; - // - // [PrevCurrIndex, CurrIndex) forms a range of a screen-line - // - UINTN CurrIndex; - UINTN PrevCurrIndex; - UINTN LineCount; - UINTN VirtualLineCount; - // - // GlyphOffset stores glyph width of current screen-line - // - UINTN GlyphOffset; - // - // GlyphWidth equals to 2 if we meet width directive - // - UINTN GlyphWidth; - // - // during scanning, we remember the position of last space character - // in case that if next word cannot put in current line, we could restore back to the position - // of last space character - // while we should also remmeber the glyph width of the last space character for restoring - // - UINTN LastSpaceIndex; - UINTN LastSpaceGlyphWidth; - // - // every time we begin to form a new screen-line, we should remember glyph width of single character - // of last line - // - UINTN LineStartGlyphWidth; - UINTN *IndexArray; - UINTN *OldIndexArray; - - // - // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] ) - // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want - // to bring the width directive of the last line to current screen-line. - // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line - // different from that of "\wideabcde", we should remember the width directive. - // - AllocateSize = 0x20; - IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3); - - if (*FormattedString != NULL) { - gBS->FreePool (*FormattedString); - *FormattedString = NULL; - } - - for (PrevCurrIndex = 0, CurrIndex = 0, LineCount = 0, LastSpaceIndex = 0, - IndexArray[0] = 0, GlyphWidth = 1, GlyphOffset = 0, LastSpaceGlyphWidth = 1, LineStartGlyphWidth = 1; - (StringPtr[CurrIndex] != CHAR_NULL); - CurrIndex ++) { - - if (LineCount == AllocateSize) { - AllocateSize += 0x10; - OldIndexArray = IndexArray; - IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3); - CopyMem (IndexArray, OldIndexArray, LineCount * sizeof (UINTN) * 3); - gBS->FreePool (OldIndexArray); - } - switch (StringPtr[CurrIndex]) { - - case NARROW_CHAR: - case WIDE_CHAR: - GlyphWidth = ((StringPtr[CurrIndex] == WIDE_CHAR) ? 2 : 1); - if (CurrIndex == 0) { - LineStartGlyphWidth = GlyphWidth; - } - break; - - // - // char is '\n' - // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN - // - case CHAR_LINEFEED: - // - // Store a range of string as a line - // - IndexArray[LineCount*3] = PrevCurrIndex; - IndexArray[LineCount*3+1] = CurrIndex; - IndexArray[LineCount*3+2] = LineStartGlyphWidth; - LineCount ++; - // - // Reset offset and save begin position of line - // - GlyphOffset = 0; - LineStartGlyphWidth = GlyphWidth; - PrevCurrIndex = CurrIndex + 1; - break; - - // - // char is '\r' - // "\r\n" and "\r" both are handled here - // - case CHAR_CARRIAGE_RETURN: - if (StringPtr[CurrIndex + 1] == CHAR_LINEFEED) { - // - // next char is '\n' - // - IndexArray[LineCount*3] = PrevCurrIndex; - IndexArray[LineCount*3+1] = CurrIndex; - IndexArray[LineCount*3+2] = LineStartGlyphWidth; - LineCount ++; - CurrIndex ++; - } - GlyphOffset = 0; - LineStartGlyphWidth = GlyphWidth; - PrevCurrIndex = CurrIndex + 1; - break; - - // - // char is space or other char - // - default: - GlyphOffset += GlyphWidth; - if (GlyphOffset >= BlockWidth) { - if (LastSpaceIndex > PrevCurrIndex) { - // - // LastSpaceIndex points to space inside current screen-line, - // restore to LastSpaceIndex - // (Otherwise the word is too long to fit one screen-line, just cut it) - // - CurrIndex = LastSpaceIndex; - GlyphWidth = LastSpaceGlyphWidth; - } else if (GlyphOffset > BlockWidth) { - // - // the word is too long to fit one screen-line and we don't get the chance - // of GlyphOffset == BlockWidth because GlyphWidth = 2 - // - CurrIndex --; - } - - IndexArray[LineCount*3] = PrevCurrIndex; - IndexArray[LineCount*3+1] = CurrIndex + 1; - IndexArray[LineCount*3+2] = LineStartGlyphWidth; - LineStartGlyphWidth = GlyphWidth; - LineCount ++; - // - // Reset offset and save begin position of line - // - GlyphOffset = 0; - PrevCurrIndex = CurrIndex + 1; - } - - // - // LastSpaceIndex: remember position of last space - // - if (StringPtr[CurrIndex] == CHAR_SPACE) { - LastSpaceIndex = CurrIndex; - LastSpaceGlyphWidth = GlyphWidth; - } - break; - } - } - - if (GlyphOffset > 0) { - IndexArray[LineCount*3] = PrevCurrIndex; - IndexArray[LineCount*3+1] = CurrIndex; - IndexArray[LineCount*3+2] = GlyphWidth; - LineCount ++; - } - - if (LineCount == 0) { - // - // in case we meet null string - // - IndexArray[0] = 0; - IndexArray[1] = 1; - // - // we assume null string's glyph width is 1 - // - IndexArray[1] = 1; - LineCount ++; - } - - VirtualLineCount = RowCount * (LineCount / RowCount + (LineCount % RowCount > 0)); - *FormattedString = AllocateZeroPool (VirtualLineCount * (BlockWidth + 1) * sizeof (CHAR16) * 2); - - for (CurrIndex = 0; CurrIndex < LineCount; CurrIndex ++) { - *(*FormattedString + CurrIndex * 2 * (BlockWidth + 1)) = (CHAR16) ((IndexArray[CurrIndex*3+2] == 2) ? WIDE_CHAR : NARROW_CHAR); - StrnCpy ( - *FormattedString + CurrIndex * 2 * (BlockWidth + 1) + 1, - StringPtr + IndexArray[CurrIndex*3], - IndexArray[CurrIndex*3+1]-IndexArray[CurrIndex*3] - ); - } - - gBS->FreePool (IndexArray); -} +/** @file
+Implementation for handling the User Interface option processing.
+
+
+Copyright (c) 2004 - 2007, 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 "Ui.h"
+#include "Setup.h"
+
+
+/**
+ Process Question Config.
+
+ @param Selection The UI menu selection.
+ @param Question The Question to be peocessed.
+
+ @retval EFI_SUCCESS Question Config process success.
+ @retval Other Question Config process fail.
+
+**/
+EFI_STATUS
+ProcessQuestionConfig (
+ IN UI_MENU_SELECTION *Selection,
+ IN FORM_BROWSER_STATEMENT *Question
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *ConfigResp;
+ CHAR16 *Progress;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+
+ if (Question->QuestionConfig == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get <ConfigResp>
+ //
+ ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);
+ if (ConfigResp == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Send config to Configuration Driver
+ //
+ ConfigAccess = Selection->FormSet->ConfigAccess;
+ if (ConfigAccess == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = ConfigAccess->RouteConfig (
+ ConfigAccess,
+ ConfigResp,
+ &Progress
+ );
+
+ return Status;
+}
+
+
+/**
+ Search an Option of a Question by its value.
+
+ @param Question The Question
+ @param OptionValue Value for Option to be searched.
+
+ @retval Pointer Pointer to the found Option.
+ @retval NULL Option not found.
+
+**/
+QUESTION_OPTION *
+ValueToOption (
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN EFI_HII_VALUE *OptionValue
+ )
+{
+ LIST_ENTRY *Link;
+ QUESTION_OPTION *Option;
+
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+
+ if (CompareHiiValue (&Option->Value, OptionValue, NULL) == 0) {
+ return Option;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Print Question Value according to it's storage width and display attributes.
+
+ @param Question The Question to be printed.
+ @param FormattedNumber Buffer for output string.
+ @param BufferSize The FormattedNumber buffer size in bytes.
+
+ @retval EFI_SUCCESS Print success.
+ @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
+
+**/
+EFI_STATUS
+PrintFormattedNumber (
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN OUT CHAR16 *FormattedNumber,
+ IN UINTN BufferSize
+ )
+{
+ INT64 Value;
+ CHAR16 *Format;
+ EFI_HII_VALUE *QuestionValue;
+
+ if (BufferSize < (21 * sizeof (CHAR16))) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ QuestionValue = &Question->HiiValue;
+
+ Value = (INT64) QuestionValue->Value.u64;
+ switch (Question->Flags & EFI_IFR_DISPLAY) {
+ case EFI_IFR_DISPLAY_INT_DEC:
+ switch (QuestionValue->Type) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ Value = (INT64) ((INT8) QuestionValue->Value.u8);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ Value = (INT64) ((INT16) QuestionValue->Value.u16);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ Value = (INT64) ((INT32) QuestionValue->Value.u32);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ default:
+ break;
+ }
+
+ if (Value < 0) {
+ Value = -Value;
+ Format = L"-%ld";
+ } else {
+ Format = L"%ld";
+ }
+ break;
+
+ case EFI_IFR_DISPLAY_UINT_DEC:
+ Format = L"%ld";
+ break;
+
+ case EFI_IFR_DISPLAY_UINT_HEX:
+ Format = L"%lx";
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ break;
+ }
+
+ UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Password may be stored as encrypted by Configuration Driver. When change a
+ password, user will be challenged with old password. To validate user input old
+ password, we will send the clear text to Configuration Driver via Callback().
+ Configuration driver is responsible to check the passed in password and return
+ the validation result. If validation pass, state machine in password Callback()
+ will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.
+ After user type in new password twice, Callback() will be invoked to send the
+ new password to Configuration Driver.
+
+ @param Selection Pointer to UI_MENU_SELECTION.
+ @param MenuOption The MenuOption for this password Question.
+ @param String The clear text of password.
+
+ @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.
+ @return In state of BROWSER_STATE_VALIDATE_PASSWORD:
+ @retval EFI_SUCCESS Password correct, Browser will prompt for new
+ password.
+ @retval EFI_NOT_READY Password incorrect, Browser will show error
+ message.
+ @retval Other Browser will do nothing.
+ @return In state of BROWSER_STATE_SET_PASSWORD:
+ @retval EFI_SUCCESS Set password success.
+ @retval Other Set password failed.
+
+**/
+EFI_STATUS
+PasswordCallback (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption,
+ IN CHAR16 *String
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ EFI_HII_VALUE *QuestionValue;
+
+ QuestionValue = &MenuOption->ThisTag->HiiValue;
+ ConfigAccess = Selection->FormSet->ConfigAccess;
+ if (ConfigAccess == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Prepare password string in HII database
+ //
+ if (String != NULL) {
+ QuestionValue->Value.string = NewString (String, Selection->FormSet->HiiHandle);
+ } else {
+ QuestionValue->Value.string = 0;
+ }
+
+ //
+ // Send password to Configuration Driver for validation
+ //
+ Status = ConfigAccess->Callback (
+ ConfigAccess,
+ EFI_BROWSER_ACTION_CHANGING,
+ MenuOption->ThisTag->QuestionId,
+ QuestionValue->Type,
+ &QuestionValue->Value,
+ &ActionRequest
+ );
+
+ //
+ // Remove password string from HII database
+ //
+ if (String != NULL) {
+ DeleteString (QuestionValue->Value.string, Selection->FormSet->HiiHandle);
+ }
+
+ return Status;
+}
+
+
+/**
+ Display error message for invalid password.
+
+**/
+VOID
+PasswordInvalid (
+ VOID
+ )
+{
+ EFI_INPUT_KEY Key;
+
+ //
+ // Invalid password, prompt error message
+ //
+ do {
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+}
+
+
+/**
+ Process a Question's Option (whether selected or un-selected).
+
+ @param Selection Pointer to UI_MENU_SELECTION.
+ @param MenuOption The MenuOption for this Question.
+ @param Selected TRUE: if Question is selected.
+ @param OptionString Pointer of the Option String to be displayed.
+
+ @retval EFI_SUCCESS Question Option process success.
+ @retval Other Question Option process fail.
+
+**/
+EFI_STATUS
+ProcessOptions (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected,
+ OUT CHAR16 **OptionString
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *StringPtr;
+ CHAR16 *TempString;
+ UINTN Index;
+ FORM_BROWSER_STATEMENT *Question;
+ CHAR16 FormattedNumber[21];
+ UINT16 Number;
+ CHAR16 Character[2];
+ EFI_INPUT_KEY Key;
+ UINTN BufferSize;
+ QUESTION_OPTION *OneOfOption;
+ LIST_ENTRY *Link;
+ EFI_HII_VALUE HiiValue;
+ EFI_HII_VALUE *QuestionValue;
+ BOOLEAN Suppress;
+ UINT16 Maximum;
+
+ Status = EFI_SUCCESS;
+
+ StringPtr = NULL;
+ Character[1] = L'\0';
+ *OptionString = NULL;
+
+ ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
+ BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow;
+
+ Question = MenuOption->ThisTag;
+ QuestionValue = &Question->HiiValue;
+ Maximum = (UINT16) Question->Maximum;
+
+ switch (Question->Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ //
+ // Initialize Option value array
+ //
+
+ if (Question->BufferValue[0] == 0) {
+ GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0);
+ }
+
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ Status = GetSelectionInputPopUp (Selection, MenuOption);
+ } else {
+ //
+ // We now know how many strings we will have, so we can allocate the
+ // space required for the array or strings.
+ //
+ *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize);
+ ASSERT (*OptionString);
+
+ HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ HiiValue.Value.u64 = 0;
+ for (Index = 0; Index < Question->MaxContainers; Index++) {
+ HiiValue.Value.u8 = Question->BufferValue[Index];
+ if (HiiValue.Value.u8 == 0) {
+ //
+ // Values for the options in ordered lists should never be a 0
+ //
+ break;
+ }
+
+ OneOfOption = ValueToOption (Question, &HiiValue);
+ if (OneOfOption == NULL) {
+ gBS->FreePool (*OptionString);
+ return EFI_NOT_FOUND;
+ }
+
+ Suppress = FALSE;
+ if ((OneOfOption->SuppressExpression != NULL) &&
+ (OneOfOption->SuppressExpression->Result.Value.b)) {
+ //
+ // This option is suppressed
+ //
+ Suppress = TRUE;
+ }
+
+ if (!Suppress) {
+ Character[0] = LEFT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ StringPtr = GetToken (OneOfOption->Text, Selection->Handle);
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ Character[0] = CHAR_CARRIAGE_RETURN;
+ NewStrCat (OptionString[0], Character);
+
+ gBS->FreePool (StringPtr);
+ }
+ }
+ }
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ Status = GetSelectionInputPopUp (Selection, MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ OneOfOption = ValueToOption (Question, QuestionValue);
+ if (OneOfOption == NULL) {
+ gBS->FreePool (*OptionString);
+ return EFI_NOT_FOUND;
+ }
+
+ if ((OneOfOption->SuppressExpression != NULL) &&
+ (OneOfOption->SuppressExpression->Result.Value.b)) {
+ //
+ // This option is suppressed
+ //
+ Suppress = TRUE;
+ } else {
+ Suppress = FALSE;
+ }
+
+ if (Suppress) {
+ //
+ // Current selected option happen to be suppressed,
+ // enforce to select on a non-suppressed option
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+ if ((OneOfOption->SuppressExpression == NULL) ||
+ !OneOfOption->SuppressExpression->Result.Value.b) {
+ Suppress = FALSE;
+ CopyMem (QuestionValue, &OneOfOption->Value, sizeof (EFI_HII_VALUE));
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+ break;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ }
+
+ if (!Suppress) {
+ Character[0] = LEFT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ StringPtr = GetToken (OneOfOption->Text, Selection->Handle);
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+
+ gBS->FreePool (StringPtr);
+ }
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ *OptionString[0] = LEFT_CHECKBOX_DELIMITER;
+
+ if (Selected) {
+ //
+ // Since this is a BOOLEAN operation, flip it upon selection
+ //
+ QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
+
+ //
+ // Perform inconsistent check
+ //
+ Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
+ if (EFI_ERROR (Status)) {
+ //
+ // Inconsistent check fail, restore Question Value
+ //
+ QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
+ gBS->FreePool (*OptionString);
+ return Status;
+ }
+
+ //
+ // Save Question value
+ //
+ Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+ }
+
+ if (QuestionValue->Value.b) {
+ *(OptionString[0] + 1) = CHECK_ON;
+ } else {
+ *(OptionString[0] + 1) = CHECK_OFF;
+ }
+ *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ Status = GetNumericInput (Selection, MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+
+ //
+ // Formatted print
+ //
+ PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ CopyMem (OptionString[0] + 1, FormattedNumber, Number);
+
+ *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;
+ }
+ break;
+
+ case EFI_IFR_DATE_OP:
+ if (Selected) {
+ //
+ // This is similar to numerics
+ //
+ Status = GetNumericInput (Selection, MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ switch (MenuOption->Sequence) {
+ case 0:
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+ UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);
+ *(OptionString[0] + 3) = DATE_SEPARATOR;
+ break;
+
+ case 1:
+ SetUnicodeMem (OptionString[0], 4, L' ');
+ UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);
+ *(OptionString[0] + 6) = DATE_SEPARATOR;
+ break;
+
+ case 2:
+ SetUnicodeMem (OptionString[0], 7, L' ');
+ UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%4d", QuestionValue->Value.date.Year);
+ *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;
+ break;
+ }
+ }
+ break;
+
+ case EFI_IFR_TIME_OP:
+ if (Selected) {
+ //
+ // This is similar to numerics
+ //
+ Status = GetNumericInput (Selection, MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ switch (MenuOption->Sequence) {
+ case 0:
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+ UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);
+ *(OptionString[0] + 3) = TIME_SEPARATOR;
+ break;
+
+ case 1:
+ SetUnicodeMem (OptionString[0], 4, L' ');
+ UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);
+ *(OptionString[0] + 6) = TIME_SEPARATOR;
+ break;
+
+ case 2:
+ SetUnicodeMem (OptionString[0], 7, L' ');
+ UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);
+ *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;
+ break;
+ }
+ }
+ break;
+
+ case EFI_IFR_STRING_OP:
+ if (Selected) {
+ StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+ ASSERT (StringPtr);
+
+ Status = ReadString (MenuOption, gPromptForData, StringPtr);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+ }
+
+ gBS->FreePool (StringPtr);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) {
+ *(OptionString[0]) = '_';
+ } else {
+ if ((Maximum * sizeof (CHAR16)) < BufferSize) {
+ BufferSize = Maximum * sizeof (CHAR16);
+ }
+ CopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize);
+ }
+ }
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ if (Selected) {
+ StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+ ASSERT (StringPtr);
+
+ //
+ // For interactive passwords, old password is validated by callback
+ //
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
+ //
+ // Use a NULL password to test whether old password is required
+ //
+ *StringPtr = 0;
+ Status = PasswordCallback (Selection, MenuOption, StringPtr);
+ if (Status == EFI_NOT_AVAILABLE_YET) {
+ //
+ // Callback request to terminate password input
+ //
+ gBS->FreePool (StringPtr);
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Old password exist, ask user for the old password
+ //
+ Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (StringPtr);
+ return Status;
+ }
+
+ //
+ // Check user input old password
+ //
+ Status = PasswordCallback (Selection, MenuOption, StringPtr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_READY) {
+ //
+ // Typed in old password incorrect
+ //
+ PasswordInvalid ();
+ } else {
+ Status = EFI_SUCCESS;
+ }
+
+ gBS->FreePool (StringPtr);
+ return Status;
+ }
+ }
+ } else {
+ //
+ // For non-interactive password, validate old password in local
+ //
+ if (*((CHAR16 *) Question->BufferValue) != 0) {
+ //
+ // There is something there! Prompt for password
+ //
+ Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (StringPtr);
+ return Status;
+ }
+
+ TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue);
+ TempString[Maximum] = L'\0';
+
+ if (StrCmp (StringPtr, TempString) != 0) {
+ //
+ // Typed in old password incorrect
+ //
+ PasswordInvalid ();
+
+ gBS->FreePool (StringPtr);
+ gBS->FreePool (TempString);
+ return Status;
+ }
+
+ gBS->FreePool (TempString);
+ }
+ }
+
+ //
+ // Ask for new password
+ //
+ ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
+ Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset state machine for interactive password
+ //
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
+ PasswordCallback (Selection, MenuOption, NULL);
+ }
+
+ gBS->FreePool (StringPtr);
+ return Status;
+ }
+
+ //
+ // Confirm new password
+ //
+ TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+ ASSERT (TempString);
+ Status = ReadString (MenuOption, gConfirmPassword, TempString);
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset state machine for interactive password
+ //
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
+ PasswordCallback (Selection, MenuOption, NULL);
+ }
+
+ gBS->FreePool (StringPtr);
+ gBS->FreePool (TempString);
+ return Status;
+ }
+
+ //
+ // Compare two typed-in new passwords
+ //
+ if (StrCmp (StringPtr, TempString) == 0) {
+ //
+ // Two password match, send it to Configuration Driver
+ //
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
+ PasswordCallback (Selection, MenuOption, StringPtr);
+ } else {
+ CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);
+ }
+ } else {
+ //
+ // Reset state machine for interactive password
+ //
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
+ PasswordCallback (Selection, MenuOption, NULL);
+ }
+
+ //
+ // Two password mismatch, prompt error message
+ //
+ do {
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ }
+
+ gBS->FreePool (TempString);
+ gBS->FreePool (StringPtr);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Process the help string: Split StringPtr to several lines of strings stored in
+ FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
+
+ @param StringPtr The entire help string.
+ @param FormattedString The oupput formatted string.
+ @param RowCount TRUE: if Question is selected.
+
+**/
+VOID
+ProcessHelpString (
+ IN CHAR16 *StringPtr,
+ OUT CHAR16 **FormattedString,
+ IN UINTN RowCount
+ )
+{
+ CONST UINTN BlockWidth = (UINTN) gHelpBlockWidth - 1;
+ UINTN AllocateSize;
+ //
+ // [PrevCurrIndex, CurrIndex) forms a range of a screen-line
+ //
+ UINTN CurrIndex;
+ UINTN PrevCurrIndex;
+ UINTN LineCount;
+ UINTN VirtualLineCount;
+ //
+ // GlyphOffset stores glyph width of current screen-line
+ //
+ UINTN GlyphOffset;
+ //
+ // GlyphWidth equals to 2 if we meet width directive
+ //
+ UINTN GlyphWidth;
+ //
+ // during scanning, we remember the position of last space character
+ // in case that if next word cannot put in current line, we could restore back to the position
+ // of last space character
+ // while we should also remmeber the glyph width of the last space character for restoring
+ //
+ UINTN LastSpaceIndex;
+ UINTN LastSpaceGlyphWidth;
+ //
+ // every time we begin to form a new screen-line, we should remember glyph width of single character
+ // of last line
+ //
+ UINTN LineStartGlyphWidth;
+ UINTN *IndexArray;
+ UINTN *OldIndexArray;
+
+ //
+ // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )
+ // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want
+ // to bring the width directive of the last line to current screen-line.
+ // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line
+ // different from that of "\wideabcde", we should remember the width directive.
+ //
+ AllocateSize = 0x20;
+ IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);
+
+ if (*FormattedString != NULL) {
+ gBS->FreePool (*FormattedString);
+ *FormattedString = NULL;
+ }
+
+ for (PrevCurrIndex = 0, CurrIndex = 0, LineCount = 0, LastSpaceIndex = 0,
+ IndexArray[0] = 0, GlyphWidth = 1, GlyphOffset = 0, LastSpaceGlyphWidth = 1, LineStartGlyphWidth = 1;
+ (StringPtr[CurrIndex] != CHAR_NULL);
+ CurrIndex ++) {
+
+ if (LineCount == AllocateSize) {
+ AllocateSize += 0x10;
+ OldIndexArray = IndexArray;
+ IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);
+ CopyMem (IndexArray, OldIndexArray, LineCount * sizeof (UINTN) * 3);
+ gBS->FreePool (OldIndexArray);
+ }
+ switch (StringPtr[CurrIndex]) {
+
+ case NARROW_CHAR:
+ case WIDE_CHAR:
+ GlyphWidth = ((StringPtr[CurrIndex] == WIDE_CHAR) ? 2 : 1);
+ if (CurrIndex == 0) {
+ LineStartGlyphWidth = GlyphWidth;
+ }
+ break;
+
+ //
+ // char is '\n'
+ // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN
+ //
+ case CHAR_LINEFEED:
+ //
+ // Store a range of string as a line
+ //
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex;
+ IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+ LineCount ++;
+ //
+ // Reset offset and save begin position of line
+ //
+ GlyphOffset = 0;
+ LineStartGlyphWidth = GlyphWidth;
+ PrevCurrIndex = CurrIndex + 1;
+ break;
+
+ //
+ // char is '\r'
+ // "\r\n" and "\r" both are handled here
+ //
+ case CHAR_CARRIAGE_RETURN:
+ if (StringPtr[CurrIndex + 1] == CHAR_LINEFEED) {
+ //
+ // next char is '\n'
+ //
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex;
+ IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+ LineCount ++;
+ CurrIndex ++;
+ }
+ GlyphOffset = 0;
+ LineStartGlyphWidth = GlyphWidth;
+ PrevCurrIndex = CurrIndex + 1;
+ break;
+
+ //
+ // char is space or other char
+ //
+ default:
+ GlyphOffset += GlyphWidth;
+ if (GlyphOffset >= BlockWidth) {
+ if (LastSpaceIndex > PrevCurrIndex) {
+ //
+ // LastSpaceIndex points to space inside current screen-line,
+ // restore to LastSpaceIndex
+ // (Otherwise the word is too long to fit one screen-line, just cut it)
+ //
+ CurrIndex = LastSpaceIndex;
+ GlyphWidth = LastSpaceGlyphWidth;
+ } else if (GlyphOffset > BlockWidth) {
+ //
+ // the word is too long to fit one screen-line and we don't get the chance
+ // of GlyphOffset == BlockWidth because GlyphWidth = 2
+ //
+ CurrIndex --;
+ }
+
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex + 1;
+ IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+ LineStartGlyphWidth = GlyphWidth;
+ LineCount ++;
+ //
+ // Reset offset and save begin position of line
+ //
+ GlyphOffset = 0;
+ PrevCurrIndex = CurrIndex + 1;
+ }
+
+ //
+ // LastSpaceIndex: remember position of last space
+ //
+ if (StringPtr[CurrIndex] == CHAR_SPACE) {
+ LastSpaceIndex = CurrIndex;
+ LastSpaceGlyphWidth = GlyphWidth;
+ }
+ break;
+ }
+ }
+
+ if (GlyphOffset > 0) {
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex;
+ IndexArray[LineCount*3+2] = GlyphWidth;
+ LineCount ++;
+ }
+
+ if (LineCount == 0) {
+ //
+ // in case we meet null string
+ //
+ IndexArray[0] = 0;
+ IndexArray[1] = 1;
+ //
+ // we assume null string's glyph width is 1
+ //
+ IndexArray[1] = 1;
+ LineCount ++;
+ }
+
+ VirtualLineCount = RowCount * (LineCount / RowCount + (LineCount % RowCount > 0));
+ *FormattedString = AllocateZeroPool (VirtualLineCount * (BlockWidth + 1) * sizeof (CHAR16) * 2);
+
+ for (CurrIndex = 0; CurrIndex < LineCount; CurrIndex ++) {
+ *(*FormattedString + CurrIndex * 2 * (BlockWidth + 1)) = (CHAR16) ((IndexArray[CurrIndex*3+2] == 2) ? WIDE_CHAR : NARROW_CHAR);
+ StrnCpy (
+ *FormattedString + CurrIndex * 2 * (BlockWidth + 1) + 1,
+ StringPtr + IndexArray[CurrIndex*3],
+ IndexArray[CurrIndex*3+1]-IndexArray[CurrIndex*3]
+ );
+ }
+
+ gBS->FreePool (IndexArray);
+}
|