Reviewed-by: Liming Gao <liming....@intel.com>

-----Original Message-----
From: Dong, Eric 
Sent: Thursday, April 30, 2015 1:57 PM
To: edk2-devel@lists.sourceforge.net; Gao, Liming
Subject: [Patch 2/2] MdeModulePkg: Enhance the check for numeric opcode with 
EFI_IFR_DISPLAY_INT_DEC attribute.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Eric Dong <eric.d...@intel.com>
---
 MdeModulePkg/Library/UefiHiiLib/HiiLib.c           | 100 ++++++----
 .../Universal/DisplayEngineDxe/InputHandler.c      | 202 +++++++++++++++++----
 MdeModulePkg/Universal/SetupBrowserDxe/Setup.c     |  40 +++-
 3 files changed, 267 insertions(+), 75 deletions(-)

diff --git a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c 
b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
index 09f1ff7..7ae5c4c 100644
--- a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
+++ b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
@@ -1296,45 +1296,81 @@ ValidateQuestionFromVfr (
             // Check the current value is in the numeric range.
             //
             VarValue = 0;
             CopyMem (&VarValue, VarBuffer +  Offset, Width);
           }
-          switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
-          case EFI_IFR_NUMERIC_SIZE_1:
-            if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) 
VarValue > IfrNumeric->data.u8.MaxValue) {
-              //
-              // Not in the valid range.
-              //
-              return EFI_INVALID_PARAMETER;
-            }
-            break;
-          case EFI_IFR_NUMERIC_SIZE_2:
-            if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) 
VarValue > IfrNumeric->data.u16.MaxValue) {
-              //
-              // Not in the valid range.
-              //
-              return EFI_INVALID_PARAMETER;
-            }
-            break;
-          case EFI_IFR_NUMERIC_SIZE_4:
-            if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) 
VarValue > IfrNumeric->data.u32.MaxValue) {
-              //
-              // Not in the valid range.
-              //
-              return EFI_INVALID_PARAMETER;
+          if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) {
+            switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
+            case EFI_IFR_NUMERIC_SIZE_1:
+              if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || 
(INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
+            case EFI_IFR_NUMERIC_SIZE_2:
+              if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || 
(INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
+            case EFI_IFR_NUMERIC_SIZE_4:
+              if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || 
(INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
+            case EFI_IFR_NUMERIC_SIZE_8:
+              if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || 
(INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
             }
-            break;
-          case EFI_IFR_NUMERIC_SIZE_8:
-            if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) 
VarValue > IfrNumeric->data.u64.MaxValue) {
-              //
-              // Not in the valid range.
-              //
-              return EFI_INVALID_PARAMETER;
+          } else {
+            switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
+            case EFI_IFR_NUMERIC_SIZE_1:
+              if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) 
VarValue > IfrNumeric->data.u8.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
+            case EFI_IFR_NUMERIC_SIZE_2:
+              if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || 
(UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
+            case EFI_IFR_NUMERIC_SIZE_4:
+              if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || 
(UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
+            case EFI_IFR_NUMERIC_SIZE_8:
+              if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || 
(UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {
+                //
+                // Not in the valid range.
+                //
+                return EFI_INVALID_PARAMETER;
+              }
+              break;
             }
-            break;
           }
-
           break;
         case EFI_IFR_CHECKBOX_OP:
           //
           // Check value is BOOLEAN type, only 0 and 1 is valid.
           //
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c 
b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
index f76937a..f6e65b2 100644
--- a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
@@ -366,19 +366,25 @@ AdjustQuestionValue (
 
 /**
   Get field info from numeric opcode.
 
   @param  OpCode            Pointer to the current input opcode.
+  @param  IntInput          Whether question shows with 
EFI_IFR_DISPLAY_INT_DEC type.
+  @param  QuestionValue     Input question value, with EFI_HII_VALUE type.
+  @param  Value             Return question value, always return UINT64 type.
   @param  Minimum           The minimum size info for this opcode.
   @param  Maximum           The maximum size info for this opcode.
   @param  Step              The step size info for this opcode.
   @param  StorageWidth      The storage width info for this opcode.
 
 **/
 VOID
 GetValueFromNum (
   IN  EFI_IFR_OP_HEADER     *OpCode,
+  IN  BOOLEAN               IntInput,
+  IN  EFI_HII_VALUE         *QuestionValue,
+  OUT UINT64                *Value,
   OUT UINT64                *Minimum,
   OUT UINT64                *Maximum,
   OUT UINT64                *Step,
   OUT UINT16                *StorageWidth
 )
@@ -387,33 +393,61 @@ GetValueFromNum (
 
   NumericOp = (EFI_IFR_NUMERIC *) OpCode;
   
   switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {
   case EFI_IFR_NUMERIC_SIZE_1:
-    *Minimum = NumericOp->data.u8.MinValue;
-    *Maximum = NumericOp->data.u8.MaxValue;
+    if (IntInput) {
+      *Minimum = (INT64) (INT8) NumericOp->data.u8.MinValue;
+      *Maximum = (INT64) (INT8) NumericOp->data.u8.MaxValue;
+      *Value   = (INT64) (INT8) QuestionValue->Value.u8;
+    } else {
+      *Minimum = NumericOp->data.u8.MinValue;
+      *Maximum = NumericOp->data.u8.MaxValue;
+      *Value   = QuestionValue->Value.u8;
+    }
     *Step    = NumericOp->data.u8.Step;
     *StorageWidth = (UINT16) sizeof (UINT8);
     break;
   
   case EFI_IFR_NUMERIC_SIZE_2:
-    *Minimum = NumericOp->data.u16.MinValue;
-    *Maximum = NumericOp->data.u16.MaxValue;
+    if (IntInput) {
+      *Minimum = (INT64) (INT16) NumericOp->data.u16.MinValue;
+      *Maximum = (INT64) (INT16) NumericOp->data.u16.MaxValue;
+      *Value   = (INT64) (INT16) QuestionValue->Value.u16;
+    } else {
+      *Minimum = NumericOp->data.u16.MinValue;
+      *Maximum = NumericOp->data.u16.MaxValue;
+      *Value   = QuestionValue->Value.u16;
+    }
     *Step    = NumericOp->data.u16.Step;
     *StorageWidth = (UINT16) sizeof (UINT16);
     break;
   
   case EFI_IFR_NUMERIC_SIZE_4:
-    *Minimum = NumericOp->data.u32.MinValue;
-    *Maximum = NumericOp->data.u32.MaxValue;
+    if (IntInput) {
+      *Minimum = (INT64) (INT32) NumericOp->data.u32.MinValue;
+      *Maximum = (INT64) (INT32) NumericOp->data.u32.MaxValue;
+      *Value   = (INT64) (INT32) QuestionValue->Value.u32;
+    } else {
+      *Minimum = NumericOp->data.u32.MinValue;
+      *Maximum = NumericOp->data.u32.MaxValue;
+      *Value   = QuestionValue->Value.u32;
+    }
     *Step    = NumericOp->data.u32.Step;
     *StorageWidth = (UINT16) sizeof (UINT32);
     break;
   
   case EFI_IFR_NUMERIC_SIZE_8:
-    *Minimum = NumericOp->data.u64.MinValue;
-    *Maximum = NumericOp->data.u64.MaxValue;
+    if (IntInput) {
+      *Minimum = (INT64) NumericOp->data.u64.MinValue;
+      *Maximum = (INT64) NumericOp->data.u64.MaxValue;
+      *Value   = (INT64) QuestionValue->Value.u64;
+    } else {
+      *Minimum = NumericOp->data.u64.MinValue;
+      *Maximum = NumericOp->data.u64.MaxValue;
+      *Value   = QuestionValue->Value.u64;
+    }
     *Step    = NumericOp->data.u64.Step;
     *StorageWidth = (UINT16) sizeof (UINT64);
     break;
   
   default:
@@ -446,10 +480,13 @@ GetNumericInput (
   UINT64                  PreviousNumber[MAX_NUMERIC_INPUT_WIDTH - 3];
   UINTN                   Count;
   UINTN                   Loop;
   BOOLEAN                 ManualInput;
   BOOLEAN                 HexInput;
+  BOOLEAN                 IntInput;
+  BOOLEAN                 Negative;
+  BOOLEAN                 ValidateFail;
   BOOLEAN                 DateOrTime;
   UINTN                   InputWidth;
   UINT64                  EditValue;
   UINT64                  Step;
   UINT64                  Minimum;
@@ -470,10 +507,14 @@ GetNumericInput (
   Digital           = 0;
   StorageWidth      = 0;
   Minimum           = 0;
   Maximum           = 0;
   NumericOp         = NULL;
+  IntInput          = FALSE;
+  HexInput          = FALSE;
+  Negative          = FALSE;
+  ValidateFail      = FALSE;
 
   Question      = MenuOption->ThisTag;
   QuestionValue = &Question->CurrentValue;
 
   //
@@ -566,20 +607,23 @@ GetNumericInput (
       break;
     }
   } else {
     ASSERT (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP);
     NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;
-    GetValueFromNum(Question->OpCode, &Minimum, &Maximum, &Step, 
&StorageWidth);
-    EditValue = QuestionValue->Value.u64;
+    GetValueFromNum(Question->OpCode, (NumericOp->Flags & 
+ EFI_IFR_DISPLAY) == 0, QuestionValue, &EditValue, &Minimum, &Maximum, 
+ &Step, &StorageWidth);
     EraseLen  = gOptionBlockWidth;
   }
 
-  if ((Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL) 
&&
-      ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
-    HexInput = TRUE;
-  } else {
-    HexInput = FALSE;
+  if ((Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL)) 
{
+    if ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX){
+      HexInput = TRUE;
+    } else if ((NumericOp->Flags & EFI_IFR_DISPLAY) == 0){
+      //
+      // Display with EFI_IFR_DISPLAY_INT_DEC type. Support negative number.
+      //
+      IntInput = TRUE;
+    }
   }
 
   //
   // Enter from "Enter" input, clear the old word showing.
   //
@@ -607,10 +651,17 @@ GetNumericInput (
 
         default:
           InputWidth = 0;
           break;
         }
+
+        if (IntInput) {
+          //
+          // Support an extra '-' for negative number.
+          //
+          InputWidth += 1;
+        }
       }
 
       InputText[0] = LEFT_NUMERIC_DELIMITER;
       SetUnicodeMem (InputText + 1, InputWidth, L' ');
       ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH); @@ -689,17 +740,31 @@ 
GetNumericInput (
 TheKey2:
     switch (Key.UnicodeChar) {
 
     case '+':
     case '-':
-      if (Key.UnicodeChar == '+') {
-        Key.ScanCode = SCAN_RIGHT;
+      if (ManualInput && IntInput) {
+        //
+        // In Manual input mode, check whether input the negative flag.
+        //
+        if (Key.UnicodeChar == '-') {
+          if (Negative) {
+            break;
+          }
+          Negative = TRUE;
+          PrintCharAt (Column++, Row, Key.UnicodeChar);
+        }
       } else {
-        Key.ScanCode = SCAN_LEFT;
+        if (Key.UnicodeChar == '+') {
+          Key.ScanCode = SCAN_RIGHT;
+        } else {
+          Key.ScanCode = SCAN_LEFT;
+        }
+        Key.UnicodeChar = CHAR_NULL;
+        goto TheKey2;
       }
-      Key.UnicodeChar = CHAR_NULL;
-      goto TheKey2;
+      break;
 
     case CHAR_NULL:
       switch (Key.ScanCode) {
       case SCAN_LEFT:
       case SCAN_RIGHT:
@@ -713,24 +778,44 @@ TheKey2:
           gDirection = SCAN_DOWN;
         }
 
         if ((Step != 0) && !ManualInput) {
           if (Key.ScanCode == SCAN_LEFT) {
-            if (EditValue >= Minimum + Step) {
-              EditValue = EditValue - Step;
-            } else if (EditValue > Minimum){
-              EditValue = Minimum;
+            if (IntInput) {
+              if ((INT64) EditValue >= (INT64) Minimum + (INT64) Step) {
+                EditValue = EditValue - Step;
+              } else if ((INT64) EditValue > (INT64) Minimum){
+                EditValue = Minimum;
+              } else {
+                EditValue = Maximum;
+              }
             } else {
-              EditValue = Maximum;
+              if (EditValue >= Minimum + Step) {
+                EditValue = EditValue - Step;
+              } else if (EditValue > Minimum){
+                EditValue = Minimum;
+              } else {
+                EditValue = Maximum;
+              }
             }
           } else if (Key.ScanCode == SCAN_RIGHT) {
-            if (EditValue + Step <= Maximum) {
-              EditValue = EditValue + Step;
-            } else if (EditValue < Maximum) {
-              EditValue = Maximum;
+            if (IntInput) {
+              if ((INT64) EditValue + (INT64) Step <= (INT64) Maximum) {
+                EditValue = EditValue + Step;
+              } else if ((INT64) EditValue < (INT64) Maximum) {
+                EditValue = Maximum;
+              } else {
+                EditValue = Minimum;
+              }
             } else {
-              EditValue = Minimum;
+              if (EditValue + Step <= Maximum) {
+                EditValue = EditValue + Step;
+              } else if (EditValue < Maximum) {
+                EditValue = Maximum;
+              } else {
+                EditValue = Minimum;
+              }
             }
           }
 
           ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
           if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { @@ -806,17 
+891,28 @@ EnterCarriageReturn:
 
     case CHAR_CARRIAGE_RETURN:
       //
       // Validate input value with Minimum value.
       //
-      if (EditValue < Minimum) {
+      ValidateFail = FALSE;
+      if (IntInput) {
+        if (Negative) {
+          ValidateFail = (INT64) EditValue > (INT64) Maximum ? TRUE : FALSE;
+        } else {
+          ValidateFail = (INT64) EditValue < (INT64) Minimum ? TRUE : FALSE;
+        }
+
+        if (ValidateFail) {
+          UpdateStatusBar (INPUT_ERROR, TRUE);
+          break;
+        }
+      } else if (EditValue < Minimum) {
         UpdateStatusBar (INPUT_ERROR, TRUE);
         break;
-      } else {
-        UpdateStatusBar (INPUT_ERROR, FALSE);
       }
-      
+
+      UpdateStatusBar (INPUT_ERROR, FALSE);
       CopyMem (&gUserInput->InputValue, &Question->CurrentValue, sizeof 
(EFI_HII_VALUE));
       QuestionValue = &gUserInput->InputValue;
       //
       // Store Edit value back to Question
       //
@@ -920,30 +1016,56 @@ EnterCarriageReturn:
         // Someone typed something valid!
         //
         if (Count != 0) {
           if (HexInput) {
             EditValue = LShiftU64 (EditValue, 4) + Digital;
+          } else if (IntInput && Negative) {
+            //
+            // Save the negative number.
+            //
+            EditValue = ~(MultU64x32 (~(EditValue - 1), 10) + 
+ (Key.UnicodeChar - L'0')) + 1;
           } else {
             EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');
           }
         } else {
           if (HexInput) {
             EditValue = Digital;
+          } else if (IntInput && Negative) {
+            //
+            // Save the negative number.
+            //
+            EditValue = ~(Key.UnicodeChar - L'0') + 1;
           } else {
             EditValue = Key.UnicodeChar - L'0';
           }
         }
 
-        if (EditValue > Maximum) {
-          UpdateStatusBar (INPUT_ERROR, TRUE);
-          ASSERT (Count < sizeof (PreviousNumber) / sizeof 
(PreviousNumber[0]));
-          EditValue = PreviousNumber[Count];
-          break;
+        if (IntInput) {
+          ValidateFail = FALSE;
+          if (Negative) {
+            ValidateFail = (INT64) EditValue < (INT64) Minimum ? TRUE : FALSE;
+          } else {
+            ValidateFail = (INT64) EditValue > (INT64) Maximum ? TRUE : FALSE;
+          }
+
+          if (ValidateFail) {
+            UpdateStatusBar (INPUT_ERROR, TRUE);
+            ASSERT (Count < sizeof (PreviousNumber) / sizeof 
(PreviousNumber[0]));
+            EditValue = PreviousNumber[Count];
+            break;
+          }
         } else {
-          UpdateStatusBar (INPUT_ERROR, FALSE);
+          if (EditValue > Maximum) {
+            UpdateStatusBar (INPUT_ERROR, TRUE);
+            ASSERT (Count < sizeof (PreviousNumber) / sizeof 
(PreviousNumber[0]));
+            EditValue = PreviousNumber[Count];
+            break;
+          }
         }
 
+        UpdateStatusBar (INPUT_ERROR, FALSE);
+
         Count++;
         ASSERT (Count < (sizeof (PreviousNumber) / sizeof 
(PreviousNumber[0])));
         PreviousNumber[Count] = EditValue;
 
         gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); 
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c 
b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
index 9646823..7a4b056 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -3937,13 +3937,47 @@ GetQuestionDefault (
   switch (Question->Operand) {
   case EFI_IFR_NUMERIC_OP:
     //
     // Take minimum value as numeric default value
     //
-    if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > 
Question->Maximum)) {
-      HiiValue->Value.u64 = Question->Minimum;
-      Status = EFI_SUCCESS;
+    if ((Question->Flags & EFI_IFR_DISPLAY) == 0) {
+      //
+      // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
+      //
+      switch (Question->Flags & EFI_IFR_NUMERIC_SIZE) {
+      case EFI_IFR_NUMERIC_SIZE_1:
+        if (((INT8) HiiValue->Value.u8 < (INT8) Question->Minimum) || ((INT8) 
HiiValue->Value.u8 > (INT8) Question->Maximum)) {
+          HiiValue->Value.u8 = (UINT8) Question->Minimum;
+          Status = EFI_SUCCESS;
+        }
+        break;
+      case EFI_IFR_NUMERIC_SIZE_2:
+        if (((INT16) HiiValue->Value.u16 < (INT16) Question->Minimum) || 
((INT16) HiiValue->Value.u16 > (INT16) Question->Maximum)) {
+          HiiValue->Value.u16 = (UINT16) Question->Minimum;
+          Status = EFI_SUCCESS;
+        }
+        break;
+      case EFI_IFR_NUMERIC_SIZE_4:
+        if (((INT32) HiiValue->Value.u32 < (INT32) Question->Minimum) || 
((INT32) HiiValue->Value.u32 > (INT32) Question->Maximum)) {
+          HiiValue->Value.u32 = (UINT32) Question->Minimum;
+          Status = EFI_SUCCESS;
+        }
+        break;
+      case EFI_IFR_NUMERIC_SIZE_8:
+        if (((INT64) HiiValue->Value.u64 < (INT64) Question->Minimum) || 
((INT64) HiiValue->Value.u64 > (INT64) Question->Maximum)) {
+          HiiValue->Value.u64 = Question->Minimum;
+          Status = EFI_SUCCESS;
+        }
+        break;
+      default:
+        break;     
+      }
+    } else {
+      if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > 
Question->Maximum)) {
+        HiiValue->Value.u64 = Question->Minimum;
+        Status = EFI_SUCCESS;
+      }
     }
     break;
 
   case EFI_IFR_ONE_OF_OP:
     //
--
1.9.5.msysgit.1


------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud 
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to