]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.c
Refine all R9 call back function to return EFI_UNSUPPORTED for all unsupported call...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / ConfigAccess.c
index 117d6ea636ebd000f05920020a05e410061294de..86820ca5dadb6f4094e43ae5a87efc594dc60ab8 100644 (file)
@@ -1,10 +1,10 @@
-/**@file\r
+/** @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, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2008 - 2011, 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
@@ -83,14 +83,15 @@ GetFirstStorageOfFormSet (
 }\r
 \r
 /**\r
-  Get the EFI_IFR_VARSTORE where the Question's value is stored.\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 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.\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
-FORMSET_STORAGE *\r
+FORM_BROWSER_STATEMENT *\r
 GetStorageFromQuestionId (\r
   IN CONST FORM_BROWSER_FORMSET * FormSet,\r
   IN       EFI_QUESTION_ID        QuestionId\r
@@ -115,7 +116,7 @@ GetStorageFromQuestionId (
         // UEFI Question ID is unique in a FormSet.\r
         //\r
         ASSERT (Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER);\r
-        return Statement->Storage;\r
+        return Statement;\r
       }\r
       StatementList = GetNextNode (&Form->StatementListHead, StatementList);\r
     }\r
@@ -126,38 +127,6 @@ GetStorageFromQuestionId (
   return NULL;\r
 }\r
 \r
-/**\r
-  Get the EFI_IFR_VARSTORE based the ID.\r
-    \r
-  @param FormSet                  The Form Set.\r
-   \r
-  @retval FORMSET_STORAGE *       The EFI_IFR_VARSTORE with the ID.\r
-  @retval NULL                    If the Form Set does not have EFI_IFR_VARSTORE with such ID.\r
-**/\r
-FORMSET_STORAGE *\r
-GetStorageFromVarStoreId (\r
-  IN CONST FORM_BROWSER_FORMSET * FormSet,\r
-  IN       EFI_VARSTORE_ID        VarStoreId\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
-\r
-    if (VarStoreId == Storage->VarStoreId) {\r
-      return Storage;\r
-    }\r
-\r
-    StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\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
@@ -178,6 +147,10 @@ GetStorageFromConfigString (
   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
@@ -189,14 +162,14 @@ GetStorageFromConfigString (
       Name = Storage->Name;\r
     }\r
     \r
-    if (IsConfigHdrMatch (ConfigString, &Storage->Guid, Name)) {\r
+    if (HiiIsConfigHdrMatch (ConfigString, &Storage->Guid, Name)) {\r
       return Storage;\r
     }\r
 \r
     StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
   }\r
 \r
-   return NULL;\r
+  return NULL;\r
 }\r
 \r
 /**\r
@@ -343,11 +316,11 @@ CallFormCallBack (
     }\r
 \r
     *Data = AllocateZeroPool (*DataSize);\r
-    if (Data == NULL) {\r
+    if (*Data == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    FwFormCallBack->NvRead (\r
+    Status = FwFormCallBack->NvRead (\r
                   FwFormCallBack,  \r
                   BufferStorage->Name,\r
                   &BufferStorage->Guid,\r
@@ -376,7 +349,6 @@ CallFormCallBack (
    @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
-\r
 EFI_STATUS\r
 GetUefiVariable (\r
   IN       FORMSET_STORAGE                            *BufferStorage,\r
@@ -403,7 +375,7 @@ GetUefiVariable (
     }\r
 \r
     *Data = AllocateZeroPool (*DataSize);\r
-    if (Data == NULL) {\r
+    if (*Data == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
@@ -451,73 +423,194 @@ ThunkExtractConfig (
   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
-\r
-  if (Request == NULL) {\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
-  Data = NULL;\r
-  ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\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
+    }\r
+  \r
+    VarStoreName     = NULL;\r
+    ConfigRequestHdr = NULL;\r
+    ConfigRequest    = NULL;\r
+    Size             = 0;\r
+    AllocatedRequest = FALSE;\r
 \r
-  BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Request);\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 == NULL) {\r
-    *Progress = (EFI_STRING) Request;\r
-    return EFI_NOT_FOUND;\r
-  }\r
+        if ((BufferStorage->VarStoreId == FormSetContext->DefaultVarStoreId) && (FormSetContext->OriginalDefaultVarStoreName != NULL)) {\r
+          VarStoreName = FormSetContext->OriginalDefaultVarStoreName;\r
+        } else {\r
+          VarStoreName = BufferStorage->Name;\r
+        }\r
 \r
-  if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\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
-    // NvMapOverride is not used. Get the Storage data from EFI Variable or Framework Form Callback.\r
+    // Free the allocated Data\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
+    if (Data != NULL) {\r
+      FreePool (Data);\r
     }\r
-  } else {\r
     //\r
-    // Use the NvMapOverride.\r
+    // Directly return when meet with error\r
     //\r
-    DataSize = BufferStorage->Size;\r
-    Data = AllocateCopyPool (DataSize, ConfigAccess->ThunkContext->NvMapOverride);\r
-    \r
-    if (Data != NULL) {\r
-      Status = EFI_SUCCESS;\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
-      Status = EFI_OUT_OF_RESOURCES;\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
-  }\r
-  \r
+  } while (Request == NULL);\r
+\r
   if (!EFI_ERROR (Status)) {\r
-    Status = mHiiConfigRoutingProtocol->BlockToConfig (\r
-                                            mHiiConfigRoutingProtocol,\r
-                                            Request,\r
-                                            Data,\r
-                                            DataSize,\r
-                                            Results,\r
-                                            Progress\r
-                                            );\r
+    *Results = FinalResults;\r
+  } else {\r
+    if (FinalResults != NULL) {\r
+      FreePool (FinalResults);\r
+    }\r
   }\r
-\r
-  if (Data != NULL) {\r
-    FreePool (Data);\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
@@ -550,7 +643,6 @@ ThunkRouteConfig (
   VOID                                        *Data;\r
   UINTN                                       DataSize;\r
   UINTN                                       DataSize2;\r
-  UINTN                                       LastModifiedByteIndex;\r
   BOOLEAN                                     ResetRequired;\r
   BOOLEAN                                     DataAllocated;\r
 \r
@@ -601,17 +693,18 @@ ThunkRouteConfig (
     }\r
   }\r
 \r
+  DataSize = DataSize2;\r
   Status = mHiiConfigRoutingProtocol->ConfigToBlock (\r
                                           mHiiConfigRoutingProtocol,\r
                                           Configuration,\r
                                           Data,\r
-                                          &LastModifiedByteIndex,\r
+                                          &DataSize,\r
                                           Progress\r
                                           );\r
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
-\r
+  \r
   if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
     if (ConfigAccess->FormCallbackProtocol == NULL ||\r
         ConfigAccess->FormCallbackProtocol->NvWrite == NULL) {\r
@@ -632,7 +725,6 @@ ThunkRouteConfig (
                     Data,\r
                     &ResetRequired\r
                     );\r
-      \r
     }\r
   }\r
 \r
@@ -645,21 +737,21 @@ Done:
 }\r
 \r
 /**\r
-  Build the FRAMEWORK_EFI_IFR_DATA_ARRAY which will be used to pass to \r
-  EFI_FORM_CALLBACK_PROTOCOL.Callback. Check definition of FRAMEWORK_EFI_IFR_DATA_ARRAY\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 This             Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\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 FRAMEWORK_EFI_IFR_DATA_ARRAY. The caller must free this buffer allocated.\r
+   @return A pointer to EFI_IFR_DATA_ARRAY. The caller must free this buffer allocated.\r
 **/   \r
-FRAMEWORK_EFI_IFR_DATA_ARRAY *\r
+EFI_IFR_DATA_ARRAY *\r
 CreateIfrDataArray (\r
   IN    CONFIG_ACCESS_PRIVATE         *ConfigAccess,\r
   IN    EFI_QUESTION_ID               QuestionId,\r
@@ -668,14 +760,13 @@ CreateIfrDataArray (
   OUT   BOOLEAN                       *NvMapAllocated\r
   )\r
 {\r
-  FRAMEWORK_EFI_IFR_DATA_ARRAY      *IfrDataArray;\r
-  FRAMEWORK_EFI_IFR_DATA_ENTRY      *IfrDataEntry;\r
+  EFI_IFR_DATA_ARRAY                *IfrDataArray;\r
+  EFI_IFR_DATA_ENTRY                *IfrDataEntry;\r
   UINTN                             BrowserDataSize;\r
-  FORMSET_STORAGE                  *BufferStorage;\r
-  EFI_STATUS                        Status;\r
+  FORMSET_STORAGE                   *BufferStorage;\r
   UINTN                             Size;\r
-  UINTN                             StringSize;\r
   EFI_STRING                        String;\r
+  FORM_BROWSER_STATEMENT            *Statement;\r
 \r
   *NvMapAllocated = FALSE;\r
 \r
@@ -691,17 +782,19 @@ CreateIfrDataArray (
       break;\r
 \r
     case EFI_IFR_TYPE_STRING:\r
-      StringSize = 0;\r
-      Status = HiiLibGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, String, &StringSize);\r
-      ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
-\r
-      String = AllocateZeroPool (StringSize);\r
-      ASSERT (String != NULL);\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
-      Status = HiiLibGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, String, &StringSize);\r
-      ASSERT_EFI_ERROR (Status);\r
+        Size = StrSize (String);\r
+      }\r
+      break;\r
 \r
-      Size = StringSize;\r
+    case EFI_IFR_TYPE_ACTION:\r
+    case EFI_IFR_TYPE_UNDEFINED:\r
+      Size = 0;\r
       break;\r
       \r
     default:\r
@@ -710,21 +803,27 @@ CreateIfrDataArray (
       break;\r
   }\r
 \r
-  IfrDataArray = AllocateZeroPool (sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY) + sizeof (FRAMEWORK_EFI_IFR_DATA_ENTRY) + Size);\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
-  BufferStorage  = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
+  Statement = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
 \r
-  if (BufferStorage == NULL) {\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
+    BrowserDataSize      = BufferStorage->Size;\r
+    IfrDataEntry->Length = (UINT8) (sizeof (EFI_IFR_DATA_ENTRY) + Size);\r
 \r
     if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
       *NvMapAllocated = TRUE;\r
@@ -734,10 +833,7 @@ CreateIfrDataArray (
       IfrDataArray->NvRamMap = ConfigAccess->ThunkContext->NvMapOverride;\r
     }\r
     \r
-    Status = GetBrowserData (&BufferStorage->Guid, BufferStorage->Name, &BrowserDataSize, IfrDataArray->NvRamMap);\r
-    ASSERT_EFI_ERROR (Status);\r
-\r
-    IfrDataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) (IfrDataArray + 1);\r
+    ASSERT (HiiGetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, (UINT8 *) IfrDataArray->NvRamMap));\r
 \r
     switch (Type) {\r
       case EFI_IFR_TYPE_NUM_SIZE_8:\r
@@ -749,21 +845,28 @@ CreateIfrDataArray (
         break;\r
 \r
       case EFI_IFR_TYPE_STRING:\r
-        ASSERT (String != NULL);\r
-        StrCpy ((CHAR16 *) &IfrDataEntry->Data, String);\r
-        FreePool (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 FRAMEWORK_EFI_IFR_DATA_ENTRY.\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 FRAMEWORK_EFI_IFR_DATA_ENTRY packet\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
@@ -791,21 +894,24 @@ SyncBrowserDataForNvMapOverride (
   IN          EFI_QUESTION_ID               QuestionId\r
   )\r
 {\r
-  FORMSET_STORAGE                  *BufferStorage;\r
-  EFI_STATUS                        Status;\r
-  UINTN                             BrowserDataSize;\r
+  FORMSET_STORAGE   *BufferStorage;\r
+  BOOLEAN           CheckFlag;\r
+  UINTN             BrowserDataSize;\r
+  FORM_BROWSER_STATEMENT *Statement;\r
 \r
   if (ConfigAccess->ThunkContext->NvMapOverride != NULL) {\r
 \r
-    BufferStorage = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
+    Statement = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
 \r
-    if (BufferStorage == NULL) {\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
@@ -815,22 +921,22 @@ SyncBrowserDataForNvMapOverride (
     \r
     BrowserDataSize = BufferStorage->Size;\r
 \r
-    Status = SetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, ConfigAccess->ThunkContext->NvMapOverride, NULL);\r
-    ASSERT_EFI_ERROR (Status);\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 FRAMEWORK_EFI_IFR_DATA_ARRAY by CreateIfrDataArray ().\r
+  Free up resource allocated for a EFI_IFR_DATA_ARRAY by CreateIfrDataArray ().\r
 \r
-  @param Array              The FRAMEWORK_EFI_IFR_DATA_ARRAY allocated.\r
-  @param NvMapAllocated     If the NvRamMap is allocated for FRAMEWORK_EFI_IFR_DATA_ARRAY.\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  FRAMEWORK_EFI_IFR_DATA_ARRAY *Array,\r
+  IN  EFI_IFR_DATA_ARRAY           *Array,\r
   IN  BOOLEAN                      NvMapAllocated\r
   )\r
 {\r
@@ -993,133 +1099,139 @@ ThunkCallback (
   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_ENTRY                *DataEntry;\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
-  ASSERT (This != NULL);\r
-  ASSERT (Value != NULL);\r
-  ASSERT (ActionRequest != NULL);\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
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
 \r
-  ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\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
+    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
+    // 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
-  if (OneOfOptionMapEntry == NULL) {\r
     //\r
-    // This is not a One-Of-Option opcode. QuestionId is the KeyValue\r
+    // Build the EFI_IFR_DATA_ARRAY\r
     //\r
-    KeyValue = QuestionId;\r
-  } else {\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
-    // Otherwise, use the original Key specified in One Of Option in the Framework VFR syntax.\r
+    //Call the Framework Callback function.\r
     //\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_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
+    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
-        IfrLibCreatePopUp (1, &Key, Packet->String);\r
-      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-    }\r
     //\r
-    // Error Code in Status is discarded.\r
+    // Callback require browser to perform action\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
+    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
-        }\r
-        FreePool (Packet);\r
+          FreePool (Packet);\r
+      }\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
+    // 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
+    //\r
+    // Clean up.\r
+    //\r
+    DestroyIfrDataArray (Data, NvMapAllocated);\r
+\r
+    return Status;\r
+  }\r
 \r
   //\r
-  // Clean up.\r
+  // All other action return unsupported.\r
   //\r
-  DestroyIfrDataArray (Data, NvMapAllocated);\r
-  \r
-  return Status;\r
+  return EFI_UNSUPPORTED;\r
 }\r
 \r