From afc9bf796cbf82f1a9722cd1d6e785bb58b078b9 Mon Sep 17 00:00:00 2001 From: Eric Dong Date: Wed, 6 May 2015 12:30:13 +0000 Subject: 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 Reviewed-by: Liming Gao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17345 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Library/UefiHiiLib/HiiLib.c | 100 +++++++--- .../Universal/DisplayEngineDxe/InputHandler.c | 217 +++++++++++++++++---- MdeModulePkg/Universal/SetupBrowserDxe/Setup.c | 40 +++- 3 files changed, 282 insertions(+), 75 deletions(-) diff --git a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c index 09f1ff7545..7ae5c4c077 100644 --- a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c +++ b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c @@ -1298,41 +1298,77 @@ ValidateQuestionFromVfr ( 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: // diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c index f76937a442..4a347a9b65 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c @@ -368,6 +368,9 @@ 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. @@ -377,6 +380,9 @@ AdjustQuestionValue ( 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, @@ -389,29 +395,57 @@ GetValueFromNum ( 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; @@ -448,6 +482,9 @@ GetNumericInput ( UINTN Loop; BOOLEAN ManualInput; BOOLEAN HexInput; + BOOLEAN IntInput; + BOOLEAN Negative; + BOOLEAN ValidateFail; BOOLEAN DateOrTime; UINTN InputWidth; UINT64 EditValue; @@ -472,6 +509,10 @@ GetNumericInput ( Minimum = 0; Maximum = 0; NumericOp = NULL; + IntInput = FALSE; + HexInput = FALSE; + Negative = FALSE; + ValidateFail = FALSE; Question = MenuOption->ThisTag; QuestionValue = &Question->CurrentValue; @@ -568,16 +609,19 @@ GetNumericInput ( } 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; + } } // @@ -609,6 +653,13 @@ GetNumericInput ( InputWidth = 0; break; } + + if (IntInput) { + // + // Support an extra '-' for negative number. + // + InputWidth += 1; + } } InputText[0] = LEFT_NUMERIC_DELIMITER; @@ -691,13 +742,27 @@ TheKey2: 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) { @@ -715,20 +780,40 @@ TheKey2: 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; + } } } @@ -808,13 +893,29 @@ EnterCarriageReturn: // // Validate input value with Minimum value. // - if (EditValue < Minimum) { + ValidateFail = FALSE; + if (IntInput) { + // + // After user input Enter, need to check whether the input value. + // If input a negative value, should compare with maximum value. + // else compare with the minimum value. + // + 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; // @@ -877,6 +978,11 @@ EnterCarriageReturn: case CHAR_BACKSPACE: if (ManualInput) { if (Count == 0) { + if (Negative) { + Negative = FALSE; + Column--; + PrintStringAt (Column, Row, L" "); + } break; } // @@ -922,26 +1028,57 @@ EnterCarriageReturn: 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; + // + // When user input a new value, should check the current value. + // If user input a negative value, should compare it with minimum + // value, else compare it with maximum value. + // + 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; diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index 5cf13cec59..ea9205a252 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -3944,9 +3944,43 @@ GetQuestionDefault ( // // 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; -- cgit v1.2.3