]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
Base on the type field to get the width of value field for option opcode.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / ProcessOptions.c
index 8ac531f09cfbc6333fc08948d3e869fa26d92551..fecb98e8bf9a275b2716f8298803b22c012062b4 100644 (file)
@@ -2,8 +2,8 @@
 Implementation for handling the User Interface option processing.\r
 \r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -13,7 +13,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 **/\r
 \r
-#include "Ui.h"\r
 #include "Setup.h"\r
 \r
 \r
@@ -85,13 +84,20 @@ ValueToOption (
 {\r
   LIST_ENTRY       *Link;\r
   QUESTION_OPTION  *Option;\r
+  INTN             Result;\r
 \r
   Link = GetFirstNode (&Question->OptionListHead);\r
   while (!IsNull (&Question->OptionListHead, Link)) {\r
     Option = QUESTION_OPTION_FROM_LINK (Link);\r
 \r
-    if (CompareHiiValue (&Option->Value, OptionValue, NULL) == 0) {\r
-      return Option;\r
+    if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+      //\r
+      // Check the suppressif condition, only a valid option can be return.\r
+      //\r
+      if ((Option->SuppressExpression == NULL) ||\r
+          ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
+        return Option;\r
+      }\r
     }\r
 \r
     Link = GetNextNode (&Question->OptionListHead, Link);\r
@@ -101,6 +107,137 @@ ValueToOption (
 }\r
 \r
 \r
+/**\r
+  Return data element in an Array by its Index.\r
+\r
+  @param  Array                  The data array.\r
+  @param  Type                   Type of the data in this array.\r
+  @param  Index                  Zero based index for data in this array.\r
+\r
+  @retval Value                  The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+  IN VOID                     *Array,\r
+  IN UINT8                    Type,\r
+  IN UINTN                    Index\r
+  )\r
+{\r
+  UINT64 Data;\r
+\r
+  ASSERT (Array != NULL);\r
+\r
+  Data = 0;\r
+  switch (Type) {\r
+  case EFI_IFR_TYPE_NUM_SIZE_8:\r
+    Data = (UINT64) *(((UINT8 *) Array) + Index);\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_16:\r
+    Data = (UINT64) *(((UINT16 *) Array) + Index);\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_32:\r
+    Data = (UINT64) *(((UINT32 *) Array) + Index);\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_64:\r
+    Data = (UINT64) *(((UINT64 *) Array) + Index);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return Data;\r
+}\r
+\r
+\r
+/**\r
+  Set value of a data element in an Array by its Index.\r
+\r
+  @param  Array                  The data array.\r
+  @param  Type                   Type of the data in this array.\r
+  @param  Index                  Zero based index for data in this array.\r
+  @param  Value                  The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+  IN VOID                     *Array,\r
+  IN UINT8                    Type,\r
+  IN UINTN                    Index,\r
+  IN UINT64                   Value\r
+  )\r
+{\r
+\r
+  ASSERT (Array != NULL);\r
+\r
+  switch (Type) {\r
+  case EFI_IFR_TYPE_NUM_SIZE_8:\r
+    *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_16:\r
+    *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_32:\r
+    *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_64:\r
+    *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether this value already in the array, if yes, return the index.\r
+\r
+  @param  Array                  The data array.\r
+  @param  Type                   Type of the data in this array.\r
+  @param  Value                  The value to be find.\r
+  @param  Index                  The index in the array which has same value with Value.\r
+  \r
+  @retval   TRUE Found the value in the array.\r
+  @retval   FALSE Not found the value.\r
+\r
+**/\r
+BOOLEAN \r
+FindArrayData (\r
+  IN VOID                     *Array,\r
+  IN UINT8                    Type,\r
+  IN UINT64                   Value,\r
+  OUT UINTN                   *Index OPTIONAL\r
+  )\r
+{\r
+  UINTN  Count;\r
+  UINT64 TmpValue;\r
+  \r
+  ASSERT (Array != NULL);\r
+\r
+  Count    = 0;\r
+  TmpValue = 0;\r
+\r
+  while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {\r
+    if (Value == TmpValue) {\r
+      if (Index != NULL) {\r
+        *Index = Count;\r
+      }\r
+      return TRUE;\r
+    }\r
+\r
+    Count ++;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Print Question Value according to it's storage width and display attributes.\r
 \r
@@ -213,9 +350,8 @@ PasswordCallback (
   EFI_STATUS                      Status;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
   EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
-  EFI_HII_VALUE                   *QuestionValue;\r
+  EFI_IFR_TYPE_VALUE              IfrTypeValue;\r
 \r
-  QuestionValue = &MenuOption->ThisTag->HiiValue;\r
   ConfigAccess = Selection->FormSet->ConfigAccess;\r
   if (ConfigAccess == NULL) {\r
     return EFI_UNSUPPORTED;\r
@@ -225,9 +361,9 @@ PasswordCallback (
   // Prepare password string in HII database\r
   //\r
   if (String != NULL) {\r
-    QuestionValue->Value.string = NewString (String, Selection->FormSet->HiiHandle);\r
+    IfrTypeValue.string = NewString (String, Selection->FormSet->HiiHandle);\r
   } else {\r
-    QuestionValue->Value.string = 0;\r
+    IfrTypeValue.string = 0;\r
   }\r
 \r
   //\r
@@ -237,8 +373,8 @@ PasswordCallback (
                            ConfigAccess,\r
                            EFI_BROWSER_ACTION_CHANGING,\r
                            MenuOption->ThisTag->QuestionId,\r
-                           QuestionValue->Type,\r
-                           &QuestionValue->Value,\r
+                           MenuOption->ThisTag->HiiValue.Type,\r
+                           &IfrTypeValue,\r
                            &ActionRequest\r
                            );\r
 \r
@@ -246,7 +382,7 @@ PasswordCallback (
   // Remove password string from HII database\r
   //\r
   if (String != NULL) {\r
-    DeleteString (QuestionValue->Value.string, Selection->FormSet->HiiHandle);\r
+    DeleteString (IfrTypeValue.string, Selection->FormSet->HiiHandle);\r
   }\r
 \r
   return Status;\r
@@ -307,16 +443,19 @@ ProcessOptions (
   LIST_ENTRY                      *Link;\r
   EFI_HII_VALUE                   HiiValue;\r
   EFI_HII_VALUE                   *QuestionValue;\r
-  BOOLEAN                         Suppress;\r
   UINT16                          Maximum;\r
   QUESTION_OPTION                 *Option;\r
   UINTN                           Index2;\r
+  UINT8                           *ValueArray;\r
+  UINT8                           ValueType;\r
+  EFI_STRING_ID                   StringId;\r
 \r
   Status        = EFI_SUCCESS;\r
 \r
   StringPtr     = NULL;\r
   Character[1]  = L'\0';\r
   *OptionString = NULL;\r
+  StringId      = 0;\r
 \r
   ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
   BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow;\r
@@ -325,13 +464,21 @@ ProcessOptions (
   QuestionValue = &Question->HiiValue;\r
   Maximum = (UINT16) Question->Maximum;\r
 \r
+  ValueArray = Question->BufferValue;\r
+  ValueType = Question->ValueType;\r
+\r
   switch (Question->Operand) {\r
   case EFI_IFR_ORDERED_LIST_OP:\r
+    //\r
+    // Check whether there are Options of this OrderedList\r
+    //\r
+    if (IsListEmpty (&Question->OptionListHead)) {\r
+      break;\r
+    }\r
     //\r
     // Initialize Option value array\r
     //\r
-\r
-    if (Question->BufferValue[0] == 0) {\r
+    if (GetArrayData (ValueArray, ValueType, 0) == 0) {\r
       GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0);\r
     }\r
 \r
@@ -348,11 +495,11 @@ ProcessOptions (
       *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize);\r
       ASSERT (*OptionString);\r
 \r
-      HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+      HiiValue.Type = ValueType;\r
       HiiValue.Value.u64 = 0;\r
       for (Index = 0; Index < Question->MaxContainers; Index++) {\r
-        HiiValue.Value.u8 = Question->BufferValue[Index];\r
-        if (HiiValue.Value.u8 == 0) {\r
+        HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
+        if (HiiValue.Value.u64 == 0) {\r
           //\r
           // Values for the options in ordered lists should never be a 0\r
           //\r
@@ -375,45 +522,75 @@ ProcessOptions (
           Index2 = 0;\r
           while (!IsNull (&Question->OptionListHead, Link) && Index2 < Question->MaxContainers) {\r
             Option = QUESTION_OPTION_FROM_LINK (Link);\r
-            Question->BufferValue[Index2++] = Option->Value.Value.u8;\r
             Link = GetNextNode (&Question->OptionListHead, Link);\r
+            if ((Option->SuppressExpression != NULL) &&\r
+                ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
+              continue;\r
+            }\r
+            SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64);\r
+            Index2++;\r
           }\r
-          Question->BufferValue[Index2] = 0;\r
+          SetArrayData (ValueArray, ValueType, Index2, 0);\r
 \r
-          Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
-          UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+          Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
+          UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
 \r
           FreePool (*OptionString);\r
           *OptionString = NULL;\r
           return EFI_NOT_FOUND;\r
         }\r
 \r
-        Suppress = FALSE;\r
+        Character[0] = LEFT_ONEOF_DELIMITER;\r
+        NewStrCat (OptionString[0], Character);\r
+        StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
+        ASSERT (StringPtr != NULL);\r
+        NewStrCat (OptionString[0], StringPtr);\r
+        Character[0] = RIGHT_ONEOF_DELIMITER;\r
+        NewStrCat (OptionString[0], Character);\r
+        Character[0] = CHAR_CARRIAGE_RETURN;\r
+        NewStrCat (OptionString[0], Character);\r
+        FreePool (StringPtr);\r
+      }\r
+\r
+      //\r
+      // Search the other options, try to find the one not in the container.\r
+      //\r
+      Link = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+        Link = GetNextNode (&Question->OptionListHead, Link);\r
         if ((OneOfOption->SuppressExpression != NULL) &&\r
-            (OneOfOption->SuppressExpression->Result.Value.b)) {\r
-          //\r
-          // This option is suppressed\r
-          //\r
-          Suppress = TRUE;\r
+            ((EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
+          continue;\r
         }\r
 \r
-        if (!Suppress) {\r
-          Character[0] = LEFT_ONEOF_DELIMITER;\r
-          NewStrCat (OptionString[0], Character);\r
-          StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
-          NewStrCat (OptionString[0], StringPtr);\r
-          Character[0] = RIGHT_ONEOF_DELIMITER;\r
-          NewStrCat (OptionString[0], Character);\r
-          Character[0] = CHAR_CARRIAGE_RETURN;\r
-          NewStrCat (OptionString[0], Character);\r
-\r
-          FreePool (StringPtr);\r
+        if (FindArrayData (ValueArray, ValueType, OneOfOption->Value.Value.u64, NULL)) {\r
+          continue;\r
         }\r
+\r
+        SetArrayData (ValueArray, ValueType, Index++, OneOfOption->Value.Value.u64);\r
+\r
+        Character[0] = LEFT_ONEOF_DELIMITER;\r
+        NewStrCat (OptionString[0], Character);\r
+        StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
+        ASSERT (StringPtr != NULL);\r
+        NewStrCat (OptionString[0], StringPtr);\r
+        Character[0] = RIGHT_ONEOF_DELIMITER;\r
+        NewStrCat (OptionString[0], Character);\r
+        Character[0] = CHAR_CARRIAGE_RETURN;\r
+        NewStrCat (OptionString[0], Character);\r
+        FreePool (StringPtr);\r
       }\r
     }\r
     break;\r
 \r
   case EFI_IFR_ONE_OF_OP:\r
+    //\r
+    // Check whether there are Options of this OneOf\r
+    //\r
+    if (IsListEmpty (&Question->OptionListHead)) {\r
+      break;\r
+    }\r
     if (Selected) {\r
       //\r
       // Go ask for input\r
@@ -440,10 +617,10 @@ ProcessOptions (
           Option = QUESTION_OPTION_FROM_LINK (Link);\r
 \r
           if ((Option->SuppressExpression == NULL) ||\r
-              !Option->SuppressExpression->Result.Value.b) {\r
+              (EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)) {\r
             CopyMem (QuestionValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
-            SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
-            UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+            SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
+            UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
             break;\r
           }\r
 \r
@@ -455,49 +632,15 @@ ProcessOptions (
         return EFI_NOT_FOUND;\r
       }\r
 \r
-      if ((OneOfOption->SuppressExpression != NULL) &&\r
-          (OneOfOption->SuppressExpression->Result.Value.b)) {\r
-        //\r
-        // This option is suppressed\r
-        //\r
-        Suppress = TRUE;\r
-      } else {\r
-        Suppress = FALSE;\r
-      }\r
-\r
-      if (Suppress) {\r
-        //\r
-        // Current selected option happen to be suppressed,\r
-        // enforce to select on a non-suppressed option\r
-        //\r
-        Link = GetFirstNode (&Question->OptionListHead);\r
-        while (!IsNull (&Question->OptionListHead, Link)) {\r
-          OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
-\r
-          if ((OneOfOption->SuppressExpression == NULL) ||\r
-              !OneOfOption->SuppressExpression->Result.Value.b) {\r
-            Suppress = FALSE;\r
-            CopyMem (QuestionValue, &OneOfOption->Value, sizeof (EFI_HII_VALUE));\r
-            SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
-            UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
-            gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
-            break;\r
-          }\r
-\r
-          Link = GetNextNode (&Question->OptionListHead, Link);\r
-        }\r
-      }\r
+      Character[0] = LEFT_ONEOF_DELIMITER;\r
+      NewStrCat (OptionString[0], Character);\r
+      StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
+      ASSERT (StringPtr != NULL);\r
+      NewStrCat (OptionString[0], StringPtr);\r
+      Character[0] = RIGHT_ONEOF_DELIMITER;\r
+      NewStrCat (OptionString[0], Character);\r
 \r
-      if (!Suppress) {\r
-        Character[0] = LEFT_ONEOF_DELIMITER;\r
-        NewStrCat (OptionString[0], Character);\r
-        StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
-        NewStrCat (OptionString[0], StringPtr);\r
-        Character[0] = RIGHT_ONEOF_DELIMITER;\r
-        NewStrCat (OptionString[0], Character);\r
-\r
-        FreePool (StringPtr);\r
-      }\r
+      FreePool (StringPtr);\r
     }\r
     break;\r
 \r
@@ -530,8 +673,8 @@ ProcessOptions (
       //\r
       // Save Question value\r
       //\r
-      Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
-      UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+      Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
+      UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
     }\r
 \r
     if (QuestionValue->Value.b) {\r
@@ -590,7 +733,7 @@ ProcessOptions (
 \r
       case 2:\r
         SetUnicodeMem (OptionString[0], 7, L' ');\r
-        UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%4d", QuestionValue->Value.date.Year);\r
+        UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);\r
         *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;\r
         break;\r
       }\r
@@ -633,13 +776,20 @@ ProcessOptions (
     if (Selected) {\r
       StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
       ASSERT (StringPtr);\r
+      CopyMem(StringPtr, Question->BufferValue, Maximum * sizeof (CHAR16));\r
 \r
       Status = ReadString (MenuOption, gPromptForData, StringPtr);\r
       if (!EFI_ERROR (Status)) {\r
-        CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
-        SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
+        HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
+        Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+        if (EFI_ERROR (Status)) {\r
+          HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
+        } else {\r
+          CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
+          SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
 \r
-        UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+          UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+        }\r
       }\r
 \r
       FreePool (StringPtr);\r
@@ -672,8 +822,9 @@ ProcessOptions (
         //\r
         *StringPtr = 0;\r
         Status = PasswordCallback (Selection, MenuOption, StringPtr);\r
-        if (Status == EFI_NOT_AVAILABLE_YET) {\r
+        if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {\r
           //\r
+          // Callback is not supported, or\r
           // Callback request to terminate password input\r
           //\r
           FreePool (StringPtr);\r
@@ -724,7 +875,7 @@ ProcessOptions (
 \r
           TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue);\r
           ASSERT (TempString != NULL);\r
-          \r
+\r
           TempString[Maximum] = L'\0';\r
 \r
           if (StrCmp (StringPtr, TempString) != 0) {\r
@@ -783,13 +934,47 @@ ProcessOptions (
       //\r
       if (StrCmp (StringPtr, TempString) == 0) {\r
         //\r
-        // Two password match, send it to Configuration Driver\r
+        // Prepare the  Question->HiiValue.Value.string for ValidateQuestion use.\r
         //\r
-        if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
-          PasswordCallback (Selection, MenuOption, StringPtr);\r
+        if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+          StringId = Question->HiiValue.Value.string;\r
+          Question->HiiValue.Value.string = NewString (StringPtr, Selection->FormSet->HiiHandle);\r
         } else {\r
-          CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
-          SetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);\r
+          HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
+        }\r
+        \r
+        Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+\r
+        //\r
+        //  Researve the Question->HiiValue.Value.string.\r
+        //\r
+        if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+          DeleteString(Question->HiiValue.Value.string, Selection->FormSet->HiiHandle);\r
+          Question->HiiValue.Value.string = StringId;\r
+        }   \r
+        \r
+        if (EFI_ERROR (Status)) {\r
+          //\r
+          // Reset state machine for interactive password\r
+          //\r
+          if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+            PasswordCallback (Selection, MenuOption, NULL);\r
+          } else {\r
+            //\r
+            // Researve the Question->HiiValue.Value.string.\r
+            //\r
+            HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);            \r
+          }\r
+        } else {\r
+          //\r
+          // Two password match, send it to Configuration Driver\r
+          //\r
+          if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+            PasswordCallback (Selection, MenuOption, StringPtr);\r
+          } else {\r
+            CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
+            SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);\r
+          }\r
         }\r
       } else {\r
         //\r
@@ -826,206 +1011,65 @@ ProcessOptions (
 \r
   @param  StringPtr              The entire help string.\r
   @param  FormattedString        The oupput formatted string.\r
+  @param  EachLineWidth          The max string length of each line in the formatted string.\r
   @param  RowCount               TRUE: if Question is selected.\r
 \r
 **/\r
-VOID\r
+UINTN\r
 ProcessHelpString (\r
   IN  CHAR16  *StringPtr,\r
   OUT CHAR16  **FormattedString,\r
+  OUT UINT16  *EachLineWidth,\r
   IN  UINTN   RowCount\r
   )\r
 {\r
-  UINTN BlockWidth;\r
-  UINTN AllocateSize;\r
-  //\r
-  // [PrevCurrIndex, CurrIndex) forms a range of a screen-line\r
-  //\r
-  UINTN CurrIndex;\r
-  UINTN PrevCurrIndex;\r
-  UINTN LineCount;\r
-  UINTN VirtualLineCount;\r
-  //\r
-  // GlyphOffset stores glyph width of current screen-line\r
-  //\r
-  UINTN GlyphOffset;\r
-  //\r
-  // GlyphWidth equals to 2 if we meet width directive\r
-  //\r
-  UINTN GlyphWidth;\r
-  //\r
-  // during scanning, we remember the position of last space character\r
-  // in case that if next word cannot put in current line, we could restore back to the position\r
-  // of last space character\r
-  // while we should also remmeber the glyph width of the last space character for restoring\r
-  //\r
-  UINTN LastSpaceIndex;\r
-  UINTN LastSpaceGlyphWidth;\r
+  UINTN   Index;\r
+  CHAR16  *OutputString;\r
+  UINTN   TotalRowNum;\r
+  UINTN   CheckedNum;\r
+  UINT16  GlyphWidth;\r
+  UINT16  LineWidth;\r
+  UINT16  MaxStringLen;\r
+  UINT16  StringLen;\r
+\r
+  TotalRowNum    = 0;\r
+  CheckedNum     = 0;\r
+  GlyphWidth     = 1;\r
+  Index          = 0;\r
+  MaxStringLen   = 0;\r
+  StringLen      = 0;\r
+\r
   //\r
-  // every time we begin to form a new screen-line, we should remember glyph width of single character\r
-  // of last line\r
+  // Set default help string width.\r
   //\r
-  UINTN LineStartGlyphWidth;\r
-  UINTN *IndexArray;\r
-  UINTN *OldIndexArray;\r
+  LineWidth      = (UINT16) (gHelpBlockWidth - 1);\r
 \r
-  BlockWidth = (UINTN) gHelpBlockWidth - 1;\r
-  \r
   //\r
-  // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )\r
-  // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want\r
-  // to bring the width directive of the last line to current screen-line.\r
-  // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line\r
-  // different from that of "\wideabcde", we should remember the width directive.\r
+  // Get row number of the String.\r
   //\r
-  AllocateSize  = 0x20;\r
-  IndexArray    = AllocatePool (AllocateSize * sizeof (UINTN) * 3);\r
-  ASSERT (IndexArray != NULL);\r
-\r
-  if (*FormattedString != NULL) {\r
-    FreePool (*FormattedString);\r
-    *FormattedString = NULL;\r
-  }\r
-\r
-  for (PrevCurrIndex = 0, CurrIndex  = 0, LineCount   = 0, LastSpaceIndex = 0,\r
-       IndexArray[0] = 0, GlyphWidth = 1, GlyphOffset = 0, LastSpaceGlyphWidth = 1, LineStartGlyphWidth = 1;\r
-       (StringPtr[CurrIndex] != CHAR_NULL);\r
-       CurrIndex ++) {\r
-\r
-    if (LineCount == AllocateSize) {\r
-      AllocateSize += 0x10;\r
-      OldIndexArray  = IndexArray;\r
-      IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);\r
-      CopyMem (IndexArray, OldIndexArray, LineCount * sizeof (UINTN) * 3);\r
-      FreePool (OldIndexArray);\r
-    }\r
-    switch (StringPtr[CurrIndex]) {\r
-\r
-      case NARROW_CHAR:\r
-      case WIDE_CHAR:\r
-        GlyphWidth = ((StringPtr[CurrIndex] == WIDE_CHAR) ? 2 : 1);\r
-        if (CurrIndex == 0) {\r
-          LineStartGlyphWidth = GlyphWidth;\r
-        }\r
-        break;\r
-\r
-      //\r
-      // char is '\n'\r
-      // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN\r
-      //\r
-      case CHAR_LINEFEED:\r
-        //\r
-        // Store a range of string as a line\r
-        //\r
-        IndexArray[LineCount*3]   = PrevCurrIndex;\r
-        IndexArray[LineCount*3+1] = CurrIndex;\r
-        IndexArray[LineCount*3+2] = LineStartGlyphWidth;\r
-        LineCount ++;\r
-        //\r
-        // Reset offset and save begin position of line\r
-        //\r
-        GlyphOffset = 0;\r
-        LineStartGlyphWidth = GlyphWidth;\r
-        PrevCurrIndex = CurrIndex + 1;\r
-        break;\r
-\r
-      //\r
-      // char is '\r'\r
-      // "\r\n" and "\r" both are handled here\r
-      //\r
-      case CHAR_CARRIAGE_RETURN:\r
-        if (StringPtr[CurrIndex + 1] == CHAR_LINEFEED) {\r
-          //\r
-          // next char is '\n'\r
-          //\r
-          IndexArray[LineCount*3]   = PrevCurrIndex;\r
-          IndexArray[LineCount*3+1] = CurrIndex;\r
-          IndexArray[LineCount*3+2] = LineStartGlyphWidth;\r
-          LineCount ++;\r
-          CurrIndex ++;\r
-        }\r
-        GlyphOffset = 0;\r
-        LineStartGlyphWidth = GlyphWidth;\r
-        PrevCurrIndex = CurrIndex + 1;\r
-        break;\r
-\r
-      //\r
-      // char is space or other char\r
-      //\r
-      default:\r
-        GlyphOffset     += GlyphWidth;\r
-        if (GlyphOffset >= BlockWidth) {\r
-          if (LastSpaceIndex > PrevCurrIndex) {\r
-            //\r
-            // LastSpaceIndex points to space inside current screen-line,\r
-            // restore to LastSpaceIndex\r
-            // (Otherwise the word is too long to fit one screen-line, just cut it)\r
-            //\r
-            CurrIndex  = LastSpaceIndex;\r
-            GlyphWidth = LastSpaceGlyphWidth;\r
-          } else if (GlyphOffset > BlockWidth) {\r
-            //\r
-            // the word is too long to fit one screen-line and we don't get the chance\r
-            // of GlyphOffset == BlockWidth because GlyphWidth = 2\r
-            //\r
-            CurrIndex --;\r
-          }\r
-\r
-          IndexArray[LineCount*3]   = PrevCurrIndex;\r
-          IndexArray[LineCount*3+1] = CurrIndex + 1;\r
-          IndexArray[LineCount*3+2] = LineStartGlyphWidth;\r
-          LineStartGlyphWidth = GlyphWidth;\r
-          LineCount ++;\r
-          //\r
-          // Reset offset and save begin position of line\r
-          //\r
-          GlyphOffset                 = 0;\r
-          PrevCurrIndex               = CurrIndex + 1;\r
-        }\r
-\r
-        //\r
-        // LastSpaceIndex: remember position of last space\r
-        //\r
-        if (StringPtr[CurrIndex] == CHAR_SPACE) {\r
-          LastSpaceIndex      = CurrIndex;\r
-          LastSpaceGlyphWidth = GlyphWidth;\r
-        }\r
-        break;\r
+  while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
+    if (StringLen > MaxStringLen) {\r
+      MaxStringLen = StringLen;\r
     }\r
-  }\r
 \r
-  if (GlyphOffset > 0) {\r
-    IndexArray[LineCount*3]   = PrevCurrIndex;\r
-    IndexArray[LineCount*3+1] = CurrIndex;\r
-    IndexArray[LineCount*3+2] = GlyphWidth;\r
-    LineCount ++;\r
+    TotalRowNum ++;\r
+    FreePool (OutputString);\r
   }\r
+  *EachLineWidth = MaxStringLen;\r
 \r
-  if (LineCount == 0) {\r
-    //\r
-    // in case we meet null string\r
-    //\r
-    IndexArray[0] = 0;\r
-    IndexArray[1] = 1;\r
-    //\r
-    // we assume null string's glyph width is 1\r
-    //\r
-    IndexArray[1] = 1;\r
-    LineCount ++;\r
-  }\r
-\r
-  VirtualLineCount = RowCount * (LineCount / RowCount + (LineCount % RowCount > 0));\r
-  *FormattedString = AllocateZeroPool (VirtualLineCount * (BlockWidth + 1) * sizeof (CHAR16) * 2);\r
+  *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));\r
   ASSERT (*FormattedString != NULL);\r
 \r
-  for (CurrIndex = 0; CurrIndex < LineCount; CurrIndex ++) {\r
-    *(*FormattedString + CurrIndex * 2 * (BlockWidth + 1)) = (CHAR16) ((IndexArray[CurrIndex*3+2] == 2) ? WIDE_CHAR : NARROW_CHAR);\r
-    StrnCpy (\r
-      *FormattedString + CurrIndex * 2 * (BlockWidth + 1) + 1,\r
-      StringPtr + IndexArray[CurrIndex*3],\r
-      IndexArray[CurrIndex*3+1]-IndexArray[CurrIndex*3]\r
-      );\r
+  //\r
+  // Generate formatted help string array.\r
+  //\r
+  GlyphWidth  = 1;\r
+  Index       = 0;\r
+  while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
+    CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));\r
+    CheckedNum ++;\r
+    FreePool (OutputString);\r
   }\r
 \r
-  FreePool (IndexArray);\r
+  return TotalRowNum; \r
 }\r