diff options
Diffstat (limited to 'MdeModulePkg/Universal/SetupBrowserDxe/Setup.c')
-rw-r--r-- | MdeModulePkg/Universal/SetupBrowserDxe/Setup.c | 4614 |
1 files changed, 2302 insertions, 2312 deletions
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index ff85775..40c2544 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -1,2312 +1,2302 @@ -/** @file -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. - -Module Name: - - Setup.c - -Abstract: - - Entry and initialization module for the browser. - - -**/ - -#include "Setup.h" -#include "Ui.h" - - -SETUP_DRIVER_PRIVATE_DATA mPrivateData = { - SETUP_DRIVER_SIGNATURE, - NULL, - { - SendForm, - BrowserCallback - }, - { - UnicodeVSPrint - } -}; - -EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; -EFI_HII_STRING_PROTOCOL *mHiiString; -EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting; - -BANNER_DATA *BannerData; -EFI_HII_HANDLE FrontPageHandle; -UINTN gClassOfVfr; -UINTN gFunctionKeySetting; -BOOLEAN gResetRequired; -BOOLEAN gNvUpdateRequired; -EFI_HII_HANDLE gHiiHandle; -BOOLEAN gFirstIn; -UINT16 gDirection; -EFI_SCREEN_DESCRIPTOR gScreenDimensions; -BOOLEAN gUpArrow; -BOOLEAN gDownArrow; - -// -// Browser Global Strings -// -CHAR16 *gFunctionOneString; -CHAR16 *gFunctionTwoString; -CHAR16 *gFunctionNineString; -CHAR16 *gFunctionTenString; -CHAR16 *gEnterString; -CHAR16 *gEnterCommitString; -CHAR16 *gEscapeString; -CHAR16 *gSaveFailed; -CHAR16 *gMoveHighlight; -CHAR16 *gMakeSelection; -CHAR16 *gDecNumericInput; -CHAR16 *gHexNumericInput; -CHAR16 *gToggleCheckBox; -CHAR16 *gPromptForData; -CHAR16 *gPromptForPassword; -CHAR16 *gPromptForNewPassword; -CHAR16 *gConfirmPassword; -CHAR16 *gConfirmError; -CHAR16 *gPassowordInvalid; -CHAR16 *gPressEnter; -CHAR16 *gEmptyString; -CHAR16 *gAreYouSure; -CHAR16 *gYesResponse; -CHAR16 *gNoResponse; -CHAR16 *gMiniString; -CHAR16 *gPlusString; -CHAR16 *gMinusString; -CHAR16 *gAdjustNumber; - -CHAR16 gPromptBlockWidth; -CHAR16 gOptionBlockWidth; -CHAR16 gHelpBlockWidth; - -EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; -EFI_GUID gSetupBrowserGuid = { - 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32} -}; - -FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = { - // - // Boot Manager - // - { - { - 0x847bc3fe, - 0xb974, - 0x446d, - { - 0x94, - 0x49, - 0x5a, - 0xd5, - 0x41, - 0x2e, - 0x99, - 0x3b - } - }, - NONE_FUNCTION_KEY_SETTING - }, - // - // Device Manager - // - { - { - 0x3ebfa8e6, - 0x511d, - 0x4b5b, - { - 0xa9, - 0x5f, - 0xfb, - 0x38, - 0x26, - 0xf, - 0x1c, - 0x27 - } - }, - NONE_FUNCTION_KEY_SETTING - }, - // - // BMM FormSet. - // - { - { - 0x642237c7, - 0x35d4, - 0x472d, - { - 0x83, - 0x65, - 0x12, - 0xe0, - 0xcc, - 0xf2, - 0x7a, - 0x22 - } - }, - NONE_FUNCTION_KEY_SETTING - }, - // - // BMM File Explorer FormSet. - // - { - { - 0x1f2d63e1, - 0xfebd, - 0x4dc7, - { - 0x9c, - 0xc5, - 0xba, - 0x2b, - 0x1c, - 0xef, - 0x9c, - 0x5b - } - }, - NONE_FUNCTION_KEY_SETTING - }, -}; - -EFI_STATUS -EFIAPI -SendForm ( - IN CONST EFI_FORM_BROWSER2_PROTOCOL *This, - IN EFI_HII_HANDLE *Handles, - IN UINTN HandleCount, - IN EFI_GUID *FormSetGuid, OPTIONAL - IN UINT16 FormId, OPTIONAL - IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL - ) -/*++ - -Routine Description: - This is the routine which an external caller uses to direct the browser - where to obtain it's information. - -Arguments: - This - The Form Browser protocol instanse. - Handles - A pointer to an array of Handles. If HandleCount > 1 we - display a list of the formsets for the handles specified. - HandleCount - The number of Handles specified in Handle. - FormSetGuid - This field points to the EFI_GUID which must match the Guid - field in the EFI_IFR_FORM_SET op-code for the specified - forms-based package. If FormSetGuid is NULL, then this - function will display the first found forms package. - FormId - This field specifies which EFI_IFR_FORM to render as the first - displayable page. If this field has a value of 0x0000, then - the forms browser will render the specified forms in their encoded order. - ScreenDimenions - This allows the browser to be called so that it occupies a - portion of the physical screen instead of dynamically determining the screen dimensions. - ActionRequest - Points to the action recommended by the form. - -Returns: - EFI_SUCCESS - The function completed successfully. - EFI_INVALID_PARAMETER - One of the parameters has an invalid value. - EFI_NOT_FOUND - No valid forms could be found to display. - ---*/ -{ - EFI_STATUS Status; - UI_MENU_SELECTION *Selection; - UINTN Index; - FORM_BROWSER_FORMSET *FormSet; - - Status = EFI_SUCCESS; - ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - - // - // Seed the dimensions in the global - // - gST->ConOut->QueryMode ( - gST->ConOut, - gST->ConOut->Mode->Mode, - &gScreenDimensions.RightColumn, - &gScreenDimensions.BottomRow - ); - - if (ScreenDimensions != NULL) { - // - // Check local dimension vs. global dimension. - // - if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) || - (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow) - ) { - return EFI_INVALID_PARAMETER; - } else { - // - // Local dimension validation. - // - if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) && - (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) && - ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) && - ( - (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT + - SCROLL_ARROW_HEIGHT * - 2 + - FRONT_PAGE_HEADER_HEIGHT + - FOOTER_HEIGHT + - 1 - ) - ) { - CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - } else { - return EFI_INVALID_PARAMETER; - } - } - } - - gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3); - gHelpBlockWidth = gOptionBlockWidth; - gPromptBlockWidth = gOptionBlockWidth; - - // - // Initialize the strings for the browser, upon exit of the browser, the strings will be freed - // - InitializeBrowserStrings (); - - gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING; - gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS; - - // - // Ensure we are in Text mode - // - if (gFirstIn) { - gFirstIn = FALSE; - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - DisableQuietBoot (); - } - - for (Index = 0; Index < HandleCount; Index++) { - Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION)); - ASSERT (Selection != NULL); - - Selection->Handle = Handles[Index]; - if (FormSetGuid != NULL) { - CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID)); - Selection->FormId = FormId; - } - - do { - FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); - ASSERT (FormSet != NULL); - - // - // Initialize internal data structures of FormSet - // - Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet); - if (EFI_ERROR (Status)) { - DestroyFormSet (FormSet); - break; - } - Selection->FormSet = FormSet; - - // - // Initialize current settings of Questions in this FormSet - // - Status = InitializeCurrentSetting (FormSet); - if (EFI_ERROR (Status)) { - DestroyFormSet (FormSet); - break; - } - - // - // Display this formset - // - gCurrentSelection = Selection; - - Status = SetupBrowser (Selection); - - gCurrentSelection = NULL; - DestroyFormSet (FormSet); - - if (EFI_ERROR (Status)) { - break; - } - - } while (Selection->Action == UI_ACTION_REFRESH_FORMSET); - - gBS->FreePool (Selection); - } - - if (ActionRequest != NULL) { - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - if (gResetRequired) { - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET; - } - } - - FreeBrowserStrings (); - - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->ClearScreen (gST->ConOut); - - return Status; -} - - -/** - This function is called by a callback handler to retrieve uncommitted state - data from the browser. - - @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL - instance. - @param ResultsDataSize A pointer to the size of the buffer associated - with ResultsData. - @param ResultsData A string returned from an IFR browser or - equivalent. The results string will have no - routing information in them. - @param RetrieveData A BOOLEAN field which allows an agent to retrieve - (if RetrieveData = TRUE) data from the uncommitted - browser state information or set (if RetrieveData - = FALSE) data in the uncommitted browser state - information. - @param VariableGuid An optional field to indicate the target variable - GUID name to use. - @param VariableName An optional field to indicate the target - human-readable variable name. - - @retval EFI_SUCCESS The results have been distributed or are awaiting - distribution. - @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to - contain the results data. - -**/ -EFI_STATUS -EFIAPI -BrowserCallback ( - IN CONST EFI_FORM_BROWSER2_PROTOCOL *This, - IN OUT UINTN *ResultsDataSize, - IN OUT EFI_STRING ResultsData, - IN BOOLEAN RetrieveData, - IN CONST EFI_GUID *VariableGuid, OPTIONAL - IN CONST CHAR16 *VariableName OPTIONAL - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORMSET_STORAGE *Storage; - FORM_BROWSER_FORMSET *FormSet; - BOOLEAN Found; - CHAR16 *ConfigResp; - CHAR16 *StrPtr; - UINTN BufferSize; - UINTN TmpSize; - - if (ResultsDataSize == NULL || ResultsData == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (gCurrentSelection == NULL) { - return EFI_NOT_READY; - } - - Storage = NULL; - ConfigResp = NULL; - FormSet = gCurrentSelection->FormSet; - - // - // Find target storage - // - Link = GetFirstNode (&FormSet->StorageListHead); - if (IsNull (&FormSet->StorageListHead, Link)) { - return EFI_UNSUPPORTED; - } - - if (VariableGuid != NULL) { - // - // Try to find target storage - // - Found = FALSE; - while (!IsNull (&FormSet->StorageListHead, Link)) { - Storage = FORMSET_STORAGE_FROM_LINK (Link); - Link = GetNextNode (&FormSet->StorageListHead, Link); - - if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) { - if (Storage->Type == EFI_HII_VARSTORE_BUFFER) { - // - // Buffer storage require both GUID and Name - // - if (VariableName == NULL) { - return EFI_NOT_FOUND; - } - - if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) { - continue; - } - } - Found = TRUE; - break; - } - } - - if (!Found) { - return EFI_NOT_FOUND; - } - } else { - // - // GUID/Name is not specified, take the first storage in FormSet - // - Storage = FORMSET_STORAGE_FROM_LINK (Link); - } - - if (RetrieveData) { - // - // Skip if there is no RequestElement - // - if (Storage->ElementCount == 0) { - return EFI_SUCCESS; - } - - // - // Generate <ConfigResp> - // - Status = StorageToConfigResp (Storage, &ConfigResp); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Skip <ConfigHdr> and '&' to point to <ConfigBody> - // - StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1; - - BufferSize = StrSize (StrPtr); - if (*ResultsDataSize < BufferSize) { - *ResultsDataSize = BufferSize; - - gBS->FreePool (ConfigResp); - return EFI_BUFFER_TOO_SMALL; - } - - *ResultsDataSize = BufferSize; - CopyMem (ResultsData, StrPtr, BufferSize); - - gBS->FreePool (ConfigResp); - } else { - // - // Prepare <ConfigResp> - // - TmpSize = StrLen (ResultsData); - BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16); - ConfigResp = AllocateZeroPool (BufferSize); - ASSERT (ConfigResp != NULL); - - StrCpy (ConfigResp, Storage->ConfigHdr); - StrCat (ConfigResp, L"&"); - StrCat (ConfigResp, ResultsData); - - // - // Update Browser uncommited data - // - Status = ConfigRespToStorage (Storage, ConfigResp); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} - - -/** - Initialize Setup - - @param entry EFI_IMAGE_ENTRY_POINT) - - @retval EFI_SUCCESS Setup loaded. - @retval other Setup Error - -**/ -EFI_STATUS -EFIAPI -InitializeSetup ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_HANDLE HiiDriverHandle; - EFI_HII_PACKAGE_LIST_HEADER *PackageList; - - // - // Locate required Hii relative protocols - // - Status = gBS->LocateProtocol ( - &gEfiHiiDatabaseProtocolGuid, - NULL, - (VOID **) &mHiiDatabase - ); - ASSERT_EFI_ERROR (Status); - - Status = gBS->LocateProtocol ( - &gEfiHiiStringProtocolGuid, - NULL, - (VOID **) &mHiiString - ); - ASSERT_EFI_ERROR (Status); - - Status = gBS->LocateProtocol ( - &gEfiHiiConfigRoutingProtocolGuid, - NULL, - (VOID **) &mHiiConfigRouting - ); - ASSERT_EFI_ERROR (Status); - - // - // Publish our HII data - // - Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle); - ASSERT_EFI_ERROR (Status); - - PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings); - ASSERT (PackageList != NULL); - Status = mHiiDatabase->NewPackageList ( - mHiiDatabase, - PackageList, - HiiDriverHandle, - &gHiiHandle - ); - ASSERT_EFI_ERROR (Status); - - // - // Initialize Driver private data - // - gFirstIn = TRUE; - BannerData = AllocateZeroPool (sizeof (BANNER_DATA)); - ASSERT (BannerData != NULL); - - // - // Install FormBrowser2 protocol - // - mPrivateData.Handle = NULL; - Status = gBS->InstallProtocolInterface ( - &mPrivateData.Handle, - &gEfiFormBrowser2ProtocolGuid, - EFI_NATIVE_INTERFACE, - &mPrivateData.FormBrowser2 - ); - ASSERT_EFI_ERROR (Status); - - // - // Install Print protocol - // - Status = gBS->InstallProtocolInterface ( - &mPrivateData.Handle, - &gEfiPrintProtocolGuid, - EFI_NATIVE_INTERFACE, - &mPrivateData.Print - ); - - return Status; -} - - -/** - Create a new string in HII Package List. - - @param String The String to be added - @param HiiHandle The package list in the HII database to insert the - specified string. - - @return The output string. - -**/ -EFI_STRING_ID -NewString ( - IN CHAR16 *String, - IN EFI_HII_HANDLE HiiHandle - ) -{ - EFI_STRING_ID StringId; - EFI_STATUS Status; - - StringId = 0; - Status = HiiLibNewString (HiiHandle, &StringId, String); - ASSERT_EFI_ERROR (Status); - - return StringId; -} - - -/** - Delete a string from HII Package List. - - @param StringId Id of the string in HII database. - @param HiiHandle The HII package list handle. - - @retval EFI_SUCCESS The string was deleted successfully. - -**/ -EFI_STATUS -DeleteString ( - IN EFI_STRING_ID StringId, - IN EFI_HII_HANDLE HiiHandle - ) -{ - CHAR16 NullChar; - - NullChar = CHAR_NULL; - return HiiLibSetString (HiiHandle, StringId, &NullChar); -} - - -/** - Get the string based on the StringId and HII Package List Handle. - - @param Token The String's ID. - @param HiiHandle The package list in the HII database to search for - the specified string. - - @return The output string. - -**/ -CHAR16 * -GetToken ( - IN EFI_STRING_ID Token, - IN EFI_HII_HANDLE HiiHandle - ) -{ - EFI_STATUS Status; - CHAR16 *String; - UINTN BufferLength; - - // - // Set default string size assumption at no more than 256 bytes - // - BufferLength = 0x100; - String = AllocateZeroPool (BufferLength); - ASSERT (String != NULL); - - Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength); - - if (Status == EFI_BUFFER_TOO_SMALL) { - gBS->FreePool (String); - String = AllocateZeroPool (BufferLength); - ASSERT (String != NULL); - - Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength); - } - ASSERT_EFI_ERROR (Status); - - return String; -} - - -/** - Allocate new memory and then copy the Unicode string Source to Destination. - - @param Dest Location to copy string - @param Src String to copy - - @return NONE - -**/ -VOID -NewStringCpy ( - IN OUT CHAR16 **Dest, - IN CHAR16 *Src - ) -{ - SafeFreePool (*Dest); - *Dest = AllocateCopyPool (StrSize (Src), Src); - ASSERT (*Dest != NULL); -} - - -/** - Allocate new memory and concatinate Source on the end of Destination. - - @param Dest String to added to the end of. - @param Src String to concatinate. - - @return NONE - -**/ -VOID -NewStringCat ( - IN OUT CHAR16 **Dest, - IN CHAR16 *Src - ) -{ - CHAR16 *NewString; - UINTN TmpSize; - - if (*Dest == NULL) { - NewStringCpy (Dest, Src); - return; - } - - TmpSize = StrSize (*Dest); - NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1); - ASSERT (NewString != NULL); - - StrCpy (NewString, *Dest); - StrCat (NewString, Src); - - gBS->FreePool (*Dest); - *Dest = NewString; -} - - -/** - Synchronize Storage's Edit copy to Shadow copy. - - @param Storage The Storage to be synchronized. - - @return NONE - -**/ -VOID -SynchronizeStorage ( - IN FORMSET_STORAGE *Storage - ) -{ - LIST_ENTRY *Link; - NAME_VALUE_NODE *Node; - - switch (Storage->Type) { - case EFI_HII_VARSTORE_BUFFER: - CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size); - break; - - case EFI_HII_VARSTORE_NAME_VALUE: - Link = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - - NewStringCpy (&Node->Value, Node->EditValue); - - Link = GetNextNode (&Storage->NameValueListHead, Link); - } - break; - - case EFI_HII_VARSTORE_EFI_VARIABLE: - default: - break; - } -} - - -/** - Get Value for given Name from a NameValue Storage. - - @param Storage The NameValue Storage. - @param Name The Name. - @param Value The retured Value. - - @retval EFI_SUCCESS Value found for given Name. - @retval EFI_NOT_FOUND No such Name found in NameValue storage. - -**/ -EFI_STATUS -GetValueByName ( - IN FORMSET_STORAGE *Storage, - IN CHAR16 *Name, - IN OUT CHAR16 **Value - ) -{ - LIST_ENTRY *Link; - NAME_VALUE_NODE *Node; - - *Value = NULL; - - Link = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - - if (StrCmp (Name, Node->Name) == 0) { - NewStringCpy (Value, Node->EditValue); - return EFI_SUCCESS; - } - - Link = GetNextNode (&Storage->NameValueListHead, Link); - } - - return EFI_NOT_FOUND; -} - - -/** - Set Value of given Name in a NameValue Storage. - - @param Storage The NameValue Storage. - @param Name The Name. - @param Value The Value to set. - - @retval EFI_SUCCESS Value found for given Name. - @retval EFI_NOT_FOUND No such Name found in NameValue storage. - -**/ -EFI_STATUS -SetValueByName ( - IN FORMSET_STORAGE *Storage, - IN CHAR16 *Name, - IN CHAR16 *Value - ) -{ - LIST_ENTRY *Link; - NAME_VALUE_NODE *Node; - - Link = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - - if (StrCmp (Name, Node->Name) == 0) { - SafeFreePool (Node->EditValue); - Node->EditValue = AllocateCopyPool (StrSize (Value), Value); - ASSERT (Node->EditValue != NULL); - return EFI_SUCCESS; - } - - Link = GetNextNode (&Storage->NameValueListHead, Link); - } - - return EFI_NOT_FOUND; -} - - -/** - Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>. - - @param Storage The Storage to be conveted. - @param ConfigResp The returned <ConfigResp>. - - @retval EFI_SUCCESS Convert success. - @retval EFI_INVALID_PARAMETER Incorrect storage type. - -**/ -EFI_STATUS -StorageToConfigResp ( - IN FORMSET_STORAGE *Storage, - IN CHAR16 **ConfigResp - ) -{ - EFI_STATUS Status; - EFI_STRING Progress; - LIST_ENTRY *Link; - NAME_VALUE_NODE *Node; - - Status = EFI_SUCCESS; - - switch (Storage->Type) { - case EFI_HII_VARSTORE_BUFFER: - Status = mHiiConfigRouting->BlockToConfig ( - mHiiConfigRouting, - Storage->ConfigRequest, - Storage->EditBuffer, - Storage->Size, - ConfigResp, - &Progress - ); - break; - - case EFI_HII_VARSTORE_NAME_VALUE: - *ConfigResp = NULL; - NewStringCat (ConfigResp, Storage->ConfigHdr); - - Link = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - - NewStringCat (ConfigResp, L"&"); - NewStringCat (ConfigResp, Node->Name); - NewStringCat (ConfigResp, L"="); - NewStringCat (ConfigResp, Node->EditValue); - - Link = GetNextNode (&Storage->NameValueListHead, Link); - } - break; - - case EFI_HII_VARSTORE_EFI_VARIABLE: - default: - Status = EFI_INVALID_PARAMETER; - break; - } - - return Status; -} - - -/** - Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage. - - @param Storage The Storage to receive the settings. - @param ConfigResp The <ConfigResp> to be converted. - - @retval EFI_SUCCESS Convert success. - @retval EFI_INVALID_PARAMETER Incorrect storage type. - -**/ -EFI_STATUS -ConfigRespToStorage ( - IN FORMSET_STORAGE *Storage, - IN CHAR16 *ConfigResp - ) -{ - EFI_STATUS Status; - EFI_STRING Progress; - UINTN BufferSize; - CHAR16 *StrPtr; - CHAR16 *Name; - CHAR16 *Value; - - Status = EFI_SUCCESS; - - switch (Storage->Type) { - case EFI_HII_VARSTORE_BUFFER: - BufferSize = Storage->Size; - Status = mHiiConfigRouting->ConfigToBlock ( - mHiiConfigRouting, - ConfigResp, - Storage->EditBuffer, - &BufferSize, - &Progress - ); - break; - - case EFI_HII_VARSTORE_NAME_VALUE: - StrPtr = StrStr (ConfigResp, L"&"); - while (StrPtr != NULL) { - // - // Skip '&' - // - StrPtr = StrPtr + 1; - Name = StrPtr; - StrPtr = StrStr (StrPtr, L"="); - if (StrPtr == NULL) { - break; - } - *StrPtr = 0; - - // - // Skip '=' - // - StrPtr = StrPtr + 1; - Value = StrPtr; - StrPtr = StrStr (StrPtr, L"&"); - if (StrPtr != NULL) { - *StrPtr = 0; - } - SetValueByName (Storage, Name, Value); - } - break; - - case EFI_HII_VARSTORE_EFI_VARIABLE: - default: - Status = EFI_INVALID_PARAMETER; - break; - } - - return Status; -} - - -/** - Get Question's current Value. - - @param FormSet FormSet data structure. - @param Form Form data structure. - @param Question Question to be initialized. - @param Cached TRUE: get from Edit copy FALSE: get from original - Storage - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -GetQuestionValue ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN OUT FORM_BROWSER_STATEMENT *Question, - IN BOOLEAN Cached - ) -{ - EFI_STATUS Status; - BOOLEAN Enabled; - BOOLEAN Pending; - UINT8 *Dst; - UINTN StorageWidth; - EFI_TIME EfiTime; - FORMSET_STORAGE *Storage; - EFI_IFR_TYPE_VALUE *QuestionValue; - CHAR16 *ConfigRequest; - CHAR16 *Progress; - CHAR16 *Result; - CHAR16 *Value; - UINTN Length; - BOOLEAN IsBufferStorage; - BOOLEAN IsString; - - Status = EFI_SUCCESS; - - // - // Statement don't have storage, skip them - // - if (Question->QuestionId == 0) { - return Status; - } - - // - // Question value is provided by an Expression, evaluate it - // - if (Question->ValueExpression != NULL) { - Status = EvaluateExpression (FormSet, Form, Question->ValueExpression); - if (!EFI_ERROR (Status)) { - CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE)); - } - return Status; - } - - // - // Question value is provided by RTC - // - Storage = Question->Storage; - QuestionValue = &Question->HiiValue.Value; - if (Storage == NULL) { - // - // It's a Question without storage, or RTC date/time - // - if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) { - // - // Date and time define the same Flags bit - // - switch (Question->Flags & EFI_QF_DATE_STORAGE) { - case QF_DATE_STORAGE_TIME: - Status = gRT->GetTime (&EfiTime, NULL); - break; - - case QF_DATE_STORAGE_WAKEUP: - Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime); - break; - - case QF_DATE_STORAGE_NORMAL: - default: - // - // For date/time without storage - // - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - if (Question->Operand == EFI_IFR_DATE_OP) { - QuestionValue->date.Year = EfiTime.Year; - QuestionValue->date.Month = EfiTime.Month; - QuestionValue->date.Day = EfiTime.Day; - } else { - QuestionValue->time.Hour = EfiTime.Hour; - QuestionValue->time.Minute = EfiTime.Minute; - QuestionValue->time.Second = EfiTime.Second; - } - } - - return EFI_SUCCESS; - } - - // - // Question value is provided by EFI variable - // - StorageWidth = Question->StorageWidth; - if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - if (Question->BufferValue != NULL) { - Dst = Question->BufferValue; - } else { - Dst = (UINT8 *) QuestionValue; - } - - Status = gRT->GetVariable ( - Question->VariableName, - &Storage->Guid, - NULL, - &StorageWidth, - Dst - ); - // - // Always return success, even this EFI variable doesn't exist - // - return EFI_SUCCESS; - } - - // - // Question Value is provided by Buffer Storage or NameValue Storage - // - if (Question->BufferValue != NULL) { - // - // This Question is password or orderedlist - // - Dst = Question->BufferValue; - } else { - // - // Other type of Questions - // - Dst = (UINT8 *) &Question->HiiValue.Value; - } - - IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE); - IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE); - if (Cached) { - if (IsBufferStorage) { - // - // Copy from storage Edit buffer - // - CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth); - } else { - Status = GetValueByName (Storage, Question->VariableName, &Value); - if (EFI_ERROR (Status)) { - return Status; - } - - if (IsString) { - // - // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD" - // - Length = StorageWidth + sizeof (CHAR16); - Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value); - } else { - Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL); - } - - gBS->FreePool (Value); - } - } else { - // - // Request current settings from Configuration Driver - // - if (FormSet->ConfigAccess == NULL) { - return EFI_NOT_FOUND; - } - - // - // <ConfigRequest> ::= <ConfigHdr> + <BlockName> || - // <ConfigHdr> + "&" + <VariableName> - // - if (IsBufferStorage) { - Length = StrLen (Storage->ConfigHdr); - Length += StrLen (Question->BlockName); - } else { - Length = StrLen (Storage->ConfigHdr); - Length += StrLen (Question->VariableName) + 1; - } - ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16)); - ASSERT (ConfigRequest != NULL); - - StrCpy (ConfigRequest, Storage->ConfigHdr); - if (IsBufferStorage) { - StrCat (ConfigRequest, Question->BlockName); - } else { - StrCat (ConfigRequest, L"&"); - StrCat (ConfigRequest, Question->VariableName); - } - - Status = FormSet->ConfigAccess->ExtractConfig ( - FormSet->ConfigAccess, - ConfigRequest, - &Progress, - &Result - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Skip <ConfigRequest> - // - Value = Result + Length; - if (IsBufferStorage) { - // - // Skip "&VALUE" - // - Value = Value + 6; - } - if (*Value != '=') { - gBS->FreePool (Result); - return EFI_NOT_FOUND; - } - // - // Skip '=', point to value - // - Value = Value + 1; - if (!IsBufferStorage && IsString) { - // - // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD" - // - Length = StorageWidth + sizeof (CHAR16); - Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value); - } else { - Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL); - if (EFI_ERROR (Status)) { - gBS->FreePool (Result); - return Status; - } - } - - // - // Synchronize Edit Buffer - // - if (IsBufferStorage) { - CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth); - } else { - SetValueByName (Storage, Question->VariableName, Value); - } - gBS->FreePool (Result); - } - - return Status; -} - - -/** - Save Question Value to edit copy(cached) or Storage(uncached). - - @param FormSet FormSet data structure. - @param Form Form data structure. - @param Question Pointer to the Question. - @param Cached TRUE: set to Edit copy FALSE: set to original - Storage - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -SetQuestionValue ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN OUT FORM_BROWSER_STATEMENT *Question, - IN BOOLEAN Cached - ) -{ - EFI_STATUS Status; - BOOLEAN Enabled; - BOOLEAN Pending; - UINT8 *Src; - EFI_TIME EfiTime; - UINTN BufferLen; - UINTN StorageWidth; - FORMSET_STORAGE *Storage; - EFI_IFR_TYPE_VALUE *QuestionValue; - CHAR16 *ConfigResp; - CHAR16 *Progress; - CHAR16 *Value; - UINTN Length; - BOOLEAN IsBufferStorage; - BOOLEAN IsString; - - Status = EFI_SUCCESS; - - // - // Statement don't have storage, skip them - // - if (Question->QuestionId == 0) { - return Status; - } - - // - // If Question value is provided by an Expression, then it is read only - // - if (Question->ValueExpression != NULL) { - return Status; - } - - // - // Question value is provided by RTC - // - Storage = Question->Storage; - QuestionValue = &Question->HiiValue.Value; - if (Storage == NULL) { - // - // It's a Question without storage, or RTC date/time - // - if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) { - // - // Date and time define the same Flags bit - // - switch (Question->Flags & EFI_QF_DATE_STORAGE) { - case QF_DATE_STORAGE_TIME: - Status = gRT->GetTime (&EfiTime, NULL); - break; - - case QF_DATE_STORAGE_WAKEUP: - Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime); - break; - - case QF_DATE_STORAGE_NORMAL: - default: - // - // For date/time without storage - // - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - if (Question->Operand == EFI_IFR_DATE_OP) { - EfiTime.Year = QuestionValue->date.Year; - EfiTime.Month = QuestionValue->date.Month; - EfiTime.Day = QuestionValue->date.Day; - } else { - EfiTime.Hour = QuestionValue->time.Hour; - EfiTime.Minute = QuestionValue->time.Minute; - EfiTime.Second = QuestionValue->time.Second; - } - - if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) { - Status = gRT->SetTime (&EfiTime); - } else { - Status = gRT->SetWakeupTime (TRUE, &EfiTime); - } - } - - return Status; - } - - // - // Question value is provided by EFI variable - // - StorageWidth = Question->StorageWidth; - if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - if (Question->BufferValue != NULL) { - Src = Question->BufferValue; - } else { - Src = (UINT8 *) QuestionValue; - } - - Status = gRT->SetVariable ( - Question->VariableName, - &Storage->Guid, - Storage->Attributes, - StorageWidth, - Src - ); - return Status; - } - - // - // Question Value is provided by Buffer Storage or NameValue Storage - // - if (Question->BufferValue != NULL) { - Src = Question->BufferValue; - } else { - Src = (UINT8 *) &Question->HiiValue.Value; - } - - IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE); - IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE); - if (IsBufferStorage) { - // - // Copy to storage edit buffer - // - CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth); - } else { - if (IsString) { - // - // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044" - // - Value = NULL; - BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16); - Value = AllocateZeroPool (BufferLen); - ASSERT (Value != NULL); - Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src); - ASSERT_EFI_ERROR (Status); - } else { - BufferLen = StorageWidth * 2 + 1; - Value = AllocateZeroPool (BufferLen * sizeof (CHAR16)); - ASSERT (Value != NULL); - BufToHexString (Value, &BufferLen, Src, StorageWidth); - ToLower (Value); - } - - Status = SetValueByName (Storage, Question->VariableName, Value); - gBS->FreePool (Value); - } - - if (!Cached) { - // - // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" || - // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>" - // - if (IsBufferStorage) { - Length = StrLen (Question->BlockName) + 7; - } else { - Length = StrLen (Question->VariableName) + 2; - } - if (!IsBufferStorage && IsString) { - Length += (StrLen ((CHAR16 *) Src) * 4); - } else { - Length += (StorageWidth * 2); - } - ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16)); - ASSERT (ConfigResp != NULL); - - StrCpy (ConfigResp, Storage->ConfigHdr); - if (IsBufferStorage) { - StrCat (ConfigResp, Question->BlockName); - StrCat (ConfigResp, L"&VALUE="); - } else { - StrCat (ConfigResp, L"&"); - StrCat (ConfigResp, Question->VariableName); - StrCat (ConfigResp, L"="); - } - - Value = ConfigResp + StrLen (ConfigResp); - if (!IsBufferStorage && IsString) { - // - // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044" - // - BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16); - Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src); - ASSERT_EFI_ERROR (Status); - } else { - BufferLen = StorageWidth * 2 + 1; - BufToHexString (Value, &BufferLen, Src, StorageWidth); - ToLower (Value); - } - - // - // Submit Question Value to Configuration Driver - // - if (FormSet->ConfigAccess != NULL) { - Status = FormSet->ConfigAccess->RouteConfig ( - FormSet->ConfigAccess, - ConfigResp, - &Progress - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (ConfigResp); - return Status; - } - } - gBS->FreePool (ConfigResp); - - // - // Synchronize shadow Buffer - // - SynchronizeStorage (Storage); - } - - return Status; -} - - -/** - Perform inconsistent check for a Form. - - @param FormSet FormSet data structure. - @param Form Form data structure. - @param Question The Question to be validated. - @param Type Validation type: InConsistent or NoSubmit - - @retval EFI_SUCCESS Form validation pass. - @retval other Form validation failed. - -**/ -EFI_STATUS -ValidateQuestion ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN FORM_BROWSER_STATEMENT *Question, - IN UINTN Type - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - LIST_ENTRY *ListHead; - EFI_STRING PopUp; - EFI_INPUT_KEY Key; - FORM_EXPRESSION *Expression; - - if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) { - ListHead = &Question->InconsistentListHead; - } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { - ListHead = &Question->NoSubmitListHead; - } else { - return EFI_UNSUPPORTED; - } - - Link = GetFirstNode (ListHead); - while (!IsNull (ListHead, Link)) { - Expression = FORM_EXPRESSION_FROM_LINK (Link); - - // - // Evaluate the expression - // - Status = EvaluateExpression (FormSet, Form, Expression); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Expression->Result.Value.b) { - // - // Condition meet, show up error message - // - if (Expression->Error != 0) { - PopUp = GetToken (Expression->Error, FormSet->HiiHandle); - do { - CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - gBS->FreePool (PopUp); - } - - return EFI_NOT_READY; - } - - Link = GetNextNode (ListHead, Link); - } - - return EFI_SUCCESS; -} - - -/** - Perform NoSubmit check for a Form. - - @param FormSet FormSet data structure. - @param Form Form data structure. - - @retval EFI_SUCCESS Form validation pass. - @retval other Form validation failed. - -**/ -EFI_STATUS -NoSubmitCheck ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Question; - - Link = GetFirstNode (&Form->StatementListHead); - while (!IsNull (&Form->StatementListHead, Link)) { - Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - - Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF); - if (EFI_ERROR (Status)) { - return Status; - } - - Link = GetNextNode (&Form->StatementListHead, Link); - } - - return EFI_SUCCESS; -} - - -/** - Submit a Form. - - @param FormSet FormSet data structure. - @param Form Form data structure. - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -SubmitForm ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - EFI_STRING ConfigResp; - EFI_STRING Progress; - FORMSET_STORAGE *Storage; - - // - // Validate the Form by NoSubmit check - // - Status = NoSubmitCheck (FormSet, Form); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Submit Buffer storage or Name/Value storage - // - Link = GetFirstNode (&FormSet->StorageListHead); - while (!IsNull (&FormSet->StorageListHead, Link)) { - Storage = FORMSET_STORAGE_FROM_LINK (Link); - Link = GetNextNode (&FormSet->StorageListHead, Link); - - if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - continue; - } - - // - // Skip if there is no RequestElement - // - if (Storage->ElementCount == 0) { - continue; - } - - // - // Prepare <ConfigResp> - // - Status = StorageToConfigResp (Storage, &ConfigResp); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Send <ConfigResp> to Configuration Driver - // - if (FormSet->ConfigAccess != NULL) { - Status = FormSet->ConfigAccess->RouteConfig ( - FormSet->ConfigAccess, - ConfigResp, - &Progress - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (ConfigResp); - return Status; - } - } - gBS->FreePool (ConfigResp); - - // - // Config success, update storage shadow Buffer - // - SynchronizeStorage (Storage); - } - - gNvUpdateRequired = FALSE; - - return EFI_SUCCESS; -} - - -/** - Reset Question to its default value. - - @param FormSet FormSet data structure. - @param DefaultId The Class of the default. - - @retval EFI_SUCCESS Question is reset to default value. - -**/ -EFI_STATUS -GetQuestionDefault ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN FORM_BROWSER_STATEMENT *Question, - IN UINT16 DefaultId - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - QUESTION_DEFAULT *Default; - QUESTION_OPTION *Option; - EFI_HII_VALUE *HiiValue; - UINT8 Index; - - Status = EFI_SUCCESS; - - // - // Statement don't have storage, skip them - // - if (Question->QuestionId == 0) { - return Status; - } - - // - // There are three ways to specify default value for a Question: - // 1, use nested EFI_IFR_DEFAULT (highest priority) - // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default) - // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority) - // - HiiValue = &Question->HiiValue; - - // - // EFI_IFR_DEFAULT has highest priority - // - if (!IsListEmpty (&Question->DefaultListHead)) { - Link = GetFirstNode (&Question->DefaultListHead); - while (!IsNull (&Question->DefaultListHead, Link)) { - Default = QUESTION_DEFAULT_FROM_LINK (Link); - - if (Default->DefaultId == DefaultId) { - if (Default->ValueExpression != NULL) { - // - // Default is provided by an Expression, evaluate it - // - Status = EvaluateExpression (FormSet, Form, Default->ValueExpression); - if (EFI_ERROR (Status)) { - return Status; - } - - CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE)); - } else { - // - // Default value is embedded in EFI_IFR_DEFAULT - // - CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE)); - } - - return EFI_SUCCESS; - } - - Link = GetNextNode (&Question->DefaultListHead, Link); - } - } - - // - // EFI_ONE_OF_OPTION - // - if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) { - if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) { - // - // OneOfOption could only provide Standard and Manufacturing default - // - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - Option = QUESTION_OPTION_FROM_LINK (Link); - - if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) || - ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG)) - ) { - CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE)); - - return EFI_SUCCESS; - } - - Link = GetNextNode (&Question->OptionListHead, Link); - } - } - } - - // - // EFI_IFR_CHECKBOX - lowest priority - // - if (Question->Operand == EFI_IFR_CHECKBOX_OP) { - if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) { - // - // Checkbox could only provide Standard and Manufacturing default - // - if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) || - ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG)) - ) { - HiiValue->Value.b = TRUE; - } else { - HiiValue->Value.b = FALSE; - } - - return EFI_SUCCESS; - } - } - - // - // For Questions without default - // - switch (Question->Operand) { - case EFI_IFR_NUMERIC_OP: - // - // Take minimal value as numeric's default value - // - HiiValue->Value.u64 = Question->Minimum; - break; - - case EFI_IFR_ONE_OF_OP: - // - // Take first oneof option as oneof's default value - // - Link = GetFirstNode (&Question->OptionListHead); - if (!IsNull (&Question->OptionListHead, Link)) { - Option = QUESTION_OPTION_FROM_LINK (Link); - CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE)); - } - break; - - case EFI_IFR_ORDERED_LIST_OP: - // - // Take option sequence in IFR as ordered list's default value - // - Index = 0; - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - Option = QUESTION_OPTION_FROM_LINK (Link); - - Question->BufferValue[Index] = Option->Value.Value.u8; - - Index++; - if (Index >= Question->MaxContainers) { - break; - } - - Link = GetNextNode (&Question->OptionListHead, Link); - } - break; - - default: - Status = EFI_NOT_FOUND; - break; - } - - return Status; -} - - -/** - Reset Questions in a Form to their default value. - - @param FormSet FormSet data structure. - @param Form The Form which to be reset. - @param DefaultId The Class of the default. - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -ExtractFormDefault ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN UINT16 DefaultId - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Question; - - Link = GetFirstNode (&Form->StatementListHead); - while (!IsNull (&Form->StatementListHead, Link)) { - Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&Form->StatementListHead, Link); - - // - // Reset Question to its default value - // - Status = GetQuestionDefault (FormSet, Form, Question, DefaultId); - if (EFI_ERROR (Status)) { - continue; - } - - // - // Synchronize Buffer storage's Edit buffer - // - if ((Question->Storage != NULL) && - (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) { - SetQuestionValue (FormSet, Form, Question, TRUE); - } - } - - return EFI_SUCCESS; -} - - -/** - Initialize Question's Edit copy from Storage. - - @param FormSet FormSet data structure. - @param Form Form data structure. - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -LoadFormConfig ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Question; - - Link = GetFirstNode (&Form->StatementListHead); - while (!IsNull (&Form->StatementListHead, Link)) { - Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - - // - // Initialize local copy of Value for each Question - // - Status = GetQuestionValue (FormSet, Form, Question, TRUE); - if (EFI_ERROR (Status)) { - return Status; - } - - Link = GetNextNode (&Form->StatementListHead, Link); - } - - return EFI_SUCCESS; -} - - -/** - Fill storage's edit copy with settings requested from Configuration Driver. - - @param FormSet FormSet data structure. - @param Storage Buffer Storage. - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -LoadStorage ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORMSET_STORAGE *Storage - ) -{ - EFI_STATUS Status; - EFI_STRING Progress; - EFI_STRING Result; - CHAR16 *StrPtr; - - if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - return EFI_SUCCESS; - } - - if (FormSet->ConfigAccess == NULL) { - return EFI_NOT_FOUND; - } - - if (Storage->ElementCount == 0) { - // - // Skip if there is no RequestElement - // - return EFI_SUCCESS; - } - - // - // Request current settings from Configuration Driver - // - Status = FormSet->ConfigAccess->ExtractConfig ( - FormSet->ConfigAccess, - Storage->ConfigRequest, - &Progress, - &Result - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Convert Result from <ConfigAltResp> to <ConfigResp> - // - StrPtr = StrStr (Result, L"ALTCFG"); - if (StrPtr != NULL) { - *StrPtr = L'\0'; - } - - Status = ConfigRespToStorage (Storage, Result); - gBS->FreePool (Result); - return Status; -} - - -/** - Get current setting of Questions. - - @param FormSet FormSet data structure. - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -InitializeCurrentSetting ( - IN OUT FORM_BROWSER_FORMSET *FormSet - ) -{ - LIST_ENTRY *Link; - FORMSET_STORAGE *Storage; - FORM_BROWSER_FORM *Form; - EFI_STATUS Status; - - // - // Extract default from IFR binary - // - Link = GetFirstNode (&FormSet->FormListHead); - while (!IsNull (&FormSet->FormListHead, Link)) { - Form = FORM_BROWSER_FORM_FROM_LINK (Link); - - Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD); - - Link = GetNextNode (&FormSet->FormListHead, Link); - } - - // - // Request current settings from Configuration Driver - // - Link = GetFirstNode (&FormSet->StorageListHead); - while (!IsNull (&FormSet->StorageListHead, Link)) { - Storage = FORMSET_STORAGE_FROM_LINK (Link); - - Status = LoadStorage (FormSet, Storage); - - // - // Now Edit Buffer is filled with default values(lower priority) and current - // settings(higher priority), sychronize it to shadow Buffer - // - if (!EFI_ERROR (Status)) { - SynchronizeStorage (Storage); - } - - Link = GetNextNode (&FormSet->StorageListHead, Link); - } - - return EFI_SUCCESS; -} - - -/** - Fetch the Ifr binary data of a FormSet. - - @param Handle PackageList Handle - @param FormSetGuid GUID of a formset. If not specified (NULL or zero - GUID), take the first FormSet found in package - list. - @param BinaryLength The length of the FormSet IFR binary. - @param BinaryData The buffer designed to receive the FormSet. - - @retval EFI_SUCCESS Buffer filled with the requested FormSet. - BufferLength was updated. - @retval EFI_INVALID_PARAMETER The handle is unknown. - @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot - be found with the requested FormId. - -**/ -EFI_STATUS -GetIfrBinaryData ( - IN EFI_HII_HANDLE Handle, - IN OUT EFI_GUID *FormSetGuid, - OUT UINTN *BinaryLength, - OUT UINT8 **BinaryData - ) -{ - EFI_STATUS Status; - EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; - UINTN BufferSize; - UINT8 *Package; - UINT8 *OpCodeData; - UINT32 Offset; - UINT32 Offset2; - BOOLEAN ReturnDefault; - UINT32 PackageListLength; - EFI_HII_PACKAGE_HEADER PackageHeader; - - OpCodeData = NULL; - Package = NULL; - ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));; - - // - // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list - // - if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) { - ReturnDefault = TRUE; - } else { - ReturnDefault = FALSE; - } - - // - // Get HII PackageList - // - BufferSize = 0; - HiiPackageList = NULL; - Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); - if (Status == EFI_BUFFER_TOO_SMALL) { - HiiPackageList = AllocatePool (BufferSize); - ASSERT (HiiPackageList != NULL); - - Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); - } - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get Form package from this HII package List - // - Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); - Offset2 = 0; - CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); - - while (Offset < PackageListLength) { - Package = ((UINT8 *) HiiPackageList) + Offset; - CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); - - if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) { - // - // Search FormSet in this Form Package - // - Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); - while (Offset2 < PackageHeader.Length) { - OpCodeData = Package + Offset2; - - if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { - // - // Check whether return default FormSet - // - if (ReturnDefault) { - break; - } - - // - // FormSet GUID is specified, check it - // - if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { - break; - } - } - - Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - } - - if (Offset2 < PackageHeader.Length) { - // - // Target formset found - // - break; - } - } - - Offset += PackageHeader.Length; - } - - if (Offset >= PackageListLength) { - // - // Form package not found in this Package List - // - gBS->FreePool (HiiPackageList); - return EFI_NOT_FOUND; - } - - if (ReturnDefault && FormSetGuid != NULL) { - // - // Return the default FormSet GUID - // - CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)); - } - - // - // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes - // in this FormSet; So, here just simply copy the data from start of a FormSet to the end - // of the Form Package. - // - *BinaryLength = PackageHeader.Length - Offset2; - *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData); - - gBS->FreePool (HiiPackageList); - - if (*BinaryData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - return EFI_SUCCESS; -} - - -/** - Initialize the internal data structure of a FormSet. - - @param Handle PackageList Handle - @param FormSetGuid GUID of a formset. If not specified (NULL or zero - GUID), take the first FormSet found in package - list. - @param FormSet FormSet data structure. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_NOT_FOUND The specified FormSet could not be found. - -**/ -EFI_STATUS -InitializeFormSet ( - IN EFI_HII_HANDLE Handle, - IN OUT EFI_GUID *FormSetGuid, - OUT FORM_BROWSER_FORMSET *FormSet - ) -{ - EFI_STATUS Status; - EFI_HANDLE DriverHandle; - UINT16 Index; - - Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData); - if (EFI_ERROR (Status)) { - return Status; - } - - FormSet->HiiHandle = Handle; - CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID)); - - // - // Retrieve ConfigAccess Protocol associated with this HiiPackageList - // - Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle); - if (EFI_ERROR (Status)) { - return Status; - } - FormSet->DriverHandle = DriverHandle; - Status = gBS->HandleProtocol ( - DriverHandle, - &gEfiHiiConfigAccessProtocolGuid, - (VOID **) &FormSet->ConfigAccess - ); - if (EFI_ERROR (Status)) { - // - // Configuration Driver don't attach ConfigAccess protocol to its HII package - // list, then there will be no configuration action required - // - FormSet->ConfigAccess = NULL; - } - - // - // Parse the IFR binary OpCodes - // - Status = ParseOpCodes (FormSet); - if (EFI_ERROR (Status)) { - return Status; - } - - gClassOfVfr = FormSet->SubClass; - if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { - FrontPageHandle = FormSet->HiiHandle; - } - - // - // Match GUID to find out the function key setting. If match fail, use the default setting. - // - for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) { - if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) { - // - // Update the function key setting. - // - gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting; - // - // Function key prompt can not be displayed if the function key has been disabled. - // - if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) { - gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); - } - - if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) { - gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); - } - - if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) { - gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); - } - - if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) { - gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); - } - } - } - - return Status; -} +/** @file
+Entry and initialization module for the browser.
+
+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"
+
+
+SETUP_DRIVER_PRIVATE_DATA mPrivateData = {
+ SETUP_DRIVER_SIGNATURE,
+ NULL,
+ {
+ SendForm,
+ BrowserCallback
+ },
+ {
+ UnicodeVSPrint
+ }
+};
+
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+EFI_HII_STRING_PROTOCOL *mHiiString;
+EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
+
+BANNER_DATA *BannerData;
+EFI_HII_HANDLE FrontPageHandle;
+UINTN gClassOfVfr;
+UINTN gFunctionKeySetting;
+BOOLEAN gResetRequired;
+BOOLEAN gNvUpdateRequired;
+EFI_HII_HANDLE gHiiHandle;
+BOOLEAN gFirstIn;
+UINT16 gDirection;
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+BOOLEAN gUpArrow;
+BOOLEAN gDownArrow;
+
+//
+// Browser Global Strings
+//
+CHAR16 *gFunctionOneString;
+CHAR16 *gFunctionTwoString;
+CHAR16 *gFunctionNineString;
+CHAR16 *gFunctionTenString;
+CHAR16 *gEnterString;
+CHAR16 *gEnterCommitString;
+CHAR16 *gEscapeString;
+CHAR16 *gSaveFailed;
+CHAR16 *gMoveHighlight;
+CHAR16 *gMakeSelection;
+CHAR16 *gDecNumericInput;
+CHAR16 *gHexNumericInput;
+CHAR16 *gToggleCheckBox;
+CHAR16 *gPromptForData;
+CHAR16 *gPromptForPassword;
+CHAR16 *gPromptForNewPassword;
+CHAR16 *gConfirmPassword;
+CHAR16 *gConfirmError;
+CHAR16 *gPassowordInvalid;
+CHAR16 *gPressEnter;
+CHAR16 *gEmptyString;
+CHAR16 *gAreYouSure;
+CHAR16 *gYesResponse;
+CHAR16 *gNoResponse;
+CHAR16 *gMiniString;
+CHAR16 *gPlusString;
+CHAR16 *gMinusString;
+CHAR16 *gAdjustNumber;
+
+CHAR16 gPromptBlockWidth;
+CHAR16 gOptionBlockWidth;
+CHAR16 gHelpBlockWidth;
+
+EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
+EFI_GUID gSetupBrowserGuid = {
+ 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
+};
+
+FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
+ //
+ // Boot Manager
+ //
+ {
+ {
+ 0x847bc3fe,
+ 0xb974,
+ 0x446d,
+ {
+ 0x94,
+ 0x49,
+ 0x5a,
+ 0xd5,
+ 0x41,
+ 0x2e,
+ 0x99,
+ 0x3b
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // Device Manager
+ //
+ {
+ {
+ 0x3ebfa8e6,
+ 0x511d,
+ 0x4b5b,
+ {
+ 0xa9,
+ 0x5f,
+ 0xfb,
+ 0x38,
+ 0x26,
+ 0xf,
+ 0x1c,
+ 0x27
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // BMM FormSet.
+ //
+ {
+ {
+ 0x642237c7,
+ 0x35d4,
+ 0x472d,
+ {
+ 0x83,
+ 0x65,
+ 0x12,
+ 0xe0,
+ 0xcc,
+ 0xf2,
+ 0x7a,
+ 0x22
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // BMM File Explorer FormSet.
+ //
+ {
+ {
+ 0x1f2d63e1,
+ 0xfebd,
+ 0x4dc7,
+ {
+ 0x9c,
+ 0xc5,
+ 0xba,
+ 0x2b,
+ 0x1c,
+ 0xef,
+ 0x9c,
+ 0x5b
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+};
+
+/**
+ This is the routine which an external caller uses to direct the browser
+ where to obtain it's information.
+
+
+ @param This The Form Browser protocol instanse.
+ @param Handles A pointer to an array of Handles. If HandleCount > 1 we
+ display a list of the formsets for the handles specified.
+ @param HandleCount The number of Handles specified in Handle.
+ @param FormSetGuid This field points to the EFI_GUID which must match the Guid
+ field in the EFI_IFR_FORM_SET op-code for the specified
+ forms-based package. If FormSetGuid is NULL, then this
+ function will display the first found forms package.
+ @param FormId This field specifies which EFI_IFR_FORM to render as the first
+ displayable page. If this field has a value of 0x0000, then
+ the forms browser will render the specified forms in their encoded order.
+ ScreenDimenions - This allows the browser to be called so that it occupies a
+ portion of the physical screen instead of dynamically determining the screen dimensions.
+ ActionRequest - Points to the action recommended by the form.
+ @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
+ characters.
+ @param ActionRequest Points to the action recommended by the form.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_NOT_FOUND No valid forms could be found to display.
+
+**/
+EFI_STATUS
+EFIAPI
+SendForm (
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN EFI_HII_HANDLE *Handles,
+ IN UINTN HandleCount,
+ IN EFI_GUID *FormSetGuid, OPTIONAL
+ IN UINT16 FormId, OPTIONAL
+ IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UI_MENU_SELECTION *Selection;
+ UINTN Index;
+ FORM_BROWSER_FORMSET *FormSet;
+
+ Status = EFI_SUCCESS;
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ //
+ // Seed the dimensions in the global
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &gScreenDimensions.RightColumn,
+ &gScreenDimensions.BottomRow
+ );
+
+ if (ScreenDimensions != NULL) {
+ //
+ // Check local dimension vs. global dimension.
+ //
+ if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
+ (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Local dimension validation.
+ //
+ if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
+ (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
+ ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
+ (
+ (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
+ SCROLL_ARROW_HEIGHT *
+ 2 +
+ FRONT_PAGE_HEADER_HEIGHT +
+ FOOTER_HEIGHT +
+ 1
+ )
+ ) {
+ CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
+ gHelpBlockWidth = gOptionBlockWidth;
+ gPromptBlockWidth = gOptionBlockWidth;
+
+ //
+ // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
+ //
+ InitializeBrowserStrings ();
+
+ gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
+ gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;
+
+ //
+ // Ensure we are in Text mode
+ //
+ if (gFirstIn) {
+ gFirstIn = FALSE;
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ DisableQuietBoot ();
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
+ ASSERT (Selection != NULL);
+
+ Selection->Handle = Handles[Index];
+ if (FormSetGuid != NULL) {
+ CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
+ Selection->FormId = FormId;
+ }
+
+ do {
+ FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
+ ASSERT (FormSet != NULL);
+
+ //
+ // Initialize internal data structures of FormSet
+ //
+ Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
+ if (EFI_ERROR (Status)) {
+ DestroyFormSet (FormSet);
+ break;
+ }
+ Selection->FormSet = FormSet;
+
+ //
+ // Initialize current settings of Questions in this FormSet
+ //
+ Status = InitializeCurrentSetting (FormSet);
+ if (EFI_ERROR (Status)) {
+ DestroyFormSet (FormSet);
+ break;
+ }
+
+ //
+ // Display this formset
+ //
+ gCurrentSelection = Selection;
+
+ Status = SetupBrowser (Selection);
+
+ gCurrentSelection = NULL;
+ DestroyFormSet (FormSet);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
+
+ gBS->FreePool (Selection);
+ }
+
+ if (ActionRequest != NULL) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ if (gResetRequired) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
+ }
+ }
+
+ FreeBrowserStrings ();
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ return Status;
+}
+
+
+/**
+ This function is called by a callback handler to retrieve uncommitted state
+ data from the browser.
+
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
+ instance.
+ @param ResultsDataSize A pointer to the size of the buffer associated
+ with ResultsData.
+ @param ResultsData A string returned from an IFR browser or
+ equivalent. The results string will have no
+ routing information in them.
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve
+ (if RetrieveData = TRUE) data from the uncommitted
+ browser state information or set (if RetrieveData
+ = FALSE) data in the uncommitted browser state
+ information.
+ @param VariableGuid An optional field to indicate the target variable
+ GUID name to use.
+ @param VariableName An optional field to indicate the target
+ human-readable variable name.
+
+ @retval EFI_SUCCESS The results have been distributed or are awaiting
+ distribution.
+ @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
+ contain the results data.
+
+**/
+EFI_STATUS
+EFIAPI
+BrowserCallback (
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN OUT UINTN *ResultsDataSize,
+ IN OUT EFI_STRING ResultsData,
+ IN BOOLEAN RetrieveData,
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL
+ IN CONST CHAR16 *VariableName OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORMSET_STORAGE *Storage;
+ FORM_BROWSER_FORMSET *FormSet;
+ BOOLEAN Found;
+ CHAR16 *ConfigResp;
+ CHAR16 *StrPtr;
+ UINTN BufferSize;
+ UINTN TmpSize;
+
+ if (ResultsDataSize == NULL || ResultsData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (gCurrentSelection == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Storage = NULL;
+ ConfigResp = NULL;
+ FormSet = gCurrentSelection->FormSet;
+
+ //
+ // Find target storage
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ if (IsNull (&FormSet->StorageListHead, Link)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (VariableGuid != NULL) {
+ //
+ // Try to find target storage
+ //
+ Found = FALSE;
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+ if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+ //
+ // Buffer storage require both GUID and Name
+ //
+ if (VariableName == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
+ continue;
+ }
+ }
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ //
+ // GUID/Name is not specified, take the first storage in FormSet
+ //
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ }
+
+ if (RetrieveData) {
+ //
+ // Skip if there is no RequestElement
+ //
+ if (Storage->ElementCount == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Generate <ConfigResp>
+ //
+ Status = StorageToConfigResp (Storage, &ConfigResp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Skip <ConfigHdr> and '&' to point to <ConfigBody>
+ //
+ StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
+
+ BufferSize = StrSize (StrPtr);
+ if (*ResultsDataSize < BufferSize) {
+ *ResultsDataSize = BufferSize;
+
+ gBS->FreePool (ConfigResp);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *ResultsDataSize = BufferSize;
+ CopyMem (ResultsData, StrPtr, BufferSize);
+
+ gBS->FreePool (ConfigResp);
+ } else {
+ //
+ // Prepare <ConfigResp>
+ //
+ TmpSize = StrLen (ResultsData);
+ BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
+ ConfigResp = AllocateZeroPool (BufferSize);
+ ASSERT (ConfigResp != NULL);
+
+ StrCpy (ConfigResp, Storage->ConfigHdr);
+ StrCat (ConfigResp, L"&");
+ StrCat (ConfigResp, ResultsData);
+
+ //
+ // Update Browser uncommited data
+ //
+ Status = ConfigRespToStorage (Storage, ConfigResp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Setup Browser driver.
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
+ @return Other value if failed to initialize the Setup Browser module.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSetup (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE HiiDriverHandle;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Locate required Hii relative protocols
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **) &mHiiDatabase
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiStringProtocolGuid,
+ NULL,
+ (VOID **) &mHiiString
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **) &mHiiConfigRouting
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
+ ASSERT (PackageList != NULL);
+ Status = mHiiDatabase->NewPackageList (
+ mHiiDatabase,
+ PackageList,
+ HiiDriverHandle,
+ &gHiiHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Driver private data
+ //
+ gFirstIn = TRUE;
+ BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
+ ASSERT (BannerData != NULL);
+
+ //
+ // Install FormBrowser2 protocol
+ //
+ mPrivateData.Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &mPrivateData.Handle,
+ &gEfiFormBrowser2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.FormBrowser2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Print protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mPrivateData.Handle,
+ &gEfiPrintProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.Print
+ );
+
+ return Status;
+}
+
+
+/**
+ Create a new string in HII Package List.
+
+ @param String The String to be added
+ @param HiiHandle The package list in the HII database to insert the
+ specified string.
+
+ @return The output string.
+
+**/
+EFI_STRING_ID
+NewString (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STRING_ID StringId;
+ EFI_STATUS Status;
+
+ StringId = 0;
+ Status = HiiLibNewString (HiiHandle, &StringId, String);
+ ASSERT_EFI_ERROR (Status);
+
+ return StringId;
+}
+
+
+/**
+ Delete a string from HII Package List.
+
+ @param StringId Id of the string in HII database.
+ @param HiiHandle The HII package list handle.
+
+ @retval EFI_SUCCESS The string was deleted successfully.
+
+**/
+EFI_STATUS
+DeleteString (
+ IN EFI_STRING_ID StringId,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ CHAR16 NullChar;
+
+ NullChar = CHAR_NULL;
+ return HiiLibSetString (HiiHandle, StringId, &NullChar);
+}
+
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param Token The String's ID.
+ @param HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *String;
+ UINTN BufferLength;
+
+ //
+ // Set default string size assumption at no more than 256 bytes
+ //
+ BufferLength = 0x100;
+ String = AllocateZeroPool (BufferLength);
+ ASSERT (String != NULL);
+
+ Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ gBS->FreePool (String);
+ String = AllocateZeroPool (BufferLength);
+ ASSERT (String != NULL);
+
+ Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ return String;
+}
+
+
+/**
+ Allocate new memory and then copy the Unicode string Source to Destination.
+
+ @param Dest Location to copy string
+ @param Src String to copy
+
+**/
+VOID
+NewStringCpy (
+ IN OUT CHAR16 **Dest,
+ IN CHAR16 *Src
+ )
+{
+ SafeFreePool (*Dest);
+ *Dest = AllocateCopyPool (StrSize (Src), Src);
+ ASSERT (*Dest != NULL);
+}
+
+
+/**
+ Allocate new memory and concatinate Source on the end of Destination.
+
+ @param Dest String to added to the end of.
+ @param Src String to concatinate.
+
+**/
+VOID
+NewStringCat (
+ IN OUT CHAR16 **Dest,
+ IN CHAR16 *Src
+ )
+{
+ CHAR16 *NewString;
+ UINTN TmpSize;
+
+ if (*Dest == NULL) {
+ NewStringCpy (Dest, Src);
+ return;
+ }
+
+ TmpSize = StrSize (*Dest);
+ NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
+ ASSERT (NewString != NULL);
+
+ StrCpy (NewString, *Dest);
+ StrCat (NewString, Src);
+
+ gBS->FreePool (*Dest);
+ *Dest = NewString;
+}
+
+
+/**
+ Synchronize Storage's Edit copy to Shadow copy.
+
+ @param Storage The Storage to be synchronized.
+
+**/
+VOID
+SynchronizeStorage (
+ IN FORMSET_STORAGE *Storage
+ )
+{
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ NewStringCpy (&Node->Value, Node->EditValue);
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ break;
+ }
+}
+
+
+/**
+ Get Value for given Name from a NameValue Storage.
+
+ @param Storage The NameValue Storage.
+ @param Name The Name.
+ @param Value The retured Value.
+
+ @retval EFI_SUCCESS Value found for given Name.
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.
+
+**/
+EFI_STATUS
+GetValueByName (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN OUT CHAR16 **Value
+ )
+{
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ *Value = NULL;
+
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrCmp (Name, Node->Name) == 0) {
+ NewStringCpy (Value, Node->EditValue);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Set Value of given Name in a NameValue Storage.
+
+ @param Storage The NameValue Storage.
+ @param Name The Name.
+ @param Value The Value to set.
+
+ @retval EFI_SUCCESS Value found for given Name.
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.
+
+**/
+EFI_STATUS
+SetValueByName (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN CHAR16 *Value
+ )
+{
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrCmp (Name, Node->Name) == 0) {
+ SafeFreePool (Node->EditValue);
+ Node->EditValue = AllocateCopyPool (StrSize (Value), Value);
+ ASSERT (Node->EditValue != NULL);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
+
+ @param Storage The Storage to be conveted.
+ @param ConfigResp The returned <ConfigResp>.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+StorageToConfigResp (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 **ConfigResp
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ Status = EFI_SUCCESS;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ Status = mHiiConfigRouting->BlockToConfig (
+ mHiiConfigRouting,
+ Storage->ConfigRequest,
+ Storage->EditBuffer,
+ Storage->Size,
+ ConfigResp,
+ &Progress
+ );
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ *ConfigResp = NULL;
+ NewStringCat (ConfigResp, Storage->ConfigHdr);
+
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ NewStringCat (ConfigResp, L"&");
+ NewStringCat (ConfigResp, Node->Name);
+ NewStringCat (ConfigResp, L"=");
+ NewStringCat (ConfigResp, Node->EditValue);
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
+
+ @param Storage The Storage to receive the settings.
+ @param ConfigResp The <ConfigResp> to be converted.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+ConfigRespToStorage (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 *ConfigResp
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ UINTN BufferSize;
+ CHAR16 *StrPtr;
+ CHAR16 *Name;
+ CHAR16 *Value;
+
+ Status = EFI_SUCCESS;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ BufferSize = Storage->Size;
+ Status = mHiiConfigRouting->ConfigToBlock (
+ mHiiConfigRouting,
+ ConfigResp,
+ Storage->EditBuffer,
+ &BufferSize,
+ &Progress
+ );
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ StrPtr = StrStr (ConfigResp, L"&");
+ while (StrPtr != NULL) {
+ //
+ // Skip '&'
+ //
+ StrPtr = StrPtr + 1;
+ Name = StrPtr;
+ StrPtr = StrStr (StrPtr, L"=");
+ if (StrPtr == NULL) {
+ break;
+ }
+ *StrPtr = 0;
+
+ //
+ // Skip '='
+ //
+ StrPtr = StrPtr + 1;
+ Value = StrPtr;
+ StrPtr = StrStr (StrPtr, L"&");
+ if (StrPtr != NULL) {
+ *StrPtr = 0;
+ }
+ SetValueByName (Storage, Name, Value);
+ }
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Get Question's current Value.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Question to be initialized.
+ @param Cached TRUE: get from Edit copy FALSE: get from original
+ Storage
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetQuestionValue (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN BOOLEAN Cached
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Enabled;
+ BOOLEAN Pending;
+ UINT8 *Dst;
+ UINTN StorageWidth;
+ EFI_TIME EfiTime;
+ FORMSET_STORAGE *Storage;
+ EFI_IFR_TYPE_VALUE *QuestionValue;
+ CHAR16 *ConfigRequest;
+ CHAR16 *Progress;
+ CHAR16 *Result;
+ CHAR16 *Value;
+ UINTN Length;
+ BOOLEAN IsBufferStorage;
+ BOOLEAN IsString;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ return Status;
+ }
+
+ //
+ // Question value is provided by an Expression, evaluate it
+ //
+ if (Question->ValueExpression != NULL) {
+ Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));
+ }
+ return Status;
+ }
+
+ //
+ // Question value is provided by RTC
+ //
+ Storage = Question->Storage;
+ QuestionValue = &Question->HiiValue.Value;
+ if (Storage == NULL) {
+ //
+ // It's a Question without storage, or RTC date/time
+ //
+ if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
+ //
+ // Date and time define the same Flags bit
+ //
+ switch (Question->Flags & EFI_QF_DATE_STORAGE) {
+ case QF_DATE_STORAGE_TIME:
+ Status = gRT->GetTime (&EfiTime, NULL);
+ break;
+
+ case QF_DATE_STORAGE_WAKEUP:
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
+ break;
+
+ case QF_DATE_STORAGE_NORMAL:
+ default:
+ //
+ // For date/time without storage
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ QuestionValue->date.Year = EfiTime.Year;
+ QuestionValue->date.Month = EfiTime.Month;
+ QuestionValue->date.Day = EfiTime.Day;
+ } else {
+ QuestionValue->time.Hour = EfiTime.Hour;
+ QuestionValue->time.Minute = EfiTime.Minute;
+ QuestionValue->time.Second = EfiTime.Second;
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Question value is provided by EFI variable
+ //
+ StorageWidth = Question->StorageWidth;
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ if (Question->BufferValue != NULL) {
+ Dst = Question->BufferValue;
+ } else {
+ Dst = (UINT8 *) QuestionValue;
+ }
+
+ Status = gRT->GetVariable (
+ Question->VariableName,
+ &Storage->Guid,
+ NULL,
+ &StorageWidth,
+ Dst
+ );
+ //
+ // Always return success, even this EFI variable doesn't exist
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Question Value is provided by Buffer Storage or NameValue Storage
+ //
+ if (Question->BufferValue != NULL) {
+ //
+ // This Question is password or orderedlist
+ //
+ Dst = Question->BufferValue;
+ } else {
+ //
+ // Other type of Questions
+ //
+ Dst = (UINT8 *) &Question->HiiValue.Value;
+ }
+
+ IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
+ IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
+ if (Cached) {
+ if (IsBufferStorage) {
+ //
+ // Copy from storage Edit buffer
+ //
+ CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+ } else {
+ Status = GetValueByName (Storage, Question->VariableName, &Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (IsString) {
+ //
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
+ //
+ Length = StorageWidth + sizeof (CHAR16);
+ Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
+ } else {
+ Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
+ }
+
+ gBS->FreePool (Value);
+ }
+ } else {
+ //
+ // Request current settings from Configuration Driver
+ //
+ if (FormSet->ConfigAccess == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
+ // <ConfigHdr> + "&" + <VariableName>
+ //
+ if (IsBufferStorage) {
+ Length = StrLen (Storage->ConfigHdr);
+ Length += StrLen (Question->BlockName);
+ } else {
+ Length = StrLen (Storage->ConfigHdr);
+ Length += StrLen (Question->VariableName) + 1;
+ }
+ ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
+ ASSERT (ConfigRequest != NULL);
+
+ StrCpy (ConfigRequest, Storage->ConfigHdr);
+ if (IsBufferStorage) {
+ StrCat (ConfigRequest, Question->BlockName);
+ } else {
+ StrCat (ConfigRequest, L"&");
+ StrCat (ConfigRequest, Question->VariableName);
+ }
+
+ Status = FormSet->ConfigAccess->ExtractConfig (
+ FormSet->ConfigAccess,
+ ConfigRequest,
+ &Progress,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Skip <ConfigRequest>
+ //
+ Value = Result + Length;
+ if (IsBufferStorage) {
+ //
+ // Skip "&VALUE"
+ //
+ Value = Value + 6;
+ }
+ if (*Value != '=') {
+ gBS->FreePool (Result);
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Skip '=', point to value
+ //
+ Value = Value + 1;
+ if (!IsBufferStorage && IsString) {
+ //
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
+ //
+ Length = StorageWidth + sizeof (CHAR16);
+ Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
+ } else {
+ Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Result);
+ return Status;
+ }
+ }
+
+ //
+ // Synchronize Edit Buffer
+ //
+ if (IsBufferStorage) {
+ CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
+ } else {
+ SetValueByName (Storage, Question->VariableName, Value);
+ }
+ gBS->FreePool (Result);
+ }
+
+ return Status;
+}
+
+
+/**
+ Save Question Value to edit copy(cached) or Storage(uncached).
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Pointer to the Question.
+ @param Cached TRUE: set to Edit copy FALSE: set to original
+ Storage
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+SetQuestionValue (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN BOOLEAN Cached
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Enabled;
+ BOOLEAN Pending;
+ UINT8 *Src;
+ EFI_TIME EfiTime;
+ UINTN BufferLen;
+ UINTN StorageWidth;
+ FORMSET_STORAGE *Storage;
+ EFI_IFR_TYPE_VALUE *QuestionValue;
+ CHAR16 *ConfigResp;
+ CHAR16 *Progress;
+ CHAR16 *Value;
+ UINTN Length;
+ BOOLEAN IsBufferStorage;
+ BOOLEAN IsString;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ return Status;
+ }
+
+ //
+ // If Question value is provided by an Expression, then it is read only
+ //
+ if (Question->ValueExpression != NULL) {
+ return Status;
+ }
+
+ //
+ // Question value is provided by RTC
+ //
+ Storage = Question->Storage;
+ QuestionValue = &Question->HiiValue.Value;
+ if (Storage == NULL) {
+ //
+ // It's a Question without storage, or RTC date/time
+ //
+ if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
+ //
+ // Date and time define the same Flags bit
+ //
+ switch (Question->Flags & EFI_QF_DATE_STORAGE) {
+ case QF_DATE_STORAGE_TIME:
+ Status = gRT->GetTime (&EfiTime, NULL);
+ break;
+
+ case QF_DATE_STORAGE_WAKEUP:
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
+ break;
+
+ case QF_DATE_STORAGE_NORMAL:
+ default:
+ //
+ // For date/time without storage
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ EfiTime.Year = QuestionValue->date.Year;
+ EfiTime.Month = QuestionValue->date.Month;
+ EfiTime.Day = QuestionValue->date.Day;
+ } else {
+ EfiTime.Hour = QuestionValue->time.Hour;
+ EfiTime.Minute = QuestionValue->time.Minute;
+ EfiTime.Second = QuestionValue->time.Second;
+ }
+
+ if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
+ Status = gRT->SetTime (&EfiTime);
+ } else {
+ Status = gRT->SetWakeupTime (TRUE, &EfiTime);
+ }
+ }
+
+ return Status;
+ }
+
+ //
+ // Question value is provided by EFI variable
+ //
+ StorageWidth = Question->StorageWidth;
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ if (Question->BufferValue != NULL) {
+ Src = Question->BufferValue;
+ } else {
+ Src = (UINT8 *) QuestionValue;
+ }
+
+ Status = gRT->SetVariable (
+ Question->VariableName,
+ &Storage->Guid,
+ Storage->Attributes,
+ StorageWidth,
+ Src
+ );
+ return Status;
+ }
+
+ //
+ // Question Value is provided by Buffer Storage or NameValue Storage
+ //
+ if (Question->BufferValue != NULL) {
+ Src = Question->BufferValue;
+ } else {
+ Src = (UINT8 *) &Question->HiiValue.Value;
+ }
+
+ IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
+ IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
+ if (IsBufferStorage) {
+ //
+ // Copy to storage edit buffer
+ //
+ CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+ } else {
+ if (IsString) {
+ //
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
+ //
+ Value = NULL;
+ BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
+ Value = AllocateZeroPool (BufferLen);
+ ASSERT (Value != NULL);
+ Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ BufferLen = StorageWidth * 2 + 1;
+ Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));
+ ASSERT (Value != NULL);
+ BufToHexString (Value, &BufferLen, Src, StorageWidth);
+ ToLower (Value);
+ }
+
+ Status = SetValueByName (Storage, Question->VariableName, Value);
+ gBS->FreePool (Value);
+ }
+
+ if (!Cached) {
+ //
+ // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
+ // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
+ //
+ if (IsBufferStorage) {
+ Length = StrLen (Question->BlockName) + 7;
+ } else {
+ Length = StrLen (Question->VariableName) + 2;
+ }
+ if (!IsBufferStorage && IsString) {
+ Length += (StrLen ((CHAR16 *) Src) * 4);
+ } else {
+ Length += (StorageWidth * 2);
+ }
+ ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
+ ASSERT (ConfigResp != NULL);
+
+ StrCpy (ConfigResp, Storage->ConfigHdr);
+ if (IsBufferStorage) {
+ StrCat (ConfigResp, Question->BlockName);
+ StrCat (ConfigResp, L"&VALUE=");
+ } else {
+ StrCat (ConfigResp, L"&");
+ StrCat (ConfigResp, Question->VariableName);
+ StrCat (ConfigResp, L"=");
+ }
+
+ Value = ConfigResp + StrLen (ConfigResp);
+ if (!IsBufferStorage && IsString) {
+ //
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
+ //
+ BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
+ Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ BufferLen = StorageWidth * 2 + 1;
+ BufToHexString (Value, &BufferLen, Src, StorageWidth);
+ ToLower (Value);
+ }
+
+ //
+ // Submit Question Value to Configuration Driver
+ //
+ if (FormSet->ConfigAccess != NULL) {
+ Status = FormSet->ConfigAccess->RouteConfig (
+ FormSet->ConfigAccess,
+ ConfigResp,
+ &Progress
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ConfigResp);
+ return Status;
+ }
+ }
+ gBS->FreePool (ConfigResp);
+
+ //
+ // Synchronize shadow Buffer
+ //
+ SynchronizeStorage (Storage);
+ }
+
+ return Status;
+}
+
+
+/**
+ Perform inconsistent check for a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question The Question to be validated.
+ @param Type Validation type: InConsistent or NoSubmit
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+ValidateQuestion (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINTN Type
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *ListHead;
+ EFI_STRING PopUp;
+ EFI_INPUT_KEY Key;
+ FORM_EXPRESSION *Expression;
+
+ if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
+ ListHead = &Question->InconsistentListHead;
+ } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+ ListHead = &Question->NoSubmitListHead;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ Link = GetFirstNode (ListHead);
+ while (!IsNull (ListHead, Link)) {
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+
+ //
+ // Evaluate the expression
+ //
+ Status = EvaluateExpression (FormSet, Form, Expression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Expression->Result.Value.b) {
+ //
+ // Condition meet, show up error message
+ //
+ if (Expression->Error != 0) {
+ PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
+ do {
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ gBS->FreePool (PopUp);
+ }
+
+ return EFI_NOT_READY;
+ }
+
+ Link = GetNextNode (ListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Perform NoSubmit check for a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+NoSubmitCheck (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Submit a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+SubmitForm (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ EFI_STRING ConfigResp;
+ EFI_STRING Progress;
+ FORMSET_STORAGE *Storage;
+
+ //
+ // Validate the Form by NoSubmit check
+ //
+ Status = NoSubmitCheck (FormSet, Form);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Submit Buffer storage or Name/Value storage
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ continue;
+ }
+
+ //
+ // Skip if there is no RequestElement
+ //
+ if (Storage->ElementCount == 0) {
+ continue;
+ }
+
+ //
+ // Prepare <ConfigResp>
+ //
+ Status = StorageToConfigResp (Storage, &ConfigResp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Send <ConfigResp> to Configuration Driver
+ //
+ if (FormSet->ConfigAccess != NULL) {
+ Status = FormSet->ConfigAccess->RouteConfig (
+ FormSet->ConfigAccess,
+ ConfigResp,
+ &Progress
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ConfigResp);
+ return Status;
+ }
+ }
+ gBS->FreePool (ConfigResp);
+
+ //
+ // Config success, update storage shadow Buffer
+ //
+ SynchronizeStorage (Storage);
+ }
+
+ gNvUpdateRequired = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset Question to its default value.
+
+ @param FormSet The form set.
+ @param Form The form.
+ @param Question The question.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINT16 DefaultId
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ QUESTION_DEFAULT *Default;
+ QUESTION_OPTION *Option;
+ EFI_HII_VALUE *HiiValue;
+ UINT8 Index;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ return Status;
+ }
+
+ //
+ // There are three ways to specify default value for a Question:
+ // 1, use nested EFI_IFR_DEFAULT (highest priority)
+ // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
+ // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
+ //
+ HiiValue = &Question->HiiValue;
+
+ //
+ // EFI_IFR_DEFAULT has highest priority
+ //
+ if (!IsListEmpty (&Question->DefaultListHead)) {
+ Link = GetFirstNode (&Question->DefaultListHead);
+ while (!IsNull (&Question->DefaultListHead, Link)) {
+ Default = QUESTION_DEFAULT_FROM_LINK (Link);
+
+ if (Default->DefaultId == DefaultId) {
+ if (Default->ValueExpression != NULL) {
+ //
+ // Default is provided by an Expression, evaluate it
+ //
+ Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
+ } else {
+ //
+ // Default value is embedded in EFI_IFR_DEFAULT
+ //
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Question->DefaultListHead, Link);
+ }
+ }
+
+ //
+ // EFI_ONE_OF_OPTION
+ //
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // OneOfOption could only provide Standard and Manufacturing default
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
+ ) {
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ }
+ }
+
+ //
+ // EFI_IFR_CHECKBOX - lowest priority
+ //
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // Checkbox could only provide Standard and Manufacturing default
+ //
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
+ ) {
+ HiiValue->Value.b = TRUE;
+ } else {
+ HiiValue->Value.b = FALSE;
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // For Questions without default
+ //
+ switch (Question->Operand) {
+ case EFI_IFR_NUMERIC_OP:
+ //
+ // Take minimal value as numeric's default value
+ //
+ HiiValue->Value.u64 = Question->Minimum;
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ //
+ // Take first oneof option as oneof's default value
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ if (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+ }
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ //
+ // Take option sequence in IFR as ordered list's default value
+ //
+ Index = 0;
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+
+ Question->BufferValue[Index] = Option->Value.Value.u8;
+
+ Index++;
+ if (Index >= Question->MaxContainers) {
+ break;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ break;
+
+ default:
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Reset Questions in a Form to their default value.
+
+ @param FormSet FormSet data structure.
+ @param Form The Form which to be reset.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+ExtractFormDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT16 DefaultId
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&Form->StatementListHead, Link);
+
+ //
+ // Reset Question to its default value
+ //
+ Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Synchronize Buffer storage's Edit buffer
+ //
+ if ((Question->Storage != NULL) &&
+ (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
+ SetQuestionValue (FormSet, Form, Question, TRUE);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Question's Edit copy from Storage.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LoadFormConfig (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ //
+ // Initialize local copy of Value for each Question
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Fill storage's edit copy with settings requested from Configuration Driver.
+
+ @param FormSet FormSet data structure.
+ @param Storage Buffer Storage.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LoadStorage (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORMSET_STORAGE *Storage
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ EFI_STRING Result;
+ CHAR16 *StrPtr;
+
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ return EFI_SUCCESS;
+ }
+
+ if (FormSet->ConfigAccess == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (Storage->ElementCount == 0) {
+ //
+ // Skip if there is no RequestElement
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Status = FormSet->ConfigAccess->ExtractConfig (
+ FormSet->ConfigAccess,
+ Storage->ConfigRequest,
+ &Progress,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert Result from <ConfigAltResp> to <ConfigResp>
+ //
+ StrPtr = StrStr (Result, L"ALTCFG");
+ if (StrPtr != NULL) {
+ *StrPtr = L'\0';
+ }
+
+ Status = ConfigRespToStorage (Storage, Result);
+ gBS->FreePool (Result);
+ return Status;
+}
+
+
+/**
+ Get current setting of Questions.
+
+ @param FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+InitializeCurrentSetting (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ LIST_ENTRY *Link;
+ FORMSET_STORAGE *Storage;
+ FORM_BROWSER_FORM *Form;
+ EFI_STATUS Status;
+
+ //
+ // Extract default from IFR binary
+ //
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+ Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);
+
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+
+ Status = LoadStorage (FormSet, Storage);
+
+ //
+ // Now Edit Buffer is filled with default values(lower priority) and current
+ // settings(higher priority), sychronize it to shadow Buffer
+ //
+ if (!EFI_ERROR (Status)) {
+ SynchronizeStorage (Storage);
+ }
+
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Fetch the Ifr binary data of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @param BinaryLength The length of the FormSet IFR binary.
+ @param BinaryData The buffer designed to receive the FormSet.
+
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.
+ BufferLength was updated.
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
+ be found with the requested FormId.
+
+**/
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT UINTN *BinaryLength,
+ OUT UINT8 **BinaryData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINTN BufferSize;
+ UINT8 *Package;
+ UINT8 *OpCodeData;
+ UINT32 Offset;
+ UINT32 Offset2;
+ BOOLEAN ReturnDefault;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ OpCodeData = NULL;
+ Package = NULL;
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
+
+ //
+ // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
+ //
+ if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
+ ReturnDefault = TRUE;
+ } else {
+ ReturnDefault = FALSE;
+ }
+
+ //
+ // Get HII PackageList
+ //
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocatePool (BufferSize);
+ ASSERT (HiiPackageList != NULL);
+
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ Offset2 = 0;
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+
+ while (Offset < PackageListLength) {
+ Package = ((UINT8 *) HiiPackageList) + Offset;
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
+ //
+ // Search FormSet in this Form Package
+ //
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset2 < PackageHeader.Length) {
+ OpCodeData = Package + Offset2;
+
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
+ //
+ // Check whether return default FormSet
+ //
+ if (ReturnDefault) {
+ break;
+ }
+
+ //
+ // FormSet GUID is specified, check it
+ //
+ if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+ break;
+ }
+ }
+
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ }
+
+ if (Offset2 < PackageHeader.Length) {
+ //
+ // Target formset found
+ //
+ break;
+ }
+ }
+
+ Offset += PackageHeader.Length;
+ }
+
+ if (Offset >= PackageListLength) {
+ //
+ // Form package not found in this Package List
+ //
+ gBS->FreePool (HiiPackageList);
+ return EFI_NOT_FOUND;
+ }
+
+ if (ReturnDefault && FormSetGuid != NULL) {
+ //
+ // Return the default FormSet GUID
+ //
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ }
+
+ //
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
+ // of the Form Package.
+ //
+ *BinaryLength = PackageHeader.Length - Offset2;
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
+
+ gBS->FreePool (HiiPackageList);
+
+ if (*BinaryData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize the internal data structure of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @param FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.
+
+**/
+EFI_STATUS
+InitializeFormSet (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ UINT16 Index;
+
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FormSet->HiiHandle = Handle;
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
+
+ //
+ // Retrieve ConfigAccess Protocol associated with this HiiPackageList
+ //
+ Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FormSet->DriverHandle = DriverHandle;
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &FormSet->ConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package
+ // list, then there will be no configuration action required
+ //
+ FormSet->ConfigAccess = NULL;
+ }
+
+ //
+ // Parse the IFR binary OpCodes
+ //
+ Status = ParseOpCodes (FormSet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gClassOfVfr = FormSet->SubClass;
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ FrontPageHandle = FormSet->HiiHandle;
+ }
+
+ //
+ // Match GUID to find out the function key setting. If match fail, use the default setting.
+ //
+ for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
+ if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
+ //
+ // Update the function key setting.
+ //
+ gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
+ //
+ // Function key prompt can not be displayed if the function key has been disabled.
+ //
+ if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
+ gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
+ gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
+ gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
+ gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+ }
+ }
+
+ return Status;
+}
|