]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/ConfigAccess.c
Bug fixes for FrameworkHiiToUefiHiiThunk;
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / ConfigAccess.c
index bac07de530819a2dfd6b73f8710e6524e299faad..88565d128ca8eac685379062e191ec6bd6b6e891 100644 (file)
@@ -16,15 +16,18 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "HiiDatabase.h"\r
 \r
-HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE ConfigAccessProtocolInstanceTempate = {\r
-  HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_SIGNATURE,\r
+BOOLEAN            mHiiPackageListUpdated;\r
+\r
+CONFIG_ACCESS_PRIVATE gConfigAccessPrivateTempate = {\r
+  CONFIG_ACCESS_PRIVATE_SIGNATURE,\r
   {\r
     ThunkExtractConfig,\r
     ThunkRouteConfig,\r
     ThunkCallback\r
   }, //ConfigAccessProtocol\r
-  NULL, //FrameworkFormCallbackProtocol\r
-  {NULL, NULL} //ConfigAccessStorageListHead\r
+  NULL, //FormCallbackProtocol\r
+  {NULL, NULL}, //ConfigAccessStorageListHead\r
+  NULL \r
 };\r
 \r
 /**\r
@@ -40,11 +43,10 @@ HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE ConfigAccessProtocolInstanceTempate =
    Framework Module which does not include packages introduced by UEFI Specification\r
    or packages that is not supported by Thunk layer.\r
     \r
-   @param Packages    The Framework Package List\r
+   @param Packages                  The Framework Package List\r
    \r
-   @retval EFI_HII_PACKAGE_HEADER* Return the Package Header of\r
-                                                          Form Package.\r
-   @retval NULL                                    If no Form Package is found.\r
+   @retval EFI_HII_PACKAGE_HEADER* Return the Package Header of Form Package.\r
+   @retval NULL                    If no Form Package is found.\r
 **/\r
 EFI_HII_PACKAGE_HEADER *\r
 GetIfrFormSet (\r
@@ -100,11 +102,10 @@ GetIfrFormSet (
   If FormSetPackage is not EFI_HII_PACKAGE_FORM, then ASSERT.\r
   If there is no linear buffer storage in this formset, then ASSERT.\r
 \r
-   @param FormSetPackage            The Form Package header.\r
+   @param FormSetPackage           The Form Package header.\r
    @param BufferStorageListHead    The link list for the VARSTORE found in the form package.\r
    \r
-   @retval  EFI_SUCCESS                     The function scan the form set and find one or more \r
-                                                          VARSTOREs.\r
+   @retval  EFI_SUCCESS            The function scan the form set and find one or more VARSTOREs.\r
    @retval  EFI_OUT_OF_RESOURCES    There is not enough memory to complete the function.\r
 **/\r
 EFI_STATUS\r
@@ -118,11 +119,15 @@ GetBufferStorage  (
   UINT8                   *OpCodeData;\r
   UINT8                   Operand;\r
   EFI_IFR_VARSTORE        *VarStoreOpCode;\r
-  HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
+  BUFFER_STORAGE_ENTRY *BufferStorage;\r
 \r
   ASSERT (FormSetPackage->Type == EFI_HII_PACKAGE_FORM);\r
 \r
   OpCodeOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+  //\r
+  // Scan all opcode for the FormSet Package for \r
+  // EFI_IFR_VARSTORE_OP opcode.\r
+  //\r
   while (OpCodeOffset < FormSetPackage->Length) {\r
     OpCodeData = (UINT8 *) FormSetPackage + OpCodeOffset;\r
 \r
@@ -132,27 +137,31 @@ GetBufferStorage  (
 \r
     if (Operand == EFI_IFR_VARSTORE_OP) {\r
       VarStoreOpCode = (EFI_IFR_VARSTORE *)OpCodeData;\r
-      BufferStorageKey = AllocateZeroPool (sizeof (*BufferStorageKey));\r
-      if (BufferStorageKey == NULL) {\r
+      BufferStorage = AllocateZeroPool (sizeof (*BufferStorage));\r
+      if (BufferStorage == NULL) {\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
-      CopyMem (&BufferStorageKey->Guid, &VarStoreOpCode->Guid, sizeof (EFI_GUID));\r
+      //\r
+      // Record the attributes: GUID, Name, VarStoreId and Size.\r
+      //\r
+      CopyMem (&BufferStorage->Guid, &VarStoreOpCode->Guid, sizeof (EFI_GUID));\r
       \r
-      BufferStorageKey->Name = AllocateZeroPool (AsciiStrSize (VarStoreOpCode->Name) * 2);\r
-      AsciiStrToUnicodeStr (VarStoreOpCode->Name, BufferStorageKey->Name);\r
+      BufferStorage->Name = AllocateZeroPool (AsciiStrSize (VarStoreOpCode->Name) * 2);\r
+      AsciiStrToUnicodeStr (VarStoreOpCode->Name, BufferStorage->Name);\r
 \r
-      BufferStorageKey->VarStoreId = VarStoreOpCode->VarStoreId;\r
+      BufferStorage->VarStoreId = VarStoreOpCode->VarStoreId;\r
 \r
-      BufferStorageKey->Size = VarStoreOpCode->Size;\r
-      BufferStorageKey->Signature = HII_TRHUNK_BUFFER_STORAGE_KEY_SIGNATURE;\r
+      BufferStorage->Size = VarStoreOpCode->Size;\r
+      BufferStorage->Signature = BUFFER_STORAGE_ENTRY_SIGNATURE;\r
 \r
-      InsertTailList (BufferStorageListHead, &BufferStorageKey->List);\r
+      InsertTailList (BufferStorageListHead, &BufferStorage->Link);\r
     }\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
-  \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
@@ -160,30 +169,31 @@ GetBufferStorage  (
    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 framework package list.\r
-   @param MapEntry          The Thunk Layer Handle Mapping Database Entry.\r
+   @param Packages             The framework package list.\r
+   @param ThunkContext             The Thunk Layer Handle Mapping Database Entry.\r
    \r
-   @retval  EFI_SUCCESS             The Config Access Protocol is installed successfully.\r
-   @retval  EFI_OUT_RESOURCE    There is not enough memory.\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
-InstallDefaultUefiConfigAccessProtocol (\r
-  IN  CONST EFI_HII_PACKAGES                         *Packages,\r
-  IN  OUT   HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *MapEntry\r
+InstallDefaultConfigAccessProtocol (\r
+  IN  CONST EFI_HII_PACKAGES                    *Packages,\r
+  IN  OUT   HII_THUNK_CONTEXT                   *ThunkContext\r
   )\r
 {\r
   EFI_HII_PACKAGE_HEADER                      *FormSetPackage;\r
   EFI_STATUS                                  Status;\r
-  HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE  *ConfigAccessInstance;\r
+  CONFIG_ACCESS_PRIVATE                       *ConfigAccessInstance;\r
 \r
-  Status = HiiLibCreateHiiDriverHandle (&MapEntry->UefiHiiDriverHandle);\r
+  Status = HiiLibCreateHiiDriverHandle (&ThunkContext->UefiHiiDriverHandle);\r
   ConfigAccessInstance = AllocateCopyPool (\r
-                           sizeof (HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE), \r
-                           &ConfigAccessProtocolInstanceTempate\r
+                           sizeof (CONFIG_ACCESS_PRIVATE), \r
+                           &gConfigAccessPrivateTempate\r
                            );\r
   ASSERT (ConfigAccessInstance != NULL);\r
-  InitializeListHead (&ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
+  \r
+  InitializeListHead (&ConfigAccessInstance->BufferStorageListHead);\r
 \r
   //\r
   // We assume there is only one formset package in each Forms Package\r
@@ -191,7 +201,7 @@ InstallDefaultUefiConfigAccessProtocol (
   FormSetPackage = GetIfrFormSet (Packages);\r
   ASSERT (FormSetPackage != NULL);\r
   \r
-  Status = GetBufferStorage (FormSetPackage, &ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
+  Status = GetBufferStorage (FormSetPackage, &ConfigAccessInstance->BufferStorageListHead);\r
   if (EFI_ERROR (Status)) {\r
     FreePool (ConfigAccessInstance);\r
     ASSERT (FALSE);\r
@@ -199,70 +209,95 @@ InstallDefaultUefiConfigAccessProtocol (
   }\r
 \r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
-          &MapEntry->UefiHiiDriverHandle,\r
+          &ThunkContext->UefiHiiDriverHandle,\r
           &gEfiHiiConfigAccessProtocolGuid,\r
           &ConfigAccessInstance->ConfigAccessProtocol,\r
           NULL\r
           );\r
+  //\r
+  //BUGBUG: Remove when done.\r
+  //\r
   ASSERT_EFI_ERROR (Status);\r
+  \r
   if (EFI_ERROR (Status)) {\r
     FreePool  (ConfigAccessInstance);\r
     return Status;\r
   }\r
+\r
+  ConfigAccessInstance->ThunkContext = ThunkContext;\r
   \r
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
+VOID\r
+DestroyBufferStorageList (\r
+  IN      LIST_ENTRY  *ListHead\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  BUFFER_STORAGE_ENTRY    *Entry;\r
 \r
-   Wrap EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
-   \r
-   @param BufferStorageKey               The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
-   @param FrameworkFormCallBack     The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.\r
-   @param Data                                  The data to be saved.\r
-   @param DataSize                            The size of data.\r
-   \r
-   @retval EFI_STATUS                       The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
- **/\r
-EFI_STATUS\r
-RouteConfigToFrameworkFormCallBack (\r
-  IN       HII_TRHUNK_BUFFER_STORAGE_KEY              *BufferStorageKey,\r
-  IN       EFI_FORM_CALLBACK_PROTOCOL                 *FrameworkFormCallBack,\r
-  IN       VOID                                       *Data,\r
-  IN       UINTN                                      DataSize\r
+  while (!IsListEmpty (ListHead)) {\r
+    Link = GetFirstNode (ListHead);\r
+    \r
+    Entry = BUFFER_STORAGE_ENTRY_FROM_LINK(Link);\r
+\r
+    FreePool (Entry->Name);\r
+    Link = RemoveEntryList (Link);\r
+\r
+    FreePool (Entry);\r
+  }\r
+}\r
+\r
+VOID\r
+UninstallDefaultConfigAccessProtocol (\r
+  IN  HII_THUNK_CONTEXT                   *ThunkContext\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  BOOLEAN             ResetRequired;\r
+  EFI_STATUS                      Status;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+  CONFIG_ACCESS_PRIVATE           *ConfigAccessInstance;\r
+  \r
+  HiiLibDestroyHiiDriverHandle (ThunkContext->UefiHiiDriverHandle);\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  ThunkContext->UefiHiiDriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  (VOID **) &ConfigAccess\r
+                  );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->UninstallProtocolInterface (\r
+                  ThunkContext->UefiHiiDriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  ConfigAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ConfigAccessInstance = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (ConfigAccess);\r
+\r
+  DestroyBufferStorageList (&ConfigAccessInstance->BufferStorageListHead);\r
 \r
-  Status = FrameworkFormCallBack->NvWrite (\r
-              FrameworkFormCallBack,  \r
-              BufferStorageKey->Name,\r
-              &BufferStorageKey->Guid,\r
-              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
-              DataSize,\r
-              Data,\r
-              &ResetRequired\r
-              );\r
-  return Status;\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 BufferStorageKey               The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
-   @param FrameworkFormCallBack     The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.\r
-   @param Data                                  The data read.\r
-   @param DataSize                            The size of data.\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_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 HII_TRHUNK_BUFFER_STORAGE_KEY.\r
+                                   does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
  **/\r
 EFI_STATUS\r
-ExtractConfigFromFrameworkFormCallBack (\r
-  IN       HII_TRHUNK_BUFFER_STORAGE_KEY              *BufferStorageKey,\r
-  IN       EFI_FORM_CALLBACK_PROTOCOL                 *FrameworkFormCallBack,\r
+CallFormCallBack (\r
+  IN       BUFFER_STORAGE_ENTRY              *BufferStorage,\r
+  IN       EFI_FORM_CALLBACK_PROTOCOL                 *FwFormCallBack,\r
   OUT      VOID                                       **Data,\r
   OUT      UINTN                                      *DataSize\r
   )\r
@@ -272,16 +307,16 @@ ExtractConfigFromFrameworkFormCallBack (
   *DataSize = 0;\r
   *Data     = NULL;\r
   \r
-  Status = FrameworkFormCallBack->NvRead (\r
-              FrameworkFormCallBack,  \r
-              BufferStorageKey->Name,\r
-              &BufferStorageKey->Guid,\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 (BufferStorageKey->Size != *DataSize) {\r
+    if (BufferStorage->Size != *DataSize) {\r
       ASSERT (FALSE);\r
       return EFI_INVALID_PARAMETER;\r
     }\r
@@ -291,10 +326,10 @@ ExtractConfigFromFrameworkFormCallBack (
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    FrameworkFormCallBack->NvRead (\r
-                  FrameworkFormCallBack,  \r
-                  BufferStorageKey->Name,\r
-                  &BufferStorageKey->Guid,\r
+    FwFormCallBack->NvRead (\r
+                  FwFormCallBack,  \r
+                  BufferStorage->Name,\r
+                  &BufferStorage->Guid,\r
                   NULL,\r
                   DataSize,\r
                   *Data\r
@@ -304,52 +339,26 @@ ExtractConfigFromFrameworkFormCallBack (
   return Status;\r
 }\r
 \r
-/**\r
-   Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Set Service.\r
-   \r
-   @param BufferStorageKey               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
-   @retval EFI_STATUS                       The status returned by the UEFI Variable Set Service.\r
-   \r
- **/\r
-EFI_STATUS\r
-RouteConfigToUefiVariable (\r
-  IN       HII_TRHUNK_BUFFER_STORAGE_KEY              *BufferStorageKey,\r
-  IN       VOID                                       *Data,\r
-  IN       UINTN                                      DataSize\r
-  )\r
-{\r
-  return gRT->SetVariable (\r
-                  BufferStorageKey->Name,\r
-                  &BufferStorageKey->Guid,\r
-                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
-                  DataSize,\r
-                  Data\r
-                  );\r
-  \r
-}\r
 \r
 /**\r
    Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Get Service.\r
    \r
-   @param BufferStorageKey               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
+   @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 HII_TRHUNK_BUFFER_STORAGE_KEY.\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_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 HII_TRHUNK_BUFFER_STORAGE_KEY.\r
+                                   does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
  **/\r
 \r
 EFI_STATUS\r
-ExtractConfigFromUefiVariable (\r
-  IN       HII_TRHUNK_BUFFER_STORAGE_KEY              *BufferStorageKey,\r
+GetUefiVariable (\r
+  IN       BUFFER_STORAGE_ENTRY              *BufferStorage,\r
   OUT      VOID                                       **Data,\r
   OUT      UINTN                                      *DataSize\r
   )\r
@@ -359,15 +368,15 @@ ExtractConfigFromUefiVariable (
   *DataSize = 0;\r
   *Data = NULL;\r
   Status = gRT->GetVariable (\r
-              BufferStorageKey->Name,\r
-              &BufferStorageKey->Guid,\r
+              BufferStorage->Name,\r
+              &BufferStorage->Guid,\r
               NULL,\r
               DataSize,\r
               *Data\r
               );\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
 \r
-    if (BufferStorageKey->Size != *DataSize) {\r
+    if (BufferStorage->Size != *DataSize) {\r
       ASSERT (FALSE);\r
       return EFI_INVALID_PARAMETER;\r
     }\r
@@ -378,8 +387,8 @@ ExtractConfigFromUefiVariable (
     }\r
 \r
     Status = gRT->GetVariable (\r
-                BufferStorageKey->Name,\r
-                &BufferStorageKey->Guid,\r
+                BufferStorage->Name,\r
+                &BufferStorage->Guid,\r
                 NULL,\r
                 DataSize,\r
                 *Data\r
@@ -395,22 +404,22 @@ ExtractConfigFromUefiVariable (
   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 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
+                      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 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
+                      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
+   @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
@@ -422,37 +431,37 @@ ThunkExtractConfig (
   )\r
 {\r
   EFI_STATUS                                  Status;\r
-  HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE  *ConfigaAccessInstance;\r
-  LIST_ENTRY                                  *ListEntry;\r
-  HII_TRHUNK_BUFFER_STORAGE_KEY               *BufferStorageKey;\r
+  CONFIG_ACCESS_PRIVATE                       *ConfigAccess;\r
+  LIST_ENTRY                                  *Link;\r
+  BUFFER_STORAGE_ENTRY               *BufferStorage;\r
   VOID                                        *Data;\r
   UINTN                                       DataSize;\r
 \r
   Data = NULL;\r
-  ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+  ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
 \r
   //\r
   // For now, only one var varstore is supported so that we don't need to parse the Configuration string.\r
   //\r
-  ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
-  if (ListEntry == NULL) {\r
+  Link = GetFirstNode (&ConfigAccess->BufferStorageListHead);\r
+  if (Link == NULL) {\r
     ASSERT (FALSE);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
-  BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
+  BufferStorage = BUFFER_STORAGE_ENTRY_FROM_LINK (Link);\r
 \r
-  if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
-      ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
-    Status = ExtractConfigFromUefiVariable (\r
-               BufferStorageKey,\r
+  if (ConfigAccess->FormCallbackProtocol == NULL ||\r
+      ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
+    Status = GetUefiVariable (\r
+               BufferStorage,\r
                &Data,\r
                &DataSize\r
                );\r
   } else {\r
-    Status = ExtractConfigFromFrameworkFormCallBack (\r
-               BufferStorageKey,\r
-               ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
+    Status = CallFormCallBack (\r
+               BufferStorage,\r
+               ConfigAccess->FormCallbackProtocol,\r
                 &Data,\r
                 &DataSize\r
                );\r
@@ -479,15 +488,15 @@ ThunkExtractConfig (
   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 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
+                           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
+   @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
@@ -498,31 +507,61 @@ ThunkRouteConfig (
   )\r
 {\r
   EFI_STATUS                                  Status;\r
-  HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE  *ConfigaAccessInstance;\r
-  LIST_ENTRY                                  *ListEntry;\r
-  HII_TRHUNK_BUFFER_STORAGE_KEY               *BufferStorageKey;\r
-  VOID                                        *Data;\r
+  CONFIG_ACCESS_PRIVATE                       *ConfigAccess;\r
+  LIST_ENTRY                                  *Link;\r
+  BUFFER_STORAGE_ENTRY                        *BufferStorage;\r
+  UINT8                                       *Data;\r
   UINTN                                       DataSize;\r
+  UINTN                                       DataSize2;\r
   UINTN                                       LastModifiedByteIndex;\r
+  BOOLEAN                                     ResetRequired;\r
+  BOOLEAN                                     DataAllocated;\r
 \r
   Data = NULL;\r
-  ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+  DataAllocated = TRUE;\r
+  ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
 \r
   //\r
   // For now, only one var varstore is supported so that we don't need to parse the Configuration string.\r
   //\r
-  ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
-  if (ListEntry == NULL) {\r
+  Link = GetFirstNode (&ConfigAccess->BufferStorageListHead);\r
+  if (Link == NULL) {\r
     ASSERT (FALSE);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
-\r
-  Data = AllocateZeroPool (BufferStorageKey->Size);\r
-  if (Data == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  BufferStorage = BUFFER_STORAGE_ENTRY_FROM_LINK (Link);\r
+  DataSize2     = BufferStorage->Size;\r
+  if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+    if (ConfigAccess->FormCallbackProtocol == NULL ||\r
+        ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
+      Status = GetUefiVariable (\r
+                 BufferStorage,\r
+                 &Data,\r
+                 &DataSize\r
+                 );\r
+      ASSERT (DataSize == DataSize2);\r
+      \r
+    } else {\r
+      Status = CallFormCallBack (\r
+                 BufferStorage,\r
+                 ConfigAccess->FormCallbackProtocol,\r
+                  &Data,\r
+                  &DataSize\r
+                 );\r
+      ASSERT (DataSize == DataSize2);\r
+      \r
+    }\r
+  } else {\r
+    Status = EFI_SUCCESS;\r
+    Data = ConfigAccess->ThunkContext->NvMapOverride;\r
+    DataSize      = DataSize2;\r
+    DataAllocated = FALSE;\r
+  }  \r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
   }\r
+\r
   Status = mHiiConfigRoutingProtocol->ConfigToBlock (\r
                                           mHiiConfigRoutingProtocol,\r
                                           Configuration,\r
@@ -530,54 +569,209 @@ ThunkRouteConfig (
                                           &LastModifiedByteIndex,\r
                                           Progress\r
                                           );\r
-\r
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
 \r
-  DataSize = BufferStorageKey->Size;\r
-  if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
-      ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
-    Status = RouteConfigToUefiVariable (\r
-               BufferStorageKey,\r
-               Data,\r
-               DataSize\r
-               );\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
+                  DataSize,\r
+                  Data\r
+                  );\r
   } else {\r
-    Status = RouteConfigToFrameworkFormCallBack (\r
-               BufferStorageKey,\r
-               ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
-               Data,\r
-               DataSize\r
-               );\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
+                  DataSize,\r
+                  Data,\r
+                  &ResetRequired\r
+                  );\r
+    \r
   }\r
 \r
-Done:  \r
-  SafeFreePool (Data);\r
+Done: \r
+  if (DataAllocated && (Data != NULL)) {\r
+    FreePool (Data);\r
+  }\r
+  \r
   return Status;\r
 }\r
 \r
+FRAMEWORK_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
+  FRAMEWORK_EFI_IFR_DATA_ARRAY      *IfrDataArray;\r
+  FRAMEWORK_EFI_IFR_DATA_ENTRY      *IfrDataEntry;\r
+  UINTN                             BrowserDataSize;\r
+  BUFFER_STORAGE_ENTRY              *BufferStorageEntry;\r
+  LIST_ENTRY                        *Link;\r
+\r
+  IfrDataArray = AllocateZeroPool (0x100);\r
+  ASSERT (IfrDataArray != NULL);\r
+\r
+  if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+    Link = GetFirstNode (&ConfigAccess->BufferStorageListHead);\r
+\r
+    ASSERT (!IsNull (&ConfigAccess->BufferStorageListHead, Link));\r
+\r
+    BufferStorageEntry = BUFFER_STORAGE_ENTRY_FROM_LINK(Link);\r
+\r
+    BrowserDataSize = BufferStorageEntry->Size;\r
+    *NvMapAllocated = TRUE;\r
+    IfrDataArray->NvRamMap = AllocateZeroPool (BrowserDataSize);\r
+    GetBrowserData (NULL, NULL, &BrowserDataSize, IfrDataArray->NvRamMap);\r
+  } else {\r
+    *NvMapAllocated = FALSE;\r
+    IfrDataArray->NvRamMap = ConfigAccess->ThunkContext->NvMapOverride;\r
+  }\r
+\r
+  IfrDataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) (IfrDataArray + 1);\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
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+  }\r
+\r
+  return IfrDataArray;\r
+}\r
+\r
+VOID\r
+DestroyIfrDataArray (\r
+  IN  FRAMEWORK_EFI_IFR_DATA_ARRAY *Array,\r
+  IN  BOOLEAN                      NvMapAllocated\r
+  )\r
+{\r
+  if (NvMapAllocated) {\r
+    FreePool (Array->NvRamMap);\r
+  }\r
+\r
+  FreePool (Array);\r
+}\r
+\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
+\r
+  Link = GetFirstNode (&ThunkContext->OneOfOptionMapListHead);\r
+\r
+  while (!IsNull (&ThunkContext->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 (&ThunkContext->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
+  @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 (except some porting works needed for callback for EFI_ONE_OF_OPTION opcode)\r
   and still 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 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
+                                    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
+                                    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_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
@@ -594,12 +788,16 @@ ThunkCallback (
   )\r
 {\r
   EFI_STATUS                                  Status;\r
-  HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE  *ConfigaAccessInstance;\r
-  EFI_FORM_CALLBACK_PROTOCOL                  *FrameworkFormCallbackProtocol;\r
+  CONFIG_ACCESS_PRIVATE                       *ConfigAccess;\r
+  EFI_FORM_CALLBACK_PROTOCOL                  *FormCallbackProtocol;\r
   EFI_HII_CALLBACK_PACKET                     *Packet;\r
-  FRAMEWORK_EFI_IFR_DATA_ARRAY                Data;\r
+  FRAMEWORK_EFI_IFR_DATA_ARRAY                *Data;\r
   FRAMEWORK_EFI_IFR_DATA_ENTRY                *DataEntry;\r
-  EFI_FORM_CALLBACK                           Callback; \r
+  UINT16                                      KeyValue;\r
+  ONE_OF_OPTION_MAP_ENTRY                     *OneOfOptionMapEntry;\r
+  EFI_HANDLE                                  NotifyHandle;\r
+  EFI_INPUT_KEY                               Key;  \r
+  BOOLEAN                                     NvMapAllocated;\r
 \r
   ASSERT (This != NULL);\r
   ASSERT (Value != NULL);\r
@@ -607,43 +805,111 @@ ThunkCallback (
 \r
   *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
 \r
-  ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+  ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
 \r
-  FrameworkFormCallbackProtocol = ConfigaAccessInstance->FrameworkFormCallbackProtocol;\r
-  if (FrameworkFormCallbackProtocol == NULL) {\r
+  FormCallbackProtocol = ConfigAccess->FormCallbackProtocol;\r
+  if (FormCallbackProtocol == NULL) {\r
+    ASSERT (FALSE);\r
     return EFI_UNSUPPORTED;\r
   }\r
-  Callback = FrameworkFormCallbackProtocol->Callback;\r
 \r
-  Status = Callback (\r
-              FrameworkFormCallbackProtocol,\r
-              QuestionId,\r
-              &Data,\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
+    KeyValue = OneOfOptionMapEntry->FwKey;\r
+  }\r
+\r
+  //\r
+  // Build the FRAMEWORK_EFI_IFR_DATA_ARRAY\r
+  //\r
+  Data = CreateIfrDataArray (ConfigAccess, QuestionId, Type, Value, &NvMapAllocated);\r
+\r
+  Status = mHiiDatabase->RegisterPackageNotify (\r
+                           mHiiDatabase,\r
+                           EFI_HII_PACKAGE_FORM,\r
+                           NULL,\r
+                           FormUpdateNotify,\r
+                           EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+                           &NotifyHandle\r
+                           );\r
+  //\r
+  //\r
+  //\r
+  Packet =  NULL;\r
+  Status =  FormCallbackProtocol->Callback (\r
+              FormCallbackProtocol,\r
+              KeyValue,\r
+              Data,\r
               &Packet\r
               );\r
 \r
   //\r
   // Callback require browser to perform action\r
   //\r
-  if (Packet != NULL) {\r
-    if (Packet->DataArray.EntryCount  == 1 && Packet->DataArray.NvRamMap == NULL) {\r
-      DataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY));\r
-      switch (DataEntry->Flags) {\r
-        case EXIT_REQUIRED:\r
-          *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
-          break;\r
-        case SAVE_REQUIRED:\r
-          *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
-          break;\r
-        case RESET_REQUIRED:\r
-            *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
-            break;\r
-        default:\r
-            *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-            break;  \r
-      }\r
+  if (EFI_ERROR (Status)) {\r
+    if (Packet != NULL) {\r
+      //\r
+      // BUGBUG: need to restore the changing question to default value\r
+      //\r
+\r
+      do {\r
+        IfrLibCreatePopUp (1, &Key, Packet->String);\r
+\r
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+      \r
     }\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 = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (FRAMEWORK_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 handles scenario 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
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
   }\r
+\r
+  DestroyIfrDataArray (Data, NvMapAllocated);\r
   \r
   return Status;\r
 }\r