]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
MdeModulePkg: Check for NULL pointer before dereference it.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index a437674bdc5c0f3e57b170d4f956e652d729315f..754781457501e0f6577a4f8469fa21caf02d838a 100644 (file)
@@ -181,7 +181,7 @@ UiFindMenuList (
     // Find the same FromSet.\r
     //\r
     if (MenuList->HiiHandle == HiiHandle) {\r
-      if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) {\r
+      if (IsZeroGuid (&MenuList->FormSetGuid)) {\r
         //\r
         // FormSetGuid is not specified.\r
         //\r
@@ -938,7 +938,7 @@ InitializeSetup (
   \r
   Status = gBS->InstallProtocolInterface (\r
                   &mPrivateData.Handle,\r
-                  &gEfiFormBrowserExProtocolGuid,\r
+                  &gEdkiiFormBrowserExProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
                   &mPrivateData.FormBrowserEx\r
                   );\r
@@ -1429,40 +1429,44 @@ BufferToValue (
   *StringPtr = L'\0';\r
 \r
   LengthStr = StrLen (Value);\r
+\r
+  //\r
+  // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.\r
+  // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).\r
+  // So the maximum value string length of a question is : Question->StorageWidth * 2.\r
+  // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.\r
+  //\r
+  if (LengthStr > (UINTN) Question->StorageWidth * 2) {\r
+    Length = (UINTN) Question->StorageWidth * 2;\r
+  } else {\r
+    Length = LengthStr;\r
+  }\r
+\r
   Status    = EFI_SUCCESS;\r
   if (!IsBufferStorage && IsString) {\r
     //\r
     // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
     // Add string tail char L'\0' into Length\r
     //\r
-    Length    = Question->StorageWidth + sizeof (CHAR16);\r
-    if (Length < ((LengthStr / 4 + 1) * 2)) {\r
-      Status = EFI_BUFFER_TOO_SMALL;\r
-    } else {\r
-      DstBuf = (CHAR16 *) Dst;\r
-      ZeroMem (TemStr, sizeof (TemStr));\r
-      for (Index = 0; Index < LengthStr; Index += 4) {\r
-        StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);\r
-        DstBuf[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
-      }\r
-      //\r
-      // Add tailing L'\0' character\r
-      //\r
-      DstBuf[Index/4] = L'\0';\r
+    DstBuf = (CHAR16 *) Dst;\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index += 4) {\r
+      StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);\r
+      DstBuf[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
     }\r
+    //\r
+    // Add tailing L'\0' character\r
+    //\r
+    DstBuf[Index/4] = L'\0';\r
   } else {\r
-    if (Question->StorageWidth < ((LengthStr + 1) / 2)) {\r
-      Status = EFI_BUFFER_TOO_SMALL;\r
-    } else {\r
-      ZeroMem (TemStr, sizeof (TemStr));\r
-      for (Index = 0; Index < LengthStr; Index ++) {\r
-        TemStr[0] = Value[LengthStr - Index - 1];\r
-        DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
-        if ((Index & 1) == 0) {\r
-          Dst [Index/2] = DigitUint8;\r
-        } else {\r
-          Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
-        }\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index ++) {\r
+      TemStr[0] = Value[LengthStr - Index - 1];\r
+      DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+      if ((Index & 1) == 0) {\r
+        Dst [Index/2] = DigitUint8;\r
+      } else {\r
+        Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
       }\r
     }\r
   }\r
@@ -3182,6 +3186,9 @@ SubmitForForm (
   EFI_STRING              Progress;\r
   BROWSER_STORAGE         *Storage;\r
   FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  BOOLEAN                 SubmitFormFail;\r
+\r
+  SubmitFormFail = FALSE;\r
 \r
   if (!IsNvUpdateRequiredForForm (Form)) {\r
     return EFI_SUCCESS;\r
@@ -3225,17 +3232,19 @@ SubmitForForm (
                                       ConfigResp,\r
                                       &Progress\r
                                       );\r
-    FreePool (ConfigResp);\r
 \r
     if (EFI_ERROR (Status)) {\r
       //\r
       // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
       //\r
+      SubmitFormFail = TRUE;\r
       GetSyncRestoreConfigRequest (ConfigInfo->Storage, ConfigInfo->ConfigRequest, Progress, &ConfigInfo->RestoreConfigRequest, &ConfigInfo->SyncConfigRequest);\r
       InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
+      FreePool (ConfigResp);\r
       continue;\r
     }\r
 \r
+    FreePool (ConfigResp);\r
     //\r
     // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
     //\r
@@ -3266,6 +3275,7 @@ SubmitForForm (
 \r
         Status = EFI_SUCCESS;\r
       }\r
+      SendDiscardInfoToDriver (FormSet,Form);\r
     } else {\r
       Status = EFI_UNSUPPORTED;\r
     }\r
@@ -3288,7 +3298,9 @@ SubmitForForm (
   //\r
   // 6 Call callback with Submitted type to inform the driver.\r
   //\r
-  SubmitCallback (FormSet, Form);\r
+  if (!SubmitFormFail) {\r
+    SubmitCallback (FormSet, Form);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -3324,8 +3336,12 @@ SubmitForFormSet (
   FORM_BROWSER_FORM       *Form;\r
   BOOLEAN                 HasInserted;\r
   FORM_BROWSER_STATEMENT  *Question;\r
+  BOOLEAN                 SubmitFormSetFail;\r
+  BOOLEAN                 DiscardChange;\r
 \r
   HasInserted = FALSE;\r
+  SubmitFormSetFail = FALSE;\r
+  DiscardChange     = FALSE;\r
 \r
   if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
     return EFI_SUCCESS;\r
@@ -3388,6 +3404,7 @@ SubmitForFormSet (
       //\r
       // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
       //\r
+      SubmitFormSetFail = TRUE;\r
       GetSyncRestoreConfigRequest (FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, Progress, &FormSetStorage->RestoreConfigRequest, &FormSetStorage->SyncConfigRequest);\r
       InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
       if (!HasInserted) {\r
@@ -3425,6 +3442,7 @@ SubmitForFormSet (
       // If not in system level, just handl the save failed storage here.\r
       //\r
       if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
+        DiscardChange = TRUE;\r
         Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
         while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
           FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
@@ -3473,6 +3491,21 @@ SubmitForFormSet (
     }\r
   }\r
 \r
+  //\r
+  // If user discard the change, send the discard info to driver.\r
+  //\r
+  if (DiscardChange) {\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
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    }\r
+  }\r
+\r
   //\r
   // 5. Update the NV flag.\r
   // \r
@@ -3481,7 +3514,9 @@ SubmitForFormSet (
   //\r
   // 6. Call callback with Submitted type to inform the driver.\r
   //\r
-  SubmitCallback (FormSet, NULL);\r
+  if (!SubmitFormSetFail) {\r
+    SubmitCallback (FormSet, NULL);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -3590,6 +3625,16 @@ SubmitForSystem (
         }\r
       }\r
 \r
+      Link = GetFirstNode (&LocalFormSet->FormListHead);\r
+      while (!IsNull (&LocalFormSet->FormListHead, Link)) {\r
+        Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+        Link = GetNextNode (&LocalFormSet->FormListHead, Link);\r
+        //\r
+        // Call callback with Changed type to inform the driver.\r
+        //\r
+        SendDiscardInfoToDriver (LocalFormSet, Form);\r
+      }\r
+\r
       if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
         CleanBrowserStorage(LocalFormSet);\r
         RemoveEntryList (&LocalFormSet->Link);\r
@@ -3744,6 +3789,11 @@ GetOffsetFromConfigResp (
   // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
   //\r
 \r
+  //\r
+  // Convert all hex digits in ConfigResp to lower case before searching.\r
+  //\r
+  HiiToLower (ConfigResp);\r
+\r
   //\r
   // 1. Directly use Question->BlockName to find.\r
   //\r
@@ -4038,9 +4088,14 @@ GetQuestionDefault (
   INTN                            Action;\r
   CHAR16                          *NewString;\r
   EFI_IFR_TYPE_VALUE              *TypeValue;\r
+  UINT16                          OriginalDefaultId;\r
+  FORMSET_DEFAULTSTORE            *DefaultStore;\r
+  LIST_ENTRY                      *DefaultLink;\r
 \r
   Status   = EFI_NOT_FOUND;\r
   StrValue = NULL;\r
+  OriginalDefaultId  = DefaultId;\r
+  DefaultLink        = GetFirstNode (&FormSet->DefaultStoreListHead);\r
 \r
   //\r
   // Statement don't have storage, skip them\r
@@ -4057,6 +4112,7 @@ GetQuestionDefault (
   //  4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
   //  5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
   //\r
+ReGetDefault:\r
   HiiValue = &Question->HiiValue;\r
   TypeValue = &HiiValue->Value;\r
   if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
@@ -4088,6 +4144,7 @@ GetQuestionDefault (
 \r
         ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
         if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
+          ZeroMem (Question->BufferValue, Question->StorageWidth);\r
           CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
         } else {\r
           CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
@@ -4158,6 +4215,7 @@ GetQuestionDefault (
             return EFI_NOT_FOUND;\r
           }\r
           if (Question->StorageWidth > StrSize (StrValue)) {\r
+            ZeroMem (Question->BufferValue, Question->StorageWidth);\r
             CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
           } else {\r
             CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
@@ -4212,8 +4270,6 @@ GetQuestionDefault (
           ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
          ) {\r
         HiiValue->Value.b = TRUE;\r
-      } else {\r
-        HiiValue->Value.b = FALSE;\r
       }\r
 \r
       return EFI_SUCCESS;\r
@@ -4221,10 +4277,30 @@ GetQuestionDefault (
   }\r
 \r
   //\r
-  // For Questions without default\r
+  // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.\r
+  // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.\r
+  // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.\r
+  //\r
+  while (!IsNull(&FormSet->DefaultStoreListHead, DefaultLink)) {\r
+    DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);\r
+    DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead,DefaultLink);\r
+    DefaultId = DefaultStore->DefaultId;\r
+    if (DefaultId == OriginalDefaultId) {\r
+      continue;\r
+    }\r
+    goto ReGetDefault;\r
+  }\r
+\r
+  //\r
+  // For Questions without default value for all the default id in the DefaultStoreList.\r
   //\r
   Status = EFI_NOT_FOUND;\r
   switch (Question->Operand) {\r
+  case EFI_IFR_CHECKBOX_OP:\r
+    HiiValue->Value.b = FALSE;\r
+    Status = EFI_SUCCESS;\r
+    break;\r
+\r
   case EFI_IFR_NUMERIC_OP:\r
     //\r
     // Take minimum value as numeric default value\r
@@ -5642,7 +5718,7 @@ GetIfrBinaryData (
           //\r
           // Try to compare against formset GUID\r
           //\r
-          if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
+          if (IsZeroGuid (FormSetGuid) ||\r
               CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
             break;\r
           }\r