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