]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Base on the type field to get the width of value field for option opcode.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index b1eb88f4db240d81a098e89294291f1889e6f785..bcc8e020fdb2b8339fc60c4c6fb647e96aaaaeb9 100644 (file)
@@ -815,7 +815,7 @@ GetToken (
 \r
   String = HiiGetString (HiiHandle, Token, NULL);\r
   if (String == NULL) {\r
-    String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
+    String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
     ASSERT (String != NULL);\r
   }\r
   return (CHAR16 *) String;\r
@@ -933,6 +933,7 @@ SynchronizeStorage (
   @param  Storage                The NameValue Storage.\r
   @param  Name                   The Name.\r
   @param  Value                  The retured Value.\r
+  @param  GetValueFrom           Where to get source value, from EditValue or Value.\r
 \r
   @retval EFI_SUCCESS            Value found for given Name.\r
   @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
@@ -940,14 +941,19 @@ SynchronizeStorage (
 **/\r
 EFI_STATUS\r
 GetValueByName (\r
-  IN FORMSET_STORAGE         *Storage,\r
-  IN CHAR16                  *Name,\r
-  IN OUT CHAR16              **Value\r
+  IN FORMSET_STORAGE             *Storage,\r
+  IN CHAR16                      *Name,\r
+  IN OUT CHAR16                  **Value,\r
+  IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
   )\r
 {\r
   LIST_ENTRY              *Link;\r
   NAME_VALUE_NODE         *Node;\r
 \r
+  if (GetValueFrom != GetSetValueWithEditBuffer && GetValueFrom != GetSetValueWithBuffer) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   *Value = NULL;\r
 \r
   Link = GetFirstNode (&Storage->NameValueListHead);\r
@@ -955,7 +961,11 @@ GetValueByName (
     Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
 \r
     if (StrCmp (Name, Node->Name) == 0) {\r
-      NewStringCpy (Value, Node->EditValue);\r
+      if (GetValueFrom == GetSetValueWithEditBuffer) {\r
+        NewStringCpy (Value, Node->EditValue);\r
+      } else {\r
+        NewStringCpy (Value, Node->Value);\r
+      }\r
       return EFI_SUCCESS;\r
     }\r
 \r
@@ -972,7 +982,7 @@ GetValueByName (
   @param  Storage                The NameValue Storage.\r
   @param  Name                   The Name.\r
   @param  Value                  The Value to set.\r
-  @param  Edit                   Whether update editValue or Value.\r
+  @param  SetValueTo             Whether update editValue or Value.\r
 \r
   @retval EFI_SUCCESS            Value found for given Name.\r
   @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
@@ -983,19 +993,23 @@ SetValueByName (
   IN FORMSET_STORAGE         *Storage,\r
   IN CHAR16                  *Name,\r
   IN CHAR16                  *Value,\r
-  IN BOOLEAN                 Edit\r
+  IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
   )\r
 {\r
   LIST_ENTRY              *Link;\r
   NAME_VALUE_NODE         *Node;\r
   CHAR16                  *Buffer;\r
 \r
+  if (SetValueTo != GetSetValueWithEditBuffer && SetValueTo != GetSetValueWithBuffer) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   Link = GetFirstNode (&Storage->NameValueListHead);\r
   while (!IsNull (&Storage->NameValueListHead, Link)) {\r
     Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
 \r
     if (StrCmp (Name, Node->Name) == 0) {\r
-      if (Edit) {\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
         Buffer = Node->EditValue;\r
       } else {\r
         Buffer = Node->Value;\r
@@ -1005,7 +1019,7 @@ SetValueByName (
       }\r
       Buffer = AllocateCopyPool (StrSize (Value), Value);\r
       ASSERT (Buffer != NULL);\r
-      if (Edit) {\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
         Node->EditValue = Buffer;\r
       } else {\r
         Node->Value = Buffer;\r
@@ -1162,7 +1176,7 @@ ConfigRespToStorage (
       if (StrPtr != NULL) {\r
         *StrPtr = 0;\r
       }\r
-      SetValueByName (Storage, Name, Value, TRUE);\r
+      SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer);\r
     }\r
     break;\r
 \r
@@ -1182,8 +1196,7 @@ ConfigRespToStorage (
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
   @param  Question               Question to be initialized.\r
-  @param  Cached                 TRUE:  get from Edit copy FALSE: get from original\r
-                                 Storage\r
+  @param  GetValueFrom           Where to get value, may from editbuffer, buffer or hii driver.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
 \r
@@ -1193,7 +1206,7 @@ GetQuestionValue (
   IN FORM_BROWSER_FORMSET             *FormSet,\r
   IN FORM_BROWSER_FORM                *Form,\r
   IN OUT FORM_BROWSER_STATEMENT       *Question,\r
-  IN BOOLEAN                          Cached\r
+  IN GET_SET_QUESTION_VALUE_WITH      GetValueFrom\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -1222,6 +1235,10 @@ GetQuestionValue (
   Value  = NULL;\r
   Result = NULL;\r
 \r
+  if (GetValueFrom >= GetSetValueWithMax) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   //\r
   // Statement don't have storage, skip them\r
   //\r
@@ -1373,15 +1390,22 @@ GetQuestionValue (
     IsBufferStorage = FALSE;\r
   }\r
   IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
-  if (Cached) {\r
+  if (GetValueFrom == GetSetValueWithEditBuffer || GetValueFrom == GetSetValueWithBuffer ) {\r
     if (IsBufferStorage) {\r
-      //\r
-      // Copy from storage Edit buffer\r
-      //\r
-      CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+      if (GetValueFrom == GetSetValueWithEditBuffer) {\r
+        //\r
+        // Copy from storage Edit buffer\r
+        //\r
+        CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+      } else {\r
+        //\r
+        // Copy from storage Edit buffer\r
+        //\r
+        CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+      }\r
     } else {\r
       Value = NULL;\r
-      Status = GetValueByName (Storage, Question->VariableName, &Value);\r
+      Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
       }\r
@@ -1578,7 +1602,7 @@ GetQuestionValue (
     if (IsBufferStorage) {\r
       CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
     } else {\r
-      SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
+      SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer);\r
     }\r
 \r
     if (Result != NULL) {\r
@@ -1596,8 +1620,7 @@ GetQuestionValue (
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
   @param  Question               Pointer to the Question.\r
-  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original\r
-                                 Storage\r
+  @param  SetValueTo             Update the question value to editbuffer , buffer or hii driver.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
 \r
@@ -1607,7 +1630,7 @@ SetQuestionValue (
   IN FORM_BROWSER_FORMSET             *FormSet,\r
   IN FORM_BROWSER_FORM                *Form,\r
   IN OUT FORM_BROWSER_STATEMENT       *Question,\r
-  IN BOOLEAN                          Cached\r
+  IN GET_SET_QUESTION_VALUE_WITH      SetValueTo\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -1632,6 +1655,10 @@ SetQuestionValue (
 \r
   Status = EFI_SUCCESS;\r
 \r
+  if (SetValueTo >= GetSetValueWithMax) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   //\r
   // Statement don't have storage, skip them\r
   //\r
@@ -1747,47 +1774,55 @@ SetQuestionValue (
     IsBufferStorage = FALSE;\r
   }\r
   IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
-  if (IsBufferStorage) {\r
-    //\r
-    // Copy to storage edit buffer\r
-    //\r
-    CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
-  } else {\r
-    if (IsString) {\r
-      //\r
-      // Allocate enough string buffer.\r
-      //\r
-      Value = NULL;\r
-      BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
-      Value = AllocateZeroPool (BufferLen);\r
-      ASSERT (Value != NULL);\r
-      //\r
-      // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
-      //\r
-      TemName = (CHAR16 *) Src;\r
-      TemString = Value;\r
-      for (; *TemName != L'\0'; TemName++) {\r
-        TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
+\r
+  if (SetValueTo == GetSetValueWithEditBuffer || SetValueTo == GetSetValueWithBuffer) {\r
+    if (IsBufferStorage) {\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
+        //\r
+        // Copy to storage edit buffer\r
+        //      \r
+        CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+      } else if (SetValueTo == GetSetValueWithBuffer) {\r
+        //\r
+        // Copy to storage edit buffer\r
+        //     \r
+        CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
       }\r
     } else {\r
-      BufferLen = StorageWidth * 2 + 1;\r
-      Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
-      ASSERT (Value != NULL);\r
-      //\r
-      // Convert Buffer to Hex String\r
-      //\r
-      TemBuffer = Src + StorageWidth - 1;\r
-      TemString = Value;\r
-      for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
-        TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
+      if (IsString) {\r
+        //\r
+        // Allocate enough string buffer.\r
+        //\r
+        Value = NULL;\r
+        BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
+        Value = AllocateZeroPool (BufferLen);\r
+        ASSERT (Value != NULL);\r
+        //\r
+        // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+        //\r
+        TemName = (CHAR16 *) Src;\r
+        TemString = Value;\r
+        for (; *TemName != L'\0'; TemName++) {\r
+          TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
+        }\r
+      } else {\r
+        BufferLen = StorageWidth * 2 + 1;\r
+        Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+        ASSERT (Value != NULL);\r
+        //\r
+        // Convert Buffer to Hex String\r
+        //\r
+        TemBuffer = Src + StorageWidth - 1;\r
+        TemString = Value;\r
+        for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
+          TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
+        }\r
       }\r
-    }\r
-\r
-    Status = SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
-    FreePool (Value);\r
-  }\r
 \r
-  if (!Cached) {\r
+      Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo);\r
+      FreePool (Value);\r
+    }\r
+  } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
     if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
       //\r
       // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
@@ -1950,7 +1985,7 @@ ValidateQuestion (
       return Status;\r
     }\r
 \r
-    if (Expression->Result.Value.b) {\r
+    if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) {\r
       //\r
       // Condition meet, show up error message\r
       //\r
@@ -2115,6 +2150,105 @@ SynchronizeStorageForForm (
   return Status;\r
 }\r
 \r
+/**\r
+  When discard the question value, call the callback function with Changed type\r
+  to inform the hii driver.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+**/\r
+VOID\r
+SendDiscardInfoToDriver (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_STATEMENT      *Question;\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_VALUE               HiiValue;\r
+  UINT8                       *BufferValue;\r
+  BOOLEAN                     ValueChanged;\r
+  EFI_IFR_TYPE_VALUE          *TypeValue;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+\r
+  ValueChanged = FALSE;\r
+  BufferValue  = NULL;\r
+\r
+  if(!Form->NvUpdateRequired) {\r
+    return;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+    if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+      continue;\r
+    }\r
+\r
+    if (Question->BufferValue != NULL) {\r
+      BufferValue = AllocateZeroPool (Question->StorageWidth);\r
+      ASSERT (BufferValue != NULL);\r
+      CopyMem (BufferValue, Question->BufferValue, Question->StorageWidth);\r
+    } else {\r
+      HiiValue.Type = Question->HiiValue.Type;\r
+      CopyMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+    }\r
+\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+    if (EFI_ERROR (Status)) {\r
+      if (BufferValue != NULL) {\r
+        FreePool (BufferValue);\r
+        BufferValue = NULL;\r
+      }\r
+      continue;\r
+    }\r
+\r
+    if (Question->BufferValue != NULL) {\r
+      if (CompareMem (BufferValue, Question->BufferValue, Question->StorageWidth)) {\r
+        ValueChanged = TRUE;\r
+      }\r
+    } else {\r
+      if (CompareMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE))) {\r
+        ValueChanged = TRUE;\r
+      }\r
+    }\r
+\r
+    if (BufferValue != NULL) {\r
+      FreePool (BufferValue);\r
+      BufferValue = NULL;\r
+    }\r
+\r
+    if (!ValueChanged) {\r
+      continue;\r
+    }\r
+\r
+    ValueChanged = FALSE;\r
+\r
+    if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
+      TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
+    } else {\r
+      TypeValue = &Question->HiiValue.Value;\r
+    }\r
+\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    FormSet->ConfigAccess->Callback (\r
+                             FormSet->ConfigAccess,\r
+                             EFI_BROWSER_ACTION_CHANGED,\r
+                             Question->QuestionId,\r
+                             Question->HiiValue.Type,\r
+                             TypeValue,\r
+                             &ActionRequest\r
+                             );\r
+  }\r
+}\r
 \r
 /**\r
   Discard data based on the input setting scope (Form, FormSet or System).\r
@@ -2168,10 +2302,16 @@ DiscardForm (
       // Prepare <ConfigResp>\r
       //\r
       SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);\r
+\r
+      //\r
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
     }\r
 \r
     Form->NvUpdateRequired = FALSE;\r
   } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
+\r
     //\r
     // Discard Buffer storage or Name/Value storage\r
     //\r
@@ -2194,6 +2334,17 @@ DiscardForm (
       SynchronizeStorage(Storage, FALSE);\r
     }\r
 \r
+    Link = GetFirstNode (&FormSet->FormListHead);\r
+    while (!IsNull (&FormSet->FormListHead, Link)) {\r
+      Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+      Link = GetNextNode (&FormSet->FormListHead, Link);\r
+      \r
+      //\r
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    }\r
+\r
     UpdateNvInfoInForm (FormSet, FALSE);   \r
   } else if (SettingScope == SystemLevel) {\r
     //\r
@@ -2875,6 +3026,12 @@ GetQuestionDefault (
       Link = GetFirstNode (&Question->OptionListHead);\r
       while (!IsNull (&Question->OptionListHead, Link)) {\r
         Option = QUESTION_OPTION_FROM_LINK (Link);\r
+        Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+          continue;\r
+        }\r
 \r
         if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
             ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
@@ -2883,8 +3040,6 @@ GetQuestionDefault (
 \r
           return EFI_SUCCESS;\r
         }\r
-\r
-        Link = GetNextNode (&Question->OptionListHead, Link);\r
       }\r
     }\r
   }\r
@@ -2930,10 +3085,18 @@ GetQuestionDefault (
     //\r
     if (ValueToOption (Question, HiiValue) == NULL) {\r
       Link = GetFirstNode (&Question->OptionListHead);\r
-      if (!IsNull (&Question->OptionListHead, Link)) {\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
         Option = QUESTION_OPTION_FROM_LINK (Link);\r
+        Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+          continue;\r
+        }\r
+\r
         CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
         Status = EFI_SUCCESS;\r
+        break;\r
       }\r
     }\r
     break;\r
@@ -2947,6 +3110,12 @@ GetQuestionDefault (
     while (!IsNull (&Question->OptionListHead, Link)) {\r
       Status = EFI_SUCCESS;\r
       Option = QUESTION_OPTION_FROM_LINK (Link);\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+      if ((Option->SuppressExpression != NULL) &&\r
+          EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+        continue;\r
+      }\r
 \r
       SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
 \r
@@ -2954,8 +3123,6 @@ GetQuestionDefault (
       if (Index >= Question->MaxContainers) {\r
         break;\r
       }\r
-\r
-      Link = GetNextNode (&Question->OptionListHead, Link);\r
     }\r
     break;\r
 \r
@@ -2968,12 +3135,20 @@ GetQuestionDefault (
 \r
 \r
 /**\r
-  Reset Questions to their default value in a Form, Formset or System.\r
+  Reset Questions to their initial value or default value in a Form, Formset or System.\r
+\r
+  GetDefaultValueScope parameter decides which questions will reset \r
+  to its default value.\r
 \r
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
   @param  DefaultId              The Class of the default.\r
   @param  SettingScope           Setting Scope for Default action.\r
+  @param  GetDefaultValueScope   Get default value scope.\r
+  @param  Storage                Get default value only for this storage.\r
+  @param  RetrieveValueFirst     Whether call the retrieve call back to\r
+                                 get the initial value before get default\r
+                                 value.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
   @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
@@ -2984,7 +3159,10 @@ ExtractDefault (
   IN FORM_BROWSER_FORMSET             *FormSet,\r
   IN FORM_BROWSER_FORM                *Form,\r
   IN UINT16                           DefaultId,\r
-  IN BROWSER_SETTING_SCOPE            SettingScope\r
+  IN BROWSER_SETTING_SCOPE            SettingScope,\r
+  IN BROWSER_GET_DEFAULT_VALUE        GetDefaultValueScope,\r
+  IN FORMSET_STORAGE                  *Storage OPTIONAL,\r
+  IN BOOLEAN                          RetrieveValueFirst\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -2997,10 +3175,16 @@ ExtractDefault (
   UINTN                   Index;\r
   EFI_GUID                ZeroGuid;\r
 \r
+  Status = EFI_SUCCESS;\r
+\r
   //\r
   // Check the supported setting level.\r
   //\r
-  if (SettingScope >= MaxLevel) {\r
+  if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
     return EFI_UNSUPPORTED;\r
   }\r
   \r
@@ -3012,7 +3196,21 @@ ExtractDefault (
     while (!IsNull (&Form->StatementListHead, Link)) {\r
       Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
       Link = GetNextNode (&Form->StatementListHead, Link);\r
-  \r
+\r
+      //\r
+      // If get default value only for this storage, check the storage first.\r
+      //\r
+      if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // If get default value only for no storage question, just skip the question which has storage.\r
+      //\r
+      if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
+        continue;\r
+      }\r
+\r
       //\r
       // If Question is disabled, don't reset it to default\r
       //\r
@@ -3021,21 +3219,30 @@ ExtractDefault (
           continue;\r
         }\r
       }\r
-  \r
+\r
+      if (RetrieveValueFirst) {\r
+        //\r
+        // Call the Retrieve call back to get the initial question value.\r
+        //\r
+        Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question);\r
+      }\r
+\r
       //\r
-      // Reset Question to its default value\r
+      // If not request to get the initial value or get initial value fail, then get default value.\r
       //\r
-      Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
-      if (EFI_ERROR (Status)) {\r
-        continue;\r
+      if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
+        Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+        if (EFI_ERROR (Status)) {\r
+          continue;\r
+        }\r
       }\r
-  \r
+\r
       //\r
       // Synchronize Buffer storage's Edit buffer\r
       //\r
       if ((Question->Storage != NULL) &&\r
           (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
-        SetQuestionValue (FormSet, Form, Question, TRUE);\r
+        SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
         //\r
         // Update Form NV flag.\r
         //\r
@@ -3046,7 +3253,7 @@ ExtractDefault (
     FormLink = GetFirstNode (&FormSet->FormListHead);\r
     while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
       Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
-      ExtractDefault (FormSet, Form, DefaultId, FormLevel);\r
+      ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
       FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
     }\r
   } else if (SettingScope == SystemLevel) {\r
@@ -3093,7 +3300,7 @@ ExtractDefault (
       //\r
       // Initilize Questions' Value\r
       //\r
-      LoadFormSetConfig (NULL, LocalFormSet);\r
+      Status = LoadFormSetConfig (NULL, LocalFormSet);\r
       if (EFI_ERROR (Status)) {\r
         DestroyFormSet (LocalFormSet);\r
         continue;\r
@@ -3117,7 +3324,7 @@ ExtractDefault (
     Link = GetFirstNode (&gBrowserFormSetList);\r
     while (!IsNull (&gBrowserFormSetList, Link)) {\r
       LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
-      ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel);\r
+      ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
       Link = GetNextNode (&gBrowserFormSetList, Link);\r
     }\r
   }\r
@@ -3158,7 +3365,7 @@ LoadFormConfig (
     //\r
     // Initialize local copy of Value for each Question\r
     //\r
-    Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -3168,26 +3375,10 @@ LoadFormConfig (
     }\r
 \r
     //\r
-    // According the spec, ref opcode try to get value from call back with "retrieve" type.\r
-    //\r
-    if ((Question->Operand == EFI_IFR_REF_OP) && (FormSet->ConfigAccess != NULL) && (Selection != NULL)) {\r
-      Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Check whether EfiVarstore with CallBack can be got.\r
+    // Call the Retrieve call back function for all questions.\r
     //\r
-    if ((FormSet->ConfigAccess != NULL) &&\r
-        (Selection != NULL) &&\r
-        (Selection->Action != UI_ACTION_REFRESH_FORMSET) &&\r
-        (Question->QuestionId != 0) && \r
-        (Question->Storage != NULL) &&\r
-        (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
+    if ((FormSet->ConfigAccess != NULL) && (Selection != NULL) &&\r
         ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
-\r
       //\r
       // Check QuestionValue does exist.\r
       //\r
@@ -3197,17 +3388,21 @@ LoadFormConfig (
       } else {\r
         BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
       }\r
-      Status = gRT->GetVariable (\r
-                       Question->VariableName,\r
-                       &Question->Storage->Guid,\r
-                       NULL,\r
-                       &StorageWidth,\r
-                       BufferValue\r
-                       );\r
 \r
-      if (!EFI_ERROR (Status)) {\r
-        Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
+      //\r
+      // For efivarstore storage, initial question value first.\r
+      //\r
+      if ((Question->Storage != NULL) && (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+        Status = gRT->GetVariable (\r
+                         Question->VariableName,\r
+                         &Question->Storage->Guid,\r
+                         NULL,\r
+                         &StorageWidth,\r
+                         BufferValue\r
+                         );\r
       }\r
+\r
+      Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
     }\r
 \r
     Link = GetNextNode (&Form->StatementListHead, Link);\r
@@ -3318,7 +3513,7 @@ LoadStorage (
   //\r
   // Convert Result from <ConfigAltResp> to <ConfigResp>\r
   //\r
-  StrPtr = StrStr (Result, L"ALTCFG");\r
+  StrPtr = StrStr (Result, L"&GUID=");\r
   if (StrPtr != NULL) {\r
     *StrPtr = L'\0';\r
   }\r
@@ -3364,8 +3559,8 @@ CopyStorage (
     while (!IsNull (&Src->NameValueListHead, Link)) {\r
       Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
 \r
-      SetValueByName (Dst, Node->Name, Node->EditValue, TRUE);\r
-      SetValueByName (Dst, Node->Name, Node->Value, FALSE);\r
+      SetValueByName (Dst, Node->Name, Node->EditValue, GetSetValueWithEditBuffer);\r
+      SetValueByName (Dst, Node->Name, Node->Value, GetSetValueWithBuffer);\r
 \r
       Link = GetNextNode (&Src->NameValueListHead, Link);\r
     }\r
@@ -3379,6 +3574,79 @@ CopyStorage (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Get old question value from the saved formset.\r
+\r
+  @param  Statement              The question which need to get old question value.\r
+  @param  OldFormSet             FormSet data structure saved in the list.\r
+\r
+**/\r
+VOID \r
+GetOldQuestionValue (\r
+  IN OUT FORM_BROWSER_STATEMENT  *Statement,\r
+  IN     FORM_BROWSER_FORMSET    *OldFormSet\r
+  )\r
+{\r
+  LIST_ENTRY              *FormLink;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  FORM_BROWSER_FORM       *Form;\r
+\r
+  FormLink = GetFirstNode (&OldFormSet->FormListHead);\r
+  while (!IsNull (&OldFormSet->FormListHead, FormLink)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+    FormLink = GetNextNode (&OldFormSet->FormListHead, FormLink);\r
+\r
+    Link = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, Link)) {\r
+      Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+      Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+      if (Question->QuestionId != Statement->QuestionId) {\r
+        continue;\r
+      }\r
+\r
+      CopyMem (&Statement->HiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+      return;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get old question value from the saved formset, all these questions not have\r
+  storage.\r
+\r
+  @param  FormSet                FormSet data structure which is used now.\r
+  @param  OldFormSet             FormSet data structure saved in the list.\r
+\r
+**/\r
+VOID\r
+CopyOldValueForNoStorageQst (\r
+  IN OUT FORM_BROWSER_FORMSET             *FormSet,\r
+  IN     FORM_BROWSER_FORMSET             *OldFormSet\r
+  )\r
+{\r
+  LIST_ENTRY              *FormLink;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  FORM_BROWSER_FORM       *Form;\r
+\r
+  FormLink = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+    FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+\r
+    Link = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, Link)) {\r
+      Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+      Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+      if (Question->Storage == NULL) {\r
+        GetOldQuestionValue (Question, OldFormSet);\r
+      }\r
+    }\r
+  }\r
+}\r
 \r
 /**\r
   Get current setting of Questions.\r
@@ -3403,10 +3671,9 @@ InitializeCurrentSetting (
   EFI_STATUS              Status;\r
 \r
   //\r
-  // Extract default from IFR binary\r
-  //\r
-  ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel);\r
-  UpdateNvInfoInForm (FormSet, FALSE);\r
+  // Extract default from IFR binary for no storage questions.\r
+  //  \r
+  ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE);\r
 \r
   //\r
   // Request current settings from Configuration Driver\r
@@ -3438,13 +3705,24 @@ InitializeCurrentSetting (
       // Storage is not found in backup formset, request it from ConfigDriver\r
       //\r
       Status = LoadStorage (FormSet, Storage);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // If get last time changed value failed, extract default from IFR binary\r
+        //\r
+        ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);\r
+        //\r
+        // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag\r
+        // in current situation.\r
+        //\r
+        UpdateNvInfoInForm (FormSet, FALSE);\r
+      }\r
+\r
       //\r
-      // Now Edit Buffer is filled with default values(lower priority) and current\r
+      // Now Edit Buffer is filled with default values(lower priority) or current\r
       // settings(higher priority), sychronize it to shadow Buffer\r
       //\r
-      if (!EFI_ERROR (Status)) {\r
-        SynchronizeStorage (Storage, TRUE);\r
-      }\r
+      SynchronizeStorage (Storage, TRUE);\r
     } else {\r
       //\r
       // Storage found in backup formset, use it\r
@@ -3459,23 +3737,23 @@ InitializeCurrentSetting (
   // If has old formset, get the old nv update status.\r
   //\r
   if (gOldFormSet != NULL) {\r
-      Link = GetFirstNode (&FormSet->FormListHead);\r
-      while (!IsNull (&FormSet->FormListHead, Link)) {\r
-        Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link = GetFirstNode (&FormSet->FormListHead);\r
+    while (!IsNull (&FormSet->FormListHead, Link)) {\r
+      Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
 \r
-        Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
-        while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
-          Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
-\r
-          if (Form->FormId == Form2->FormId) {\r
-            Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
-            break;\r
-          }\r
+      Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
+      while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
+        Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
 \r
-          Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
+        if (Form->FormId == Form2->FormId) {\r
+          Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
+          break;\r
         }\r
-          Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+        Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
       }\r
+      Link = GetNextNode (&FormSet->FormListHead, Link);\r
+    }\r
   }\r
 \r
   return EFI_SUCCESS;\r