+++ /dev/null
-/** @file\r
- This file implements functions related to Config Access Protocols installed by\r
- by HII Thunk Modules. These Config access Protocols are used to thunk UEFI Config \r
- Access Callback to Framework HII Callback and EFI Variable Set/Get operations.\r
- \r
-Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "HiiDatabase.h"\r
-#include "UefiIfrParser.h"\r
-\r
-BOOLEAN mHiiPackageListUpdated = FALSE;\r
-\r
-HII_VENDOR_DEVICE_PATH mUefiHiiVendorDevicePath = {\r
- {\r
- {\r
- {\r
- HARDWARE_DEVICE_PATH,\r
- HW_VENDOR_DP,\r
- {\r
- (UINT8) (sizeof (HII_VENDOR_DEVICE_PATH_NODE)),\r
- (UINT8) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE)) >> 8)\r
- }\r
- },\r
- EFI_CALLER_ID_GUID\r
- },\r
- 0,\r
- 0\r
- },\r
- {\r
- END_DEVICE_PATH_TYPE,\r
- END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
- { \r
- (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),\r
- (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)\r
- }\r
- }\r
-};\r
-\r
-CONFIG_ACCESS_PRIVATE gConfigAccessPrivateTempate = {\r
- CONFIG_ACCESS_PRIVATE_SIGNATURE,\r
- {\r
- ThunkExtractConfig,\r
- ThunkRouteConfig,\r
- ThunkCallback\r
- }, //ConfigAccessProtocol\r
- NULL, //FormCallbackProtocol\r
- NULL \r
-};\r
-\r
-/**\r
- Get the first EFI_IFR_VARSTORE from the FormSet. \r
- \r
- @param FormSet The Form Set.\r
- \r
- @retval FORMSET_STORAGE * Return the first EFI_IFR_VARSTORE.\r
- @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.\r
-**/\r
-FORMSET_STORAGE *\r
-GetFirstStorageOfFormSet (\r
- IN CONST FORM_BROWSER_FORMSET * FormSet\r
- ) \r
-{\r
- LIST_ENTRY *StorageList;\r
- FORMSET_STORAGE *Storage;\r
-\r
- StorageList = GetFirstNode (&FormSet->StorageListHead);\r
-\r
- while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
- Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
- return Storage;\r
- }\r
- StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
- }\r
- \r
- return NULL;\r
-}\r
-\r
-/**\r
- Get the FORM_BROWSER_STATEMENT that matches the Question's value.\r
- \r
- @param FormSet The Form Set.\r
- @param QuestionId QuestionId\r
- \r
- @retval FORM_BROWSER_STATEMENT* FORM_BROWSER_STATEMENT that match Question's value.\r
- @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.\r
-**/\r
-FORM_BROWSER_STATEMENT *\r
-GetStorageFromQuestionId (\r
- IN CONST FORM_BROWSER_FORMSET * FormSet,\r
- IN EFI_QUESTION_ID QuestionId\r
- )\r
-{\r
- LIST_ENTRY *FormList;\r
- LIST_ENTRY *StatementList;\r
- FORM_BROWSER_FORM *Form;\r
- FORM_BROWSER_STATEMENT *Statement;\r
-\r
- FormList = GetFirstNode (&FormSet->FormListHead);\r
-\r
- while (!IsNull (&FormSet->FormListHead, FormList)) {\r
- Form = FORM_BROWSER_FORM_FROM_LINK (FormList);\r
-\r
- StatementList = GetFirstNode (&Form->StatementListHead);\r
-\r
- while (!IsNull (&Form->StatementListHead, StatementList)) {\r
- Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);\r
- if ((QuestionId == Statement->QuestionId) && (Statement->Storage != NULL)) {\r
- //\r
- // UEFI Question ID is unique in a FormSet.\r
- //\r
- ASSERT (Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER);\r
- return Statement;\r
- }\r
- StatementList = GetNextNode (&Form->StatementListHead, StatementList);\r
- }\r
-\r
- FormList = GetNextNode (&FormSet->FormListHead, FormList);\r
- }\r
- \r
- return NULL;\r
-}\r
-\r
-/**\r
- Get the EFI_IFR_VARSTORE based the <ConfigHdr> string in a <ConfigRequest>\r
- or a <ConfigResp> string.\r
- \r
- @param FormSet The Form Set.\r
- @param ConfigString The Configuration String which is defined by UEFI HII.\r
- \r
- @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE where the Question's value is stored.\r
- @retval NULL If the Form Set does not have EFI_IFR_VARSTORE with such ID.\r
-**/\r
-FORMSET_STORAGE *\r
-GetStorageFromConfigString (\r
- IN CONST FORM_BROWSER_FORMSET *FormSet,\r
- IN CONST EFI_STRING ConfigString\r
- )\r
-{\r
- LIST_ENTRY *StorageList;\r
- FORMSET_STORAGE *Storage;\r
- CHAR16 *Name;\r
-\r
- if (ConfigString == NULL) {\r
- return NULL;\r
- }\r
-\r
- StorageList = GetFirstNode (&FormSet->StorageListHead);\r
-\r
- while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
- Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
- StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
- if (Storage->Type != EFI_HII_VARSTORE_BUFFER) {\r
- continue;\r
- }\r
-\r
- if ((Storage->VarStoreId == FormSet->DefaultVarStoreId) && (FormSet->OriginalDefaultVarStoreName != NULL)) {\r
- Name = FormSet->OriginalDefaultVarStoreName;\r
- } else {\r
- Name = Storage->Name;\r
- }\r
- \r
- if (HiiIsConfigHdrMatch (ConfigString, &Storage->Guid, Name)) {\r
- return Storage;\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-/**\r
- This function installs a EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered\r
- by a module using Framework HII Protocol Interfaces.\r
-\r
- UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so\r
- that Setup Utility can load the Buffer Storage using this protocol.\r
- \r
- @param Packages The Package List.\r
- @param ThunkContext The Thunk Context.\r
- \r
- @retval EFI_SUCCESS The Config Access Protocol is installed successfully.\r
- @retval EFI_OUT_RESOURCE There is not enough memory.\r
- \r
-**/\r
-EFI_STATUS\r
-InstallDefaultConfigAccessProtocol (\r
- IN CONST EFI_HII_PACKAGES *Packages,\r
- IN OUT HII_THUNK_CONTEXT *ThunkContext\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CONFIG_ACCESS_PRIVATE *ConfigAccessInstance;\r
- HII_VENDOR_DEVICE_PATH *HiiVendorPath;\r
-\r
- ASSERT (ThunkContext->IfrPackageCount != 0);\r
-\r
- ConfigAccessInstance = AllocateCopyPool (\r
- sizeof (CONFIG_ACCESS_PRIVATE), \r
- &gConfigAccessPrivateTempate\r
- );\r
- ASSERT (ConfigAccessInstance != NULL);\r
-\r
- //\r
- // Use memory address as unique ID to distinguish from different device paths\r
- // This function may be called multi times by the framework HII driver.\r
- //\r
- HiiVendorPath = AllocateCopyPool (\r
- sizeof (HII_VENDOR_DEVICE_PATH), \r
- &mUefiHiiVendorDevicePath\r
- );\r
- ASSERT (HiiVendorPath != NULL);\r
-\r
- HiiVendorPath->Node.UniqueId = (UINT64) ((UINTN) HiiVendorPath);\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ThunkContext->UefiHiiDriverHandle,\r
- &gEfiDevicePathProtocolGuid, \r
- HiiVendorPath,\r
- &gEfiHiiConfigAccessProtocolGuid,\r
- &ConfigAccessInstance->ConfigAccessProtocol,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- \r
- ConfigAccessInstance->ThunkContext = ThunkContext;\r
- \r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- This function un-installs the EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered\r
- by a module using Framework HII Protocol Interfaces.\r
-\r
- ASSERT if no Config Access is found for such pakcage list or failed to uninstall the protocol.\r
-\r
- @param ThunkContext The Thunk Context.\r
- \r
-**/\r
-VOID\r
-UninstallDefaultConfigAccessProtocol (\r
- IN HII_THUNK_CONTEXT *ThunkContext\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- HII_VENDOR_DEVICE_PATH *HiiVendorPath;\r
-\r
- Status = gBS->HandleProtocol (\r
- ThunkContext->UefiHiiDriverHandle,\r
- &gEfiHiiConfigAccessProtocolGuid,\r
- (VOID **) &ConfigAccess\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = gBS->HandleProtocol (\r
- ThunkContext->UefiHiiDriverHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &HiiVendorPath\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- ThunkContext->UefiHiiDriverHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- HiiVendorPath,\r
- &gEfiHiiConfigAccessProtocolGuid,\r
- ConfigAccess,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
-}\r
- \r
-\r
-/**\r
- Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
- \r
- @param BufferStorage The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
- @param FwFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.\r
- @param Data The data read.\r
- @param DataSize The size of data.\r
- \r
- @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
- @retval EFI_INVALID_PARAMETER If the EFI_FORM_CALLBACK_PROTOCOL.NvRead return the size information of the data\r
- does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
- **/\r
-EFI_STATUS\r
-CallFormCallBack (\r
- IN FORMSET_STORAGE *BufferStorage,\r
- IN EFI_FORM_CALLBACK_PROTOCOL *FwFormCallBack,\r
- OUT VOID **Data,\r
- OUT UINTN *DataSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- *DataSize = 0;\r
- *Data = NULL;\r
- \r
- Status = FwFormCallBack->NvRead (\r
- FwFormCallBack, \r
- BufferStorage->Name,\r
- &BufferStorage->Guid,\r
- NULL,\r
- DataSize,\r
- *Data\r
- );\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- if (BufferStorage->Size != *DataSize) {\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *Data = AllocateZeroPool (*DataSize);\r
- if (*Data == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = FwFormCallBack->NvRead (\r
- FwFormCallBack, \r
- BufferStorage->Name,\r
- &BufferStorage->Guid,\r
- NULL,\r
- DataSize,\r
- *Data\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Get Service.\r
- \r
- @param BufferStorage The key with all attributes needed to call a UEFI Variable Get Service.\r
- @param Data The data read.\r
- @param DataSize The size of data.\r
-\r
- If the UEFI Variable Get Service return the size information of the data\r
- does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
- then ASSERT.\r
- \r
- @retval EFI_STATUS The status returned by the UEFI Variable Get Service.\r
- @retval EFI_INVALID_PARAMETER If the UEFI Variable Get Service return the size information of the data\r
- does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
- **/\r
-EFI_STATUS\r
-GetUefiVariable (\r
- IN FORMSET_STORAGE *BufferStorage,\r
- OUT VOID **Data,\r
- OUT UINTN *DataSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- *DataSize = 0;\r
- *Data = NULL;\r
- Status = gRT->GetVariable (\r
- BufferStorage->Name,\r
- &BufferStorage->Guid,\r
- NULL,\r
- DataSize,\r
- *Data\r
- );\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
-\r
- if (BufferStorage->Size != *DataSize) {\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *Data = AllocateZeroPool (*DataSize);\r
- if (*Data == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = gRT->GetVariable (\r
- BufferStorage->Name,\r
- &BufferStorage->Guid,\r
- NULL,\r
- DataSize,\r
- *Data\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
- This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig\r
- so that data can be read from the data storage such as UEFI Variable or module's\r
- customized storage exposed by EFI_FRAMEWORK_CALLBACK.\r
-\r
- @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
- @param Request A null-terminated Unicode string in <ConfigRequest> format. Note that this\r
- includes the routing information as well as the configurable name / value pairs. It is\r
- invalid for this string to be in <MultiConfigRequest> format.\r
-\r
- @param Progress On return, points to a character in the Request string. Points to the string's null\r
- terminator if request was successful. Points to the most recent '&' before the first\r
- failing name / value pair (or the beginning of the string if the failure is in the first\r
- name / value pair) if the request was not successful\r
- @param Results A null-terminated Unicode string in <ConfigAltResp> format which has all\r
- values filled in for the names in the Request string. String to be allocated by the called\r
- function.\r
- \r
- @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.\r
- @retval EFI_SUCCESS The setting is retrived successfully.\r
- @retval !EFI_SUCCESS The error returned by UEFI Get Variable or Framework Form Callback Nvread.\r
- **/\r
-EFI_STATUS\r
-EFIAPI\r
-ThunkExtractConfig (\r
- IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
- IN CONST EFI_STRING Request,\r
- OUT EFI_STRING *Progress,\r
- OUT EFI_STRING *Results\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
- FORMSET_STORAGE *BufferStorage;\r
- VOID *Data;\r
- UINTN DataSize;\r
- FORM_BROWSER_FORMSET *FormSetContext;\r
- CHAR16 *VarStoreName;\r
- EFI_STRING ConfigRequestHdr;\r
- EFI_STRING ConfigRequest;\r
- UINTN Size;\r
- BOOLEAN AllocatedRequest;\r
- LIST_ENTRY *StorageList;\r
- EFI_STRING SingleResult;\r
- EFI_STRING FinalResults;\r
- EFI_STRING StrPointer;\r
-\r
- if (Progress == NULL || Results == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- *Progress = Request;\r
-\r
- Status = EFI_SUCCESS;\r
- Data = NULL;\r
- StrPointer = NULL;\r
- SingleResult = NULL;\r
- FinalResults = NULL;\r
- ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
- FormSetContext = ConfigAccess->ThunkContext->FormSet;\r
- if (IsListEmpty (&FormSetContext->StorageListHead)) {\r
- //\r
- // No VarStorage does exist in this form.\r
- //\r
- return EFI_NOT_FOUND;\r
- }\r
- StorageList = GetFirstNode (&FormSetContext->StorageListHead);\r
-\r
- do {\r
- if (Request != NULL) {\r
- BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Request);\r
- if (BufferStorage == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
- } else {\r
- if (IsNull (&FormSetContext->StorageListHead, StorageList)) {\r
- //\r
- // No Storage to be extracted into the results.\r
- //\r
- break;\r
- }\r
- BufferStorage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
- StorageList = GetNextNode (&FormSetContext->StorageListHead, StorageList);\r
- if (BufferStorage->Type != EFI_HII_VARSTORE_BUFFER) {\r
- //\r
- // BufferStorage type should be EFI_HII_VARSTORE_BUFFER\r
- //\r
- continue;\r
- }\r
- }\r
- \r
- VarStoreName = NULL;\r
- ConfigRequestHdr = NULL;\r
- ConfigRequest = NULL;\r
- Size = 0;\r
- AllocatedRequest = FALSE;\r
-\r
- if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
- //\r
- // NvMapOverride is not used. Get the Storage data from EFI Variable or Framework Form Callback.\r
- //\r
- if (ConfigAccess->FormCallbackProtocol == NULL ||\r
- ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
- Status = GetUefiVariable (\r
- BufferStorage,\r
- &Data,\r
- &DataSize\r
- );\r
- } else {\r
- Status = CallFormCallBack (\r
- BufferStorage,\r
- ConfigAccess->FormCallbackProtocol,\r
- &Data,\r
- &DataSize\r
- );\r
- }\r
- } else {\r
- //\r
- // Use the NvMapOverride.\r
- //\r
- DataSize = BufferStorage->Size;\r
- Data = AllocateCopyPool (DataSize, ConfigAccess->ThunkContext->NvMapOverride);\r
- \r
- if (Data != NULL) {\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- }\r
- }\r
- \r
- if (!EFI_ERROR (Status)) {\r
- ConfigRequest = Request;\r
- if (Request == NULL || (StrStr (Request, L"OFFSET") == NULL)) {\r
- //\r
- // Request is without any request element, construct full request string.\r
- //\r
-\r
- if ((BufferStorage->VarStoreId == FormSetContext->DefaultVarStoreId) && (FormSetContext->OriginalDefaultVarStoreName != NULL)) {\r
- VarStoreName = FormSetContext->OriginalDefaultVarStoreName;\r
- } else {\r
- VarStoreName = BufferStorage->Name;\r
- }\r
-\r
- //\r
- // First Set ConfigRequestHdr string.\r
- //\r
- ConfigRequestHdr = HiiConstructConfigHdr (&BufferStorage->Guid, VarStoreName, ConfigAccess->ThunkContext->UefiHiiDriverHandle);\r
- ASSERT (ConfigRequestHdr != NULL);\r
-\r
- //\r
- // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
- // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
- //\r
- Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
- ConfigRequest = AllocateZeroPool (Size);\r
- ASSERT (ConfigRequest != NULL);\r
- AllocatedRequest = TRUE;\r
- UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)DataSize);\r
- FreePool (ConfigRequestHdr);\r
- }\r
- Status = mHiiConfigRoutingProtocol->BlockToConfig (\r
- mHiiConfigRoutingProtocol,\r
- ConfigRequest,\r
- Data,\r
- DataSize,\r
- &SingleResult,\r
- Progress\r
- );\r
- //\r
- // Free the allocated config request string.\r
- //\r
- if (AllocatedRequest) {\r
- FreePool (ConfigRequest);\r
- ConfigRequest = NULL;\r
- }\r
- }\r
- //\r
- // Free the allocated Data\r
- //\r
- if (Data != NULL) {\r
- FreePool (Data);\r
- }\r
- //\r
- // Directly return when meet with error\r
- //\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- //\r
- // Merge result into the final results.\r
- //\r
- if (FinalResults == NULL) {\r
- FinalResults = SingleResult;\r
- SingleResult = NULL;\r
- } else {\r
- Size = StrLen (FinalResults);\r
- Size = Size + 1;\r
- Size = Size + StrLen (SingleResult) + 1;\r
- StrPointer = AllocateZeroPool (Size * sizeof (CHAR16));\r
- ASSERT (StrPointer != NULL);\r
- StrCpy (StrPointer, FinalResults);\r
- FreePool (FinalResults);\r
- FinalResults = StrPointer;\r
- StrPointer = StrPointer + StrLen (StrPointer);\r
- *StrPointer = L'&';\r
- StrCpy (StrPointer + 1, SingleResult);\r
- FreePool (SingleResult);\r
- }\r
- } while (Request == NULL);\r
-\r
- if (!EFI_ERROR (Status)) {\r
- *Results = FinalResults;\r
- } else {\r
- if (FinalResults != NULL) {\r
- FreePool (FinalResults);\r
- }\r
- }\r
- //\r
- // Set Progress string to the original request string.\r
- //\r
- if (Request == NULL) {\r
- *Progress = NULL;\r
- } else if (StrStr (Request, L"OFFSET") == NULL) {\r
- *Progress = Request + StrLen (Request);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig\r
- so that data can be written to the data storage such as UEFI Variable or module's\r
- customized storage exposed by EFI_FRAMEWORK_CALLBACK.\r
- \r
- @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
- @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
- @param Progress A pointer to a string filled in with the offset of the most recent '&' before the first\r
- failing name / value pair (or the beginning of the string if the failure is in the first\r
- name / value pair) or the terminating NULL if all was successful.\r
- \r
- @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.\r
- @retval EFI_SUCCESS The setting is saved successfully.\r
- @retval !EFI_SUCCESS The error returned by UEFI Set Variable or Framework Form Callback Nvwrite.\r
-**/ \r
-EFI_STATUS\r
-EFIAPI\r
-ThunkRouteConfig (\r
- IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
- IN CONST EFI_STRING Configuration,\r
- OUT EFI_STRING *Progress\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
- FORMSET_STORAGE *BufferStorage;\r
- VOID *Data;\r
- UINTN DataSize;\r
- UINTN DataSize2;\r
- BOOLEAN ResetRequired;\r
- BOOLEAN DataAllocated;\r
-\r
- if (Configuration == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Data = NULL;\r
- ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
-\r
- BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Configuration);\r
-\r
- if (BufferStorage == NULL) {\r
- *Progress = Configuration;\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- DataSize2 = BufferStorage->Size;\r
- if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
- DataAllocated = TRUE;\r
- if (ConfigAccess->FormCallbackProtocol == NULL ||\r
- ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
- Status = GetUefiVariable (\r
- BufferStorage,\r
- &Data,\r
- &DataSize\r
- );\r
- } else {\r
- Status = CallFormCallBack (\r
- BufferStorage,\r
- ConfigAccess->FormCallbackProtocol,\r
- &Data,\r
- &DataSize\r
- );\r
- }\r
- } else {\r
- //\r
- // ConfigToBlock will convert the Config String and update the NvMapOverride accordingly.\r
- //\r
- Status = EFI_SUCCESS;\r
- Data = ConfigAccess->ThunkContext->NvMapOverride;\r
- DataSize = DataSize2;\r
- DataAllocated = FALSE;\r
- } \r
- if (EFI_ERROR (Status) || (DataSize2 != DataSize)) {\r
- if (Data == NULL) {\r
- Data = AllocateZeroPool (DataSize2);\r
- }\r
- }\r
-\r
- DataSize = DataSize2;\r
- Status = mHiiConfigRoutingProtocol->ConfigToBlock (\r
- mHiiConfigRoutingProtocol,\r
- Configuration,\r
- Data,\r
- &DataSize,\r
- Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- \r
- if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
- if (ConfigAccess->FormCallbackProtocol == NULL ||\r
- ConfigAccess->FormCallbackProtocol->NvWrite == NULL) {\r
- Status = gRT->SetVariable (\r
- BufferStorage->Name,\r
- &BufferStorage->Guid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- DataSize2,\r
- Data\r
- );\r
- } else {\r
- Status = ConfigAccess->FormCallbackProtocol->NvWrite (\r
- ConfigAccess->FormCallbackProtocol, \r
- BufferStorage->Name,\r
- &BufferStorage->Guid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- DataSize2,\r
- Data,\r
- &ResetRequired\r
- );\r
- }\r
- }\r
-\r
-Done: \r
- if (DataAllocated && (Data != NULL)) {\r
- FreePool (Data);\r
- }\r
- \r
- return Status;\r
-}\r
-\r
-/**\r
- Build the EFI_IFR_DATA_ARRAY which will be used to pass to \r
- EFI_FORM_CALLBACK_PROTOCOL.Callback. Check definition of EFI_IFR_DATA_ARRAY\r
- for details.\r
-\r
- ASSERT if the Question Type is not EFI_IFR_TYPE_NUM_SIZE_* or EFI_IFR_TYPE_STRING.\r
- \r
- @param ConfigAccess Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
- @param QuestionId The Question ID.\r
- @param Type The Question Type.\r
- @param Value The Question Value.\r
- @param NvMapAllocated On output indicates if a buffer is allocated for NvMap.\r
- \r
- @return A pointer to EFI_IFR_DATA_ARRAY. The caller must free this buffer allocated.\r
-**/ \r
-EFI_IFR_DATA_ARRAY *\r
-CreateIfrDataArray (\r
- IN CONFIG_ACCESS_PRIVATE *ConfigAccess,\r
- IN EFI_QUESTION_ID QuestionId,\r
- IN UINT8 Type,\r
- IN EFI_IFR_TYPE_VALUE *Value,\r
- OUT BOOLEAN *NvMapAllocated\r
- )\r
-{\r
- EFI_IFR_DATA_ARRAY *IfrDataArray;\r
- EFI_IFR_DATA_ENTRY *IfrDataEntry;\r
- UINTN BrowserDataSize;\r
- FORMSET_STORAGE *BufferStorage;\r
- UINTN Size;\r
- EFI_STRING String;\r
- FORM_BROWSER_STATEMENT *Statement;\r
-\r
- *NvMapAllocated = FALSE;\r
-\r
- String = NULL;\r
-\r
- switch (Type) {\r
- case EFI_IFR_TYPE_NUM_SIZE_8:\r
- case EFI_IFR_TYPE_NUM_SIZE_16:\r
- case EFI_IFR_TYPE_NUM_SIZE_32:\r
- case EFI_IFR_TYPE_NUM_SIZE_64:\r
- case EFI_IFR_TYPE_BOOLEAN:\r
- Size = sizeof (*Value);\r
- break;\r
-\r
- case EFI_IFR_TYPE_STRING:\r
- if (Value->string == 0) {\r
- Size = 0;\r
- } else {\r
- String = HiiGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, NULL);\r
- ASSERT (String != NULL);\r
-\r
- Size = StrSize (String);\r
- }\r
- break;\r
-\r
- case EFI_IFR_TYPE_ACTION:\r
- case EFI_IFR_TYPE_UNDEFINED:\r
- Size = 0;\r
- break;\r
- \r
- default:\r
- ASSERT (FALSE);\r
- Size = 0;\r
- break;\r
- }\r
-\r
- IfrDataArray = AllocateZeroPool (sizeof (EFI_IFR_DATA_ARRAY) + sizeof (EFI_IFR_DATA_ENTRY) + Size);\r
- ASSERT (IfrDataArray != NULL);\r
- IfrDataArray->EntryCount = 1;\r
- IfrDataEntry = (EFI_IFR_DATA_ENTRY *) (IfrDataArray + 1);\r
-\r
- Statement = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
-\r
- if (Statement == NULL || Statement->Storage == NULL) {\r
- //\r
- // The QuestionId is not associated with a Buffer Storage.\r
- // Try to get the first Buffer Storage then.\r
- //\r
- BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);\r
- } else {\r
- BufferStorage = Statement->Storage;\r
- IfrDataEntry->OpCode = Statement->Operand;\r
- }\r
- \r
- if (BufferStorage != NULL) {\r
- BrowserDataSize = BufferStorage->Size;\r
- IfrDataEntry->Length = (UINT8) (sizeof (EFI_IFR_DATA_ENTRY) + Size);\r
-\r
- if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
- *NvMapAllocated = TRUE;\r
- IfrDataArray->NvRamMap = AllocateZeroPool (BrowserDataSize);\r
- } else {\r
- *NvMapAllocated = FALSE;\r
- IfrDataArray->NvRamMap = ConfigAccess->ThunkContext->NvMapOverride;\r
- }\r
- \r
- ASSERT (HiiGetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, (UINT8 *) IfrDataArray->NvRamMap));\r
-\r
- switch (Type) {\r
- case EFI_IFR_TYPE_NUM_SIZE_8:\r
- case EFI_IFR_TYPE_NUM_SIZE_16:\r
- case EFI_IFR_TYPE_NUM_SIZE_32:\r
- case EFI_IFR_TYPE_NUM_SIZE_64:\r
- case EFI_IFR_TYPE_BOOLEAN:\r
- CopyMem (&IfrDataEntry->Data, &(Value->u8), sizeof (*Value));\r
- break;\r
-\r
- case EFI_IFR_TYPE_STRING:\r
- if (Size != 0) {\r
- ASSERT (String != NULL);\r
- StrCpy ((CHAR16 *) &IfrDataEntry->Data, String);\r
- FreePool (String);\r
- }\r
- break;\r
-\r
- case EFI_IFR_TYPE_ACTION:\r
- case EFI_IFR_TYPE_UNDEFINED:\r
- break;\r
-\r
- default:\r
- ASSERT (FALSE);\r
- break;\r
- }\r
-\r
- //\r
- // Need to fiil in the information for the rest of field for EFI_IFR_DATA_ENTRY.\r
- // It seems that no implementation is found to use other fields. Leave them uninitialized for now.\r
- //\r
- //UINT8 OpCode; // Likely a string, numeric, or one-of\r
- //UINT8 Length; // Length of the EFI_IFR_DATA_ENTRY packet\r
- //UINT16 Flags; // Flags settings to determine what behavior is desired from the browser after the callback\r
- //VOID *Data; // The data in the form based on the op-code type - this is not a pointer to the data, the data follows immediately\r
- // If the OpCode is a OneOf or Numeric type - Data is a UINT16 value\r
- // If the OpCode is a String type - Data is a CHAR16[x] type\r
- // If the OpCode is a Checkbox type - Data is a UINT8 value\r
- // If the OpCode is a NV Access type - Data is a FRAMEWORK_EFI_IFR_NV_DATA structure\r
- }\r
-\r
- return IfrDataArray;\r
-}\r
-\r
-/**\r
- If a NvMapOverride is passed in to EFI_FORM_BROWSER_PROTOCOL.SendForm, the Form Browser\r
- needs to be informed when data changed in NvMapOverride. This function will invoke\r
- SetBrowserData () to set internal data of Form Browser.\r
-\r
- @param ConfigAccess The Config Access Private Context.\r
- @param QuestionId The Question Id that invokes the callback.\r
- \r
-\r
-**/\r
-VOID\r
-SyncBrowserDataForNvMapOverride (\r
- IN CONST CONFIG_ACCESS_PRIVATE *ConfigAccess,\r
- IN EFI_QUESTION_ID QuestionId\r
- )\r
-{\r
- FORMSET_STORAGE *BufferStorage;\r
- BOOLEAN CheckFlag;\r
- UINTN BrowserDataSize;\r
- FORM_BROWSER_STATEMENT *Statement;\r
-\r
- if (ConfigAccess->ThunkContext->NvMapOverride != NULL) {\r
-\r
- Statement = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
-\r
- if (Statement == NULL || Statement->Storage == NULL) {\r
- //\r
- // QuestionId is a statement without Storage.\r
- // 1) It is a Goto. \r
- // \r
- //\r
- BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);\r
- } else {\r
- BufferStorage = Statement->Storage;\r
- }\r
-\r
- //\r
- // If NvMapOverride is not NULL, this Form must have at least one Buffer Type Variable Storage.\r
- //\r
- ASSERT (BufferStorage != NULL);\r
- \r
- BrowserDataSize = BufferStorage->Size;\r
-\r
- CheckFlag = HiiSetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, ConfigAccess->ThunkContext->NvMapOverride, NULL);\r
- ASSERT (CheckFlag);\r
- }\r
-\r
-}\r
-\r
-/**\r
- Free up resource allocated for a EFI_IFR_DATA_ARRAY by CreateIfrDataArray ().\r
-\r
- @param Array The EFI_IFR_DATA_ARRAY allocated.\r
- @param NvMapAllocated If the NvRamMap is allocated for EFI_IFR_DATA_ARRAY.\r
-\r
-**/\r
-VOID\r
-DestroyIfrDataArray (\r
- IN EFI_IFR_DATA_ARRAY *Array,\r
- IN BOOLEAN NvMapAllocated\r
- )\r
-{\r
- if (Array != NULL) {\r
- if (NvMapAllocated) {\r
- FreePool (Array->NvRamMap);\r
- }\r
-\r
- FreePool (Array);\r
- }\r
-}\r
-\r
-/**\r
- Get the ONE_OF_OPTION_MAP_ENTRY for a QuestionId that invokes the \r
- EFI_FORM_CALLBACK_PROTOCOL.Callback. The information is needed as\r
- the callback mechanism for EFI_IFR_ONE_OF_OPTION is changed from \r
- EFI_IFR_ONE_OF_OPTION in Framework IFR. Check EFI_IFR_GUID_OPTIONKEY\r
- for detailed information.\r
-\r
- @param ThunkContext The Thunk Context.\r
- @param QuestionId The Question Id.\r
- @param Type The Question Type.\r
- @param Value The One Of Option's value.\r
-\r
- @return The ONE_OF_OPTION_MAP_ENTRY found.\r
- @retval NULL If no entry is found.\r
-**/\r
-ONE_OF_OPTION_MAP_ENTRY *\r
-GetOneOfOptionMapEntry (\r
- IN HII_THUNK_CONTEXT *ThunkContext,\r
- IN EFI_QUESTION_ID QuestionId,\r
- IN UINT8 Type,\r
- IN EFI_IFR_TYPE_VALUE *Value\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *Link2;\r
- ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
- ONE_OF_OPTION_MAP *OneOfOptionMap;\r
- FORM_BROWSER_FORMSET *FormSet;\r
-\r
- FormSet = ThunkContext->FormSet;\r
-\r
- Link = GetFirstNode (&FormSet->OneOfOptionMapListHead);\r
-\r
- while (!IsNull (&FormSet->OneOfOptionMapListHead, Link)) {\r
- OneOfOptionMap = ONE_OF_OPTION_MAP_FROM_LINK(Link);\r
- if (OneOfOptionMap->QuestionId == QuestionId) {\r
- ASSERT (OneOfOptionMap->ValueType == Type);\r
-\r
- Link2 = GetFirstNode (&OneOfOptionMap->OneOfOptionMapEntryListHead);\r
-\r
- while (!IsNull (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2)) {\r
- OneOfOptionMapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);\r
-\r
- if (CompareMem (Value, &OneOfOptionMapEntry->Value, sizeof (EFI_IFR_TYPE_VALUE)) == 0) {\r
- return OneOfOptionMapEntry;\r
- }\r
-\r
- Link2 = GetNextNode (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2);\r
- }\r
- }\r
-\r
- Link = GetNextNode (&FormSet->OneOfOptionMapListHead, Link);\r
- }\r
-\r
-\r
- return NULL;\r
-}\r
-\r
-/**\r
- Functions which are registered to receive notification of\r
- database events have this prototype. The actual event is encoded\r
- in NotifyType. The following table describes how PackageType,\r
- PackageGuid, Handle, and Package are used for each of the\r
- notification types.\r
-\r
- If any Pakcage List in database is updated, mHiiPackageListUpdated\r
- will be set. If mHiiPackageListUpdated is set, Framework ThunkCallback()\r
- will force the UEFI Setup Browser to save the uncommitted data. This\r
- is needed as Framework's Callback function may dynamically update\r
- opcode in a Package List. UEFI Setup Browser will quit itself and reparse\r
- the Package List's IFR and display it. UEFI Config Access's implementation\r
- is required to save the modified (SetBrowserData or directly save the data\r
- to NV storage). But Framework HII Modules is not aware of this rule. Therefore,\r
- we will enforce the rule in ThunkCallback (). The side effect of force saving\r
- of NV data is the NV flag in browser may not flag a update as data has already\r
- been saved to NV storage.\r
-\r
- @param PackageType Package type of the notification.\r
-\r
- @param PackageGuid If PackageType is\r
- EFI_HII_PACKAGE_TYPE_GUID, then this is\r
- the pointer to the GUID from the Guid\r
- field of EFI_HII_PACKAGE_GUID_HEADER.\r
- Otherwise, it must be NULL.\r
-\r
- @param Package Points to the package referred to by the\r
- notification Handle The handle of the package\r
- list which contains the specified package.\r
-\r
- @param Handle The HII handle.\r
-\r
- @param NotifyType The type of change concerning the\r
- database. See\r
- EFI_HII_DATABASE_NOTIFY_TYPE.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FormUpdateNotify (\r
- IN UINT8 PackageType,\r
- IN CONST EFI_GUID *PackageGuid,\r
- IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
- IN EFI_HII_HANDLE Handle,\r
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
- )\r
-{\r
- mHiiPackageListUpdated = TRUE;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.CallBack to EFI_FORM_CALLBACK_PROTOCOL.Callback. Therefor,\r
- the framework HII module willl do no porting and work with a UEFI HII SetupBrowser.\r
- \r
- @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
- @param Action Specifies the type of action taken by the browser. See EFI_BROWSER_ACTION_x.\r
- @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the\r
- type of data to expect. The format of the data tends to vary based on the opcode that\r
- generated the callback.\r
- @param Type The type of value for the question. See EFI_IFR_TYPE_x in\r
- EFI_IFR_ONE_OF_OPTION.\r
- @param Value A pointer to the data being sent to the original exporting driver. The type is specified\r
- by Type. Type EFI_IFR_TYPE_VALUE is defined in\r
- EFI_IFR_ONE_OF_OPTION.\r
- @param ActionRequest On return, points to the action requested by the callback function. Type\r
- EFI_BROWSER_ACTION_REQUEST is specified in SendForm() in the Form\r
- Browser Protocol.\r
- \r
- @retval EFI_UNSUPPORTED If the Framework HII module does not register Callback although it specify the opcode under\r
- focuse to be INTERRACTIVE.\r
- @retval EFI_SUCCESS The callback complete successfully.\r
- @retval !EFI_SUCCESS The error code returned by EFI_FORM_CALLBACK_PROTOCOL.Callback.\r
- \r
- **/\r
-EFI_STATUS\r
-EFIAPI\r
-ThunkCallback (\r
- IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
- IN EFI_BROWSER_ACTION Action,\r
- IN EFI_QUESTION_ID QuestionId,\r
- IN UINT8 Type,\r
- IN EFI_IFR_TYPE_VALUE *Value,\r
- OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
- EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;\r
- EFI_HII_CALLBACK_PACKET *Packet;\r
- EFI_IFR_DATA_ARRAY *Data;\r
- EFI_IFR_DATA_ENTRY *DataEntry;\r
- UINT16 KeyValue;\r
- ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
- EFI_HANDLE NotifyHandle;\r
- EFI_INPUT_KEY Key; \r
- BOOLEAN NvMapAllocated;\r
-\r
- if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
- ASSERT (This != NULL);\r
- ASSERT (Value != NULL);\r
- ASSERT (ActionRequest != NULL);\r
-\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-\r
- ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
-\r
- FormCallbackProtocol = ConfigAccess->FormCallbackProtocol;\r
- if (FormCallbackProtocol == NULL) {\r
- ASSERT (FALSE);\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Check if the QuestionId match a OneOfOption.\r
- //\r
- OneOfOptionMapEntry = GetOneOfOptionMapEntry (ConfigAccess->ThunkContext, QuestionId, Type, Value);\r
-\r
- if (OneOfOptionMapEntry == NULL) {\r
- //\r
- // This is not a One-Of-Option opcode. QuestionId is the KeyValue\r
- //\r
- KeyValue = QuestionId;\r
- } else {\r
- //\r
- // Otherwise, use the original Key specified in One Of Option in the Framework VFR syntax.\r
- //\r
- KeyValue = OneOfOptionMapEntry->FwKey;\r
- }\r
-\r
- //\r
- // Build the EFI_IFR_DATA_ARRAY\r
- //\r
- Data = CreateIfrDataArray (ConfigAccess, QuestionId, Type, Value, &NvMapAllocated);\r
-\r
- Status = mHiiDatabase->RegisterPackageNotify (\r
- mHiiDatabase,\r
- EFI_HII_PACKAGE_FORMS,\r
- NULL,\r
- FormUpdateNotify,\r
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
- &NotifyHandle\r
- );\r
- //\r
- //Call the Framework Callback function.\r
- //\r
- Packet = NULL;\r
- Status = FormCallbackProtocol->Callback (\r
- FormCallbackProtocol,\r
- KeyValue,\r
- Data,\r
- &Packet\r
- );\r
- SyncBrowserDataForNvMapOverride (ConfigAccess, QuestionId);\r
-\r
- //\r
- // Callback require browser to perform action\r
- //\r
- if (EFI_ERROR (Status)) {\r
- if (Packet != NULL) {\r
- do {\r
- CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, Packet->String, NULL);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- }\r
- //\r
- // Error Code in Status is discarded.\r
- //\r
- } else {\r
- if (Packet != NULL) {\r
- if (Packet->DataArray.EntryCount == 1 && Packet->DataArray.NvRamMap == NULL) {\r
- DataEntry = (EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (EFI_IFR_DATA_ARRAY));\r
- if ((DataEntry->Flags & EXIT_REQUIRED) == EXIT_REQUIRED) {\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
- }\r
-\r
- if ((DataEntry->Flags & SAVE_REQUIRED) == SAVE_REQUIRED) {\r
- Status = ConfigAccess->ConfigAccessProtocol.RouteConfig (\r
- &ConfigAccess->ConfigAccessProtocol,\r
- NULL,\r
- NULL\r
- );\r
- }\r
- }\r
- FreePool (Packet);\r
- }\r
- }\r
-\r
- //\r
- // Unregister notify for Form package update\r
- //\r
- Status = mHiiDatabase->UnregisterPackageNotify (\r
- mHiiDatabase,\r
- NotifyHandle\r
- );\r
- //\r
- // UEFI SetupBrowser behaves differently with Framework SetupBrowser when call back function \r
- // update any forms in HII database. UEFI SetupBrowser will re-parse the displaying form package and load\r
- // the values from variable storages. Framework SetupBrowser will only re-parse the displaying form packages.\r
- // To make sure customer's previous changes is saved and the changing question behaves as expected, we\r
- // issue a EFI_BROWSER_ACTION_REQUEST_SUBMIT to ask UEFI SetupBrowser to save the changes proceed to re-parse\r
- // the form and load all the variable storages.\r
- //\r
- if (*ActionRequest == EFI_BROWSER_ACTION_REQUEST_NONE && mHiiPackageListUpdated) {\r
- mHiiPackageListUpdated= FALSE;\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
- } else {\r
- if (ConfigAccess->ThunkContext->FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS ||\r
- ConfigAccess->ThunkContext->FormSet->SubClass == EFI_SINGLE_USE_SUBCLASS) {\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
- }\r
- }\r
-\r
- //\r
- // Clean up.\r
- //\r
- DestroyIfrDataArray (Data, NvMapAllocated);\r
-\r
- return Status;\r
- }\r
-\r
- //\r
- // All other action return unsupported.\r
- //\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r