1560 lines
44 KiB
C
1560 lines
44 KiB
C
/** @file
|
|
Implement H2O display engine related functions.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2015 - 2020, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "H2ODisplayEngineLibInternal.h"
|
|
#include <Library/DxeOemSvcKernelLib.h>
|
|
#include <Guid/ZeroGuid.h>
|
|
|
|
|
|
/**
|
|
Check if the input character is a decimal character
|
|
|
|
@param[in] UnicodeChar Unicode character
|
|
|
|
@retval TRUE The input character is a decimal character
|
|
@retval FALSE The input character is not a decimal character
|
|
**/
|
|
BOOLEAN
|
|
IsDecChar (
|
|
IN CHAR16 UnicodeChar
|
|
)
|
|
{
|
|
return (BOOLEAN) (UnicodeChar >= '0' && UnicodeChar <= '9');
|
|
}
|
|
|
|
/**
|
|
Check if the input character is a hexadecimal character
|
|
|
|
@param[in] UnicodeChar Unicode character
|
|
|
|
@retval TRUE The input character is a hexadecimal character
|
|
@retval FALSE The input character is not a hexadecimal character
|
|
**/
|
|
BOOLEAN
|
|
IsHexChar (
|
|
IN CHAR16 UnicodeChar
|
|
)
|
|
{
|
|
if ((UnicodeChar >= '0' && UnicodeChar <= '9') ||
|
|
(UnicodeChar >= 'a' && UnicodeChar <= 'f') ||
|
|
(UnicodeChar >= 'A' && UnicodeChar <= 'F')) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check if the input character is a visible character
|
|
|
|
@param[in] UnicodeChar Unicode character
|
|
|
|
@retval TRUE The input character is a visible character
|
|
@retval FALSE The input character is not a visible character
|
|
**/
|
|
BOOLEAN
|
|
IsVisibleChar (
|
|
IN CHAR16 UnicodeChar
|
|
)
|
|
{
|
|
return (BOOLEAN) (UnicodeChar >= ' ' && UnicodeChar <= '~');
|
|
}
|
|
|
|
/**
|
|
Check if the input string is a hexadecimal string
|
|
|
|
@param[in] Str Unicode string
|
|
|
|
@retval TRUE The input string is a hexadecimal string
|
|
@retval FALSE The input string is not a hexadecimal string
|
|
**/
|
|
BOOLEAN
|
|
IsHexString (
|
|
IN CHAR16 *Str
|
|
)
|
|
{
|
|
//
|
|
// skip preceeding white space
|
|
//
|
|
while ((*Str != 0) && *Str == L' ') {
|
|
Str++;
|
|
}
|
|
//
|
|
// skip preceeding zeros
|
|
//
|
|
while ((*Str != 0) && *Str == L'0') {
|
|
Str++;
|
|
}
|
|
|
|
return (BOOLEAN) (*Str == L'x' || *Str == L'X');
|
|
}
|
|
|
|
/**
|
|
Check if the input year value is leap year
|
|
|
|
@param[in] Year Year value
|
|
|
|
@retval TRUE The input year value is leap year
|
|
@retval FALSE The input year value is not leap year
|
|
**/
|
|
BOOLEAN
|
|
IsLeapYear (
|
|
IN UINT16 Year
|
|
)
|
|
{
|
|
return (BOOLEAN) ((Year%4 == 0) && ((Year%100 != 0) || (Year%400 == 0)));
|
|
}
|
|
|
|
/**
|
|
Check if the input time is valid
|
|
|
|
@param[in] EfiTime Pointer to EFI time
|
|
|
|
@retval TRUE The input time is valid
|
|
@retval FALSE The input time is not valid
|
|
**/
|
|
BOOLEAN
|
|
IsTimeValid (
|
|
IN EFI_TIME *EfiTime
|
|
)
|
|
{
|
|
if (EfiTime == NULL || (EfiTime->Hour > 23) || (EfiTime->Minute > 59) || (EfiTime->Second > 59)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Check if the input day is valid
|
|
|
|
@param[in] EfiTime Pointer to EFI time
|
|
|
|
@retval TRUE The input day is valid
|
|
@retval FALSE The input day is not valid
|
|
**/
|
|
BOOLEAN
|
|
IsDayValid (
|
|
IN EFI_TIME *EfiTime
|
|
)
|
|
{
|
|
UINT8 DayOfMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
|
|
|
|
if (EfiTime == NULL ||
|
|
(EfiTime->Day < 1) ||
|
|
(EfiTime->Month < 1) ||
|
|
(EfiTime->Month > 12) ||
|
|
(EfiTime->Day > DayOfMonth[EfiTime->Month - 1]) ||
|
|
(EfiTime->Month == 2 && (!IsLeapYear (EfiTime->Year) && EfiTime->Day > 28)) ||
|
|
(EfiTime->Year < PcdGet16 (PcdRealTimeClockYearMin) || EfiTime->Year > PcdGet16 (PcdRealTimeClockYearMax))) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Check if current page is root page
|
|
|
|
@retval TRUE The current page is root page
|
|
@retval FALSE The current page is not root page, fail to locate protocol, current page pointer is NULL or
|
|
fail to get setup menu.
|
|
**/
|
|
BOOLEAN
|
|
IsRootPage (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
H2O_FORM_BROWSER_PROTOCOL *FBProtocol;
|
|
SETUP_MENU_INFO CurrentSetupMenuInfo;
|
|
|
|
Status = gBS->LocateProtocol (&gH2OFormBrowserProtocolGuid, NULL, (VOID **) &FBProtocol);
|
|
if (EFI_ERROR (Status) || FBProtocol->CurrentP == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
Status = GetSetupMenuInfoByPage (FBProtocol->CurrentP, &CurrentSetupMenuInfo);
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return (BOOLEAN) (CurrentSetupMenuInfo.PageId == FBProtocol->CurrentP->PageId);
|
|
}
|
|
|
|
/**
|
|
Check if the edit value is valid or not.
|
|
The valid condition is that the edit value or possible range overlap on [MinValue, MaxValue].
|
|
|
|
@param[in] EditValue Edit value
|
|
@param[in] MinValue Minimum value
|
|
@param[in] MaxValue Maximum value
|
|
@param[in] IsHex Flag to determine that the edit value is hex
|
|
|
|
@retval TRUE The edit value is valid
|
|
@retval FALSE The edit value is not valid
|
|
**/
|
|
BOOLEAN
|
|
IsEditValueValid (
|
|
IN UINT64 EditValue,
|
|
IN UINT64 MinValue,
|
|
IN UINT64 MaxValue,
|
|
IN BOOLEAN IsHex
|
|
)
|
|
{
|
|
UINT32 Base;
|
|
UINT64 PossibleRangeMin;
|
|
UINT64 PossibleRangeMax;
|
|
UINT64 Limit;
|
|
|
|
//
|
|
// First, check if the edit value overlap on [MinValue, MaxValue]
|
|
//
|
|
if (EditValue == 0 || IN_RANGE (EditValue, MinValue, MaxValue)) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Second, check if the passible range of edit value overlap on [MinValue, MaxValue]
|
|
// Keep possible range be multiplied by base until min value of possible range exceed MaxValue.
|
|
// For example: If [MinValue, MaxValue] is [2, 200], possible range will be [10, 19] and [100, 199] when edit value is 1.
|
|
//
|
|
if (EditValue > MaxValue) {
|
|
return FALSE;
|
|
}
|
|
|
|
Base = IsHex ? 16 : 10;
|
|
Limit = DivU64x32 ((UINT64) -1, Base);
|
|
PossibleRangeMin = EditValue;
|
|
PossibleRangeMax = EditValue;
|
|
|
|
while (PossibleRangeMin <= Limit) {
|
|
PossibleRangeMin = MultU64x32 (PossibleRangeMin, Base);
|
|
PossibleRangeMax = MultU64x32 (PossibleRangeMax, Base) + (Base - 1);
|
|
if (PossibleRangeMin > MaxValue) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (IS_OVERLAP (PossibleRangeMin, PossibleRangeMax, MinValue, MaxValue)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check if the value string is valid or not.
|
|
|
|
@param[in] ValueStr Input value string for being checked
|
|
@param[in] IsHex Is hex number or not
|
|
|
|
@retval TRUE The value string is valid
|
|
@retval FALSE The value string is invalid
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
IsValidValueStr (
|
|
IN CHAR16 *ValueStr,
|
|
IN BOOLEAN IsHex
|
|
)
|
|
{
|
|
if (ValueStr == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
while (*ValueStr != CHAR_NULL) {
|
|
if ((IsHex && !IsHexChar (*ValueStr)) ||
|
|
(!IsHex && !IsDecChar (*ValueStr))) {
|
|
return FALSE;
|
|
}
|
|
ValueStr++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Convert question HII value to INT64 value based on numeric buffer size determined by opcode flag.
|
|
|
|
@param[in] NumericFlags Numeric opcode flag
|
|
@param[in] Value Question HII value
|
|
|
|
@return Numeric value in INT64 format
|
|
**/
|
|
STATIC
|
|
INT64
|
|
IfrNumericConvertValueToInt64 (
|
|
IN UINT8 NumericFlags,
|
|
IN UINT64 Value
|
|
)
|
|
{
|
|
switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_1:
|
|
return (INT64) ((INT8) ((UINT8) Value));
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_2:
|
|
return (INT64) ((INT16) ((UINT16) Value));
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_4:
|
|
return (INT64) ((INT32) ((UINT32) Value));
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_8:
|
|
default:
|
|
return (INT64) Value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Convert INT64 value to question HII value based on numeric buffer size determined by opcode flag.
|
|
|
|
@param[in] NumericFlags Numeric opcode flag
|
|
@param[in] Int64Value Numeric value in INT64 format
|
|
|
|
@return Question HII value
|
|
**/
|
|
STATIC
|
|
UINT64
|
|
IfrNumericConvertInt64ToValue (
|
|
IN UINT8 NumericFlags,
|
|
IN INT64 Int64Value
|
|
)
|
|
{
|
|
switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_1:
|
|
return (UINT64) ((UINT8) ((INT8) Int64Value));
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_2:
|
|
return (UINT64) ((UINT16) ((INT16) Int64Value));
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_4:
|
|
return (UINT64) ((UINT32) ((INT32) Int64Value));
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_8:
|
|
default:
|
|
return (UINT64) Int64Value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Convert the numeric string to question HII value.
|
|
|
|
@param[in] NumericFlags Numeric opcode flags
|
|
@param[in] NumericStr Pointer to numeric string
|
|
|
|
@retval Question HII value in UINT64 format or 0 if input string pointer is NULL.
|
|
**/
|
|
UINT64
|
|
IfrNumericConvertStrToValue (
|
|
IN UINT8 NumericFlags,
|
|
IN CHAR16 *NumericStr
|
|
)
|
|
{
|
|
UINT64 Value;
|
|
|
|
if (NumericStr == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
while (*NumericStr != CHAR_NULL && *NumericStr == ' ') {
|
|
NumericStr++;
|
|
}
|
|
|
|
Value = 0;
|
|
switch (NumericFlags & EFI_IFR_DISPLAY) {
|
|
|
|
case EFI_IFR_DISPLAY_INT_DEC:
|
|
if (*NumericStr == '-') {
|
|
Value = StrDecimalToUint64 (NumericStr + 1);
|
|
|
|
switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_1:
|
|
Value = (UINT8) -((INT8) Value);
|
|
break;
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_2:
|
|
Value = (UINT16) -((INT16) Value);
|
|
break;
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_4:
|
|
Value = (UINT32) -((INT32) Value);
|
|
break;
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_8:
|
|
Value = (UINT64) -((INT64) Value);
|
|
break;
|
|
}
|
|
} else {
|
|
Value = StrDecimalToUint64 (NumericStr);
|
|
}
|
|
return Value;
|
|
|
|
case EFI_IFR_DISPLAY_UINT_DEC:
|
|
return StrDecimalToUint64 (NumericStr);
|
|
|
|
case EFI_IFR_DISPLAY_UINT_HEX:
|
|
return StrHexToUint64 (NumericStr);
|
|
}
|
|
|
|
return Value;
|
|
}
|
|
|
|
/**
|
|
Get numeric value size from numeric question flags.
|
|
|
|
@param[in] NumericFlags Numeric opcode flags
|
|
|
|
@return Numeric value size
|
|
**/
|
|
UINTN
|
|
IfrNumericGetValueSize (
|
|
IN UINT8 NumericFlags
|
|
)
|
|
{
|
|
switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_1:
|
|
return 1;
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_2:
|
|
return 2;
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_4:
|
|
return 4;
|
|
|
|
case EFI_IFR_NUMERIC_SIZE_8:
|
|
default:
|
|
return 8;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if the question HII value is in range [Minimum, Maximum] or not.
|
|
|
|
@param[in] NumericFlags Numeric opcode flags
|
|
@param[in] Value Question HII value
|
|
@param[in] Minimum Minimum value
|
|
@param[in] Maximum Maximum value
|
|
|
|
@retval TRUE The value is in range
|
|
@retval FALSE The value is not in range
|
|
**/
|
|
BOOLEAN
|
|
IfrNumericIsValueInRange (
|
|
IN UINT8 NumericFlags,
|
|
IN UINT64 Value,
|
|
IN UINT64 Minimum,
|
|
IN UINT64 Maximum
|
|
)
|
|
{
|
|
if ((NumericFlags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_INT_DEC) {
|
|
return IN_RANGE (IfrNumericConvertValueToInt64 (NumericFlags, Value),
|
|
IfrNumericConvertValueToInt64 (NumericFlags, Minimum),
|
|
IfrNumericConvertValueToInt64 (NumericFlags, Maximum));
|
|
} else {
|
|
return IN_RANGE (Value, Minimum, Maximum);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if the editing signed decimal string in is valid or not.
|
|
|
|
@param[in] EditStr Pointer to editing signed decimal string
|
|
@param[in] Minimum Minimum value
|
|
@param[in] Maximum Maximum value
|
|
|
|
@retval TRUE The editing string is in valid
|
|
@retval FALSE The editing string is not valid
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
IfrNumericIsEditSignedDecStrValid (
|
|
IN CHAR16 *EditStr,
|
|
IN INT64 Minimum,
|
|
IN INT64 Maximum
|
|
)
|
|
{
|
|
UINTN ValueStrLen;
|
|
CHAR16 ValueStr[22];
|
|
BOOLEAN IsNegative;
|
|
CHAR16 LastChar;
|
|
UINT64 Value;
|
|
UINT64 Min;
|
|
UINT64 Max;
|
|
|
|
if (EditStr == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Copy string without prefix space, minus char, prefix '0' and suffix space characters.
|
|
//
|
|
while (*EditStr == ' ') {
|
|
EditStr++;
|
|
}
|
|
if (*EditStr == '-') {
|
|
IsNegative = TRUE;
|
|
EditStr++;
|
|
} else {
|
|
IsNegative = FALSE;
|
|
}
|
|
while (*EditStr == '0') {
|
|
EditStr++;
|
|
}
|
|
|
|
for (ValueStrLen = StrLen (EditStr); ValueStrLen > 0 && EditStr[ValueStrLen - 1] == ' '; ValueStrLen--) {
|
|
}
|
|
if (ValueStrLen > 19) {
|
|
return FALSE;
|
|
}
|
|
StrnCpyS (ValueStr, ARRAY_SIZE(ValueStr), EditStr, ValueStrLen);
|
|
|
|
if (!IsValidValueStr (ValueStr, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (ValueStrLen == 19) {
|
|
//
|
|
// Because 19 digits value maybe make INT64 overlap
|
|
// use 18 digits to check the value whether overlap
|
|
//
|
|
LastChar = ValueStr[18];
|
|
ValueStr[18] = '\0';
|
|
Value = StrDecimalToUint64 (ValueStr);
|
|
ValueStr[18] = LastChar;
|
|
|
|
//
|
|
// INT64 maximum (minimum) value is 9223372036854775807 (-9223372036854775808).
|
|
// If 18 digits is larger than 9223372036854775801ull, user can not input any key.
|
|
// If 18 digits is equal to 9223372036854775801ull, user can not input larger than '7' and '8' for positive and negative value
|
|
//
|
|
if (Value > 922337203685477580ull) {
|
|
return FALSE;
|
|
}
|
|
if ((Value == 922337203685477580ull) &&
|
|
((!IsNegative && LastChar > '7') || (IsNegative && LastChar > '8'))) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
Value = StrDecimalToUint64 (ValueStr);
|
|
if (IsNegative) {
|
|
if (Minimum > 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
Max = (UINT64) (-Minimum);
|
|
Min = (UINT64) ((Maximum > 0) ? 0 : -Maximum);
|
|
} else {
|
|
if (Maximum < 0) {
|
|
return FALSE;
|
|
}
|
|
Max = (UINT64) (Maximum);
|
|
Min = (UINT64) ((Minimum < 0) ? 0 : Minimum);
|
|
}
|
|
|
|
return IsEditValueValid (Value, Min, Max, FALSE);
|
|
}
|
|
|
|
/**
|
|
Check if the editing unsigned decimal string in is valid or not.
|
|
|
|
@param[in] EditStr Pointer to editing unsigned decimal string
|
|
@param[in] Minimum Minimum value
|
|
@param[in] Maximum Maximum value
|
|
|
|
@retval TRUE The editing string is in valid
|
|
@retval FALSE The editing string is not valid
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
IfrNumericIsEditDecStrValid (
|
|
IN CHAR16 *EditStr,
|
|
IN UINT64 Minimum,
|
|
IN UINT64 Maximum
|
|
)
|
|
{
|
|
UINTN ValueStrLen;
|
|
CHAR16 ValueStr[22];
|
|
CHAR16 LastChar;
|
|
UINT64 Value;
|
|
|
|
if (EditStr == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Copy string without prefix space, prefix '0' and suffix space characters.
|
|
//
|
|
while (*EditStr == ' ' || *EditStr == '0') {
|
|
EditStr++;
|
|
}
|
|
|
|
for (ValueStrLen = StrLen (EditStr); ValueStrLen > 0 && EditStr[ValueStrLen - 1] == ' '; ValueStrLen--) {
|
|
}
|
|
if (ValueStrLen > 20) {
|
|
return FALSE;
|
|
}
|
|
StrnCpyS (ValueStr, ARRAY_SIZE(ValueStr), EditStr, ValueStrLen);
|
|
|
|
if (!IsValidValueStr (ValueStr, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (ValueStrLen == 20) {
|
|
//
|
|
// Because 20 digits value maybe make UINT64 overlap
|
|
// use 19 digits to check the value whether overlap
|
|
//
|
|
LastChar = ValueStr[19];
|
|
ValueStr[19] = '\0';
|
|
Value = StrDecimalToUint64 (ValueStr);
|
|
ValueStr[19] = LastChar;
|
|
|
|
//
|
|
// UINT64 maximum value is 18446744073709551615.
|
|
// If 19 digits is larger than 1844674407370955161ull,
|
|
// use can not input any key.
|
|
//
|
|
if (Value > 1844674407370955161ull) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// UINT64 maximum value is 18446744073709551615.
|
|
// If 19 digits is equal to 1844674407370955161ull,
|
|
// use can not input larger than '5' key
|
|
//
|
|
if ((Value == 1844674407370955161ull) && (LastChar > '5')) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
Value = StrDecimalToUint64 (ValueStr);
|
|
return IsEditValueValid (Value, Minimum, Maximum, FALSE);
|
|
}
|
|
|
|
/**
|
|
Check if the editing hex string in is valid or not.
|
|
|
|
@param[in] EditStr Pointer to editing hex string
|
|
@param[in] Minimum Minimum value
|
|
@param[in] Maximum Maximum value
|
|
|
|
@retval TRUE The editing string is in valid
|
|
@retval FALSE The editing string is not valid
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
IfrNumericIsEditHexStrValid (
|
|
IN CHAR16 *EditStr,
|
|
IN UINT64 Minimum,
|
|
IN UINT64 Maximum
|
|
)
|
|
{
|
|
UINTN ValueStrLen;
|
|
CHAR16 ValueStr[22];
|
|
UINT64 Value;
|
|
|
|
if (EditStr == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Copy string without prefix space, prefix '0', prefix '0x' and suffix space characters.
|
|
//
|
|
while (*EditStr == ' ') {
|
|
EditStr++;
|
|
}
|
|
while (EditStr[0] == '0' && EditStr[1] == '0') {
|
|
EditStr++;
|
|
}
|
|
if (EditStr[0] == '0' && (EditStr[1] == 'x' || EditStr[1] == 'X')) {
|
|
EditStr += 2;
|
|
}
|
|
while (*EditStr == '0') {
|
|
EditStr++;
|
|
}
|
|
|
|
for (ValueStrLen = StrLen (EditStr); ValueStrLen > 0 && EditStr[ValueStrLen - 1] == ' '; ValueStrLen--) {
|
|
}
|
|
if (ValueStrLen > 16) {
|
|
return FALSE;
|
|
}
|
|
StrnCpyS (ValueStr, ARRAY_SIZE(ValueStr), EditStr, ValueStrLen);
|
|
|
|
if (!IsValidValueStr (ValueStr, TRUE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Value = StrHexToUint64 (ValueStr);
|
|
return IsEditValueValid (Value, Minimum, Maximum, TRUE);
|
|
}
|
|
|
|
/**
|
|
Check if the editing numeric string is valid or not.
|
|
|
|
@param[in] NumericFlags Numeric opcode flags
|
|
@param[in] EditStr Pointer to editing numeric string
|
|
@param[in] Minimum Minimum value
|
|
@param[in] Maximum Maximum value
|
|
|
|
@retval TRUE The editing string is in valid
|
|
@retval FALSE The editing string is not valid
|
|
**/
|
|
BOOLEAN
|
|
IfrNumericIsEditStrValid (
|
|
IN UINT8 NumericFlags,
|
|
IN CHAR16 *EditStr,
|
|
IN UINT64 Minimum,
|
|
IN UINT64 Maximum
|
|
)
|
|
{
|
|
switch (NumericFlags & EFI_IFR_DISPLAY) {
|
|
|
|
case EFI_IFR_DISPLAY_INT_DEC:
|
|
return IfrNumericIsEditSignedDecStrValid (
|
|
EditStr,
|
|
IfrNumericConvertValueToInt64(NumericFlags, Minimum),
|
|
IfrNumericConvertValueToInt64(NumericFlags, Maximum)
|
|
);
|
|
|
|
case EFI_IFR_DISPLAY_UINT_DEC:
|
|
return IfrNumericIsEditDecStrValid (EditStr, Minimum, Maximum);
|
|
|
|
case EFI_IFR_DISPLAY_UINT_HEX:
|
|
default:
|
|
return IfrNumericIsEditHexStrValid (EditStr, Minimum, Maximum);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if the numeric value string is empty without any value char or not.
|
|
|
|
@param[in] NumericFlags Numeric opcode flags
|
|
@param[in] ValueStr Pointer to numeric value string
|
|
|
|
@retval TRUE The value string is empty
|
|
@retval FALSE The value string is not empty
|
|
**/
|
|
BOOLEAN
|
|
IfrNumericIsEmptyStr (
|
|
IN UINT8 NumericFlags,
|
|
IN CHAR16 *ValueStr
|
|
)
|
|
{
|
|
CHAR16 *StrPtr;
|
|
|
|
if (ValueStr == NULL || *ValueStr == CHAR_NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
while (*ValueStr == ' ') {
|
|
ValueStr++;
|
|
}
|
|
|
|
switch (NumericFlags & EFI_IFR_DISPLAY) {
|
|
|
|
case EFI_IFR_DISPLAY_INT_DEC:
|
|
if (*ValueStr == '-') {
|
|
ValueStr++;
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_DISPLAY_UINT_DEC:
|
|
break;
|
|
|
|
case EFI_IFR_DISPLAY_UINT_HEX:
|
|
default:
|
|
StrPtr = ValueStr;
|
|
while (StrPtr[0] == '0' && StrPtr[1] == '0') {
|
|
StrPtr++;
|
|
}
|
|
if (StrPtr[0] == '0' && (StrPtr[1] == 'x' || StrPtr[1] == 'X')) {
|
|
ValueStr = StrPtr + 2;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return (BOOLEAN) (*ValueStr == CHAR_NULL);
|
|
}
|
|
|
|
/**
|
|
Get formatted number string.
|
|
|
|
@param[in] Question Pointer to H2O form browser question
|
|
|
|
@retval Formatted number string or NULL if input question pointer is NULL.
|
|
**/
|
|
CHAR16 *
|
|
IfrNumericPrintFormattedNumber (
|
|
IN H2O_FORM_BROWSER_Q *Question
|
|
)
|
|
{
|
|
INT64 Value;
|
|
|
|
if (Question == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
switch (Question->Flags & EFI_IFR_DISPLAY) {
|
|
|
|
case EFI_IFR_DISPLAY_INT_DEC:
|
|
Value = IfrNumericConvertValueToInt64 (Question->Flags, Question->HiiValue.Value.u64);
|
|
if (Value < 0) {
|
|
Value = -Value;
|
|
return CatSPrint (NULL, L"-%lu", Value);
|
|
} else {
|
|
return CatSPrint (NULL, L"%lu", Value);
|
|
}
|
|
|
|
case EFI_IFR_DISPLAY_UINT_DEC:
|
|
return CatSPrint (NULL, L"%lu", Question->HiiValue.Value.u64);
|
|
|
|
case EFI_IFR_DISPLAY_UINT_HEX:
|
|
default:
|
|
return CatSPrint (NULL, L"0x%lx", Question->HiiValue.Value.u64);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Transfer EFI time to EFI HII value
|
|
|
|
@param[in] IsDate If true, transfer to HII value with date type. Otherwise, transfer to HII value with time type.
|
|
@param[in] EfiTime Pointer to EFI time
|
|
@param[out] HiiValue Pointer to EFI HII value
|
|
|
|
@retval EFI_SUCCESS Transfer EFI time to EFI HII value successfully
|
|
@retval EFI_INVALID_PARAMETER EfiTime or HiiValue is NULL
|
|
**/
|
|
EFI_STATUS
|
|
TransferEfiTimeToHiiValue (
|
|
IN BOOLEAN IsDate,
|
|
IN EFI_TIME *EfiTime,
|
|
OUT EFI_HII_VALUE *HiiValue
|
|
)
|
|
{
|
|
if (EfiTime == NULL || HiiValue == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
ZeroMem (HiiValue, sizeof(EFI_HII_VALUE));
|
|
if (IsDate) {
|
|
HiiValue->Type = EFI_IFR_TYPE_DATE;
|
|
HiiValue->Value.date.Year = EfiTime->Year;
|
|
HiiValue->Value.date.Month = EfiTime->Month;
|
|
HiiValue->Value.date.Day = EfiTime->Day;
|
|
} else {
|
|
HiiValue->Type = EFI_IFR_TYPE_TIME;
|
|
HiiValue->Value.time.Hour = EfiTime->Hour;
|
|
HiiValue->Value.time.Minute = EfiTime->Minute;
|
|
HiiValue->Value.time.Second = EfiTime->Second;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Transfer EFI HII value to EFI time
|
|
|
|
@param[in] HiiValue Pointer to EFI HII value
|
|
@param[out] EfiTime Pointer to EFI time
|
|
|
|
@retval EFI_SUCCESS Transfer EFI HII value to EFI time successfully
|
|
@retval EFI_INVALID_PARAMETER EfiTime or HiiValue is NULL or EFI HII value type is not date or time
|
|
**/
|
|
EFI_STATUS
|
|
TransferHiiValueToEfiTime (
|
|
IN EFI_HII_VALUE *HiiValue,
|
|
OUT EFI_TIME *EfiTime
|
|
)
|
|
{
|
|
if (EfiTime == NULL || HiiValue == NULL || (HiiValue->Type != EFI_IFR_TYPE_DATE && HiiValue->Type != EFI_IFR_TYPE_TIME)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (HiiValue->Type == EFI_IFR_TYPE_DATE) {
|
|
EfiTime->Year = HiiValue->Value.date.Year;
|
|
EfiTime->Month = HiiValue->Value.date.Month;
|
|
EfiTime->Day = HiiValue->Value.date.Day;
|
|
} else {
|
|
EfiTime->Hour = HiiValue->Value.time.Hour;
|
|
EfiTime->Minute = HiiValue->Value.time.Minute;
|
|
EfiTime->Second = HiiValue->Value.time.Second;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get next date or time value
|
|
|
|
@param[in] DateTimeItem Date time item
|
|
@param[in] Increasement If true, get next value. Otherwise, get previous value
|
|
@param[in, out] EfiTime Pointer to EFI time
|
|
|
|
@retval EFI_SUCCESS Get next date or time value successfully
|
|
@retval EFI_INVALID_PARAMETER EfiTime is NULL or DateTimeItem is invalid
|
|
@retval EFI_ABORTED Fail to get next date value
|
|
**/
|
|
EFI_STATUS
|
|
GetNextDateTimeValue (
|
|
IN H2O_DATE_TIME_ITEM DateTimeItem,
|
|
IN BOOLEAN Increasement,
|
|
IN OUT EFI_TIME *EfiTime
|
|
)
|
|
{
|
|
UINT8 DayOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
UINT8 MonthIndex;
|
|
EFI_TIME EfiTimeValue;
|
|
|
|
if (EfiTime == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
CopyMem (&EfiTimeValue, EfiTime, sizeof(EFI_TIME));
|
|
|
|
switch (DateTimeItem) {
|
|
|
|
case YearItem:
|
|
if (Increasement) {
|
|
EfiTimeValue.Year = (EfiTimeValue.Year == PcdGet16 (PcdRealTimeClockYearMax)) ? PcdGet16 (PcdRealTimeClockYearMin) : (EfiTimeValue.Year + 1);
|
|
} else {
|
|
EfiTimeValue.Year = (EfiTimeValue.Year == PcdGet16 (PcdRealTimeClockYearMin)) ? PcdGet16 (PcdRealTimeClockYearMax) : (EfiTimeValue.Year - 1);
|
|
}
|
|
break;
|
|
|
|
case MonthItem:
|
|
if (Increasement) {
|
|
EfiTimeValue.Month = (EfiTimeValue.Month == 12) ? 1 : (EfiTimeValue.Month + 1);
|
|
} else {
|
|
EfiTimeValue.Month = (EfiTimeValue.Month == 1) ? 12 : (EfiTimeValue.Month - 1);
|
|
}
|
|
break;
|
|
|
|
case DayItem:
|
|
MonthIndex = EfiTimeValue.Month - 1;
|
|
|
|
if (Increasement) {
|
|
if (EfiTimeValue.Month == 2 && IsLeapYear (EfiTimeValue.Year)) {
|
|
EfiTimeValue.Day = (EfiTimeValue.Day == 29) ? 1 : (EfiTimeValue.Day + 1);
|
|
} else {
|
|
EfiTimeValue.Day = (EfiTimeValue.Day == DayOfMonth[MonthIndex]) ? 1 : (EfiTimeValue.Day + 1);
|
|
}
|
|
} else {
|
|
if (EfiTimeValue.Month == 2 && IsLeapYear (EfiTimeValue.Year)) {
|
|
EfiTimeValue.Day = (EfiTimeValue.Day == 1) ? 29 : (EfiTimeValue.Day - 1);
|
|
} else {
|
|
EfiTimeValue.Day = (EfiTimeValue.Day == 1) ? DayOfMonth[MonthIndex] : (EfiTimeValue.Day - 1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case HourItem:
|
|
if (Increasement) {
|
|
EfiTimeValue.Hour = (EfiTimeValue.Hour == 23) ? 0 : (EfiTimeValue.Hour + 1);
|
|
} else {
|
|
EfiTimeValue.Hour = (EfiTimeValue.Hour == 0 ) ? 23 : (EfiTimeValue.Hour - 1);
|
|
}
|
|
break;
|
|
|
|
case MinuteItem:
|
|
if (Increasement) {
|
|
EfiTimeValue.Minute = (EfiTimeValue.Minute == 59) ? 0 : (EfiTimeValue.Minute + 1);
|
|
} else {
|
|
EfiTimeValue.Minute = (EfiTimeValue.Minute == 0) ? 59 : (EfiTimeValue.Minute - 1);
|
|
}
|
|
break;
|
|
|
|
case SecondItem:
|
|
if (Increasement) {
|
|
EfiTimeValue.Second = (EfiTimeValue.Second == 59) ? 0 : (EfiTimeValue.Second + 1);
|
|
} else {
|
|
EfiTimeValue.Second = (EfiTimeValue.Second == 0) ? 59 : (EfiTimeValue.Second - 1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (DateTimeItem == YearItem || DateTimeItem == MonthItem || DateTimeItem == DayItem) {
|
|
while (!IsDayValid (&EfiTimeValue)) {
|
|
EfiTimeValue.Day--;
|
|
if (EfiTimeValue.Day == 0) {
|
|
ASSERT(FALSE);
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
CopyMem (EfiTime, &EfiTimeValue, sizeof(EFI_TIME));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get next question value
|
|
|
|
@param[in] Question Pointer to form browser question
|
|
@param[in] GoDown If true, get next value. Otherwise, get previous value
|
|
@param[out] ResultHiiValue Pointer to EFI HII value
|
|
|
|
@retval EFI_SUCCESS Get next question value successfully
|
|
@retval EFI_NOT_FOUND Step value is zero if question is numeric opcode or option list is empty if question is oneof opcode
|
|
@retval EFI_UNSUPPORTED Question operand is not numeric or oneof opcode
|
|
**/
|
|
EFI_STATUS
|
|
GetNextQuestionValue (
|
|
IN H2O_FORM_BROWSER_Q *Question,
|
|
IN BOOLEAN GoDown,
|
|
OUT EFI_HII_VALUE *ResultHiiValue
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT64 Step;
|
|
UINT64 Minimum;
|
|
UINT64 Maximum;
|
|
UINT64 EditValue;
|
|
UINT64 CurrentValue;
|
|
UINT32 Index;
|
|
UINT32 OptionCount;
|
|
H2O_FORM_BROWSER_O *OptionList;
|
|
H2O_FORM_BROWSER_O *TargetOption;
|
|
|
|
Status = EFI_NOT_FOUND;
|
|
|
|
switch (Question->Operand) {
|
|
|
|
case EFI_IFR_NUMERIC_OP:
|
|
if (Question->Step == 0) {
|
|
break;
|
|
}
|
|
|
|
Step = Question->Step;
|
|
Minimum = Question->Minimum;
|
|
Maximum = Question->Maximum == 0 ? ((UINT64) -1) : Question->Maximum;
|
|
EditValue = Question->HiiValue.Value.u64;
|
|
|
|
if ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_INT_DEC) {
|
|
EditValue = (UINT64) IfrNumericConvertValueToInt64 (Question->Flags, EditValue);
|
|
Minimum = (UINT64) IfrNumericConvertValueToInt64 (Question->Flags, Minimum);
|
|
Maximum = (UINT64) IfrNumericConvertValueToInt64 (Question->Flags, Maximum);
|
|
|
|
if (GoDown) {
|
|
if ((INT64) EditValue + (INT64) Step <= (INT64) Maximum) {
|
|
EditValue = (UINT64) ((INT64) EditValue + (INT64) Step);
|
|
} else if ((INT64) EditValue < (INT64) Maximum) {
|
|
EditValue = Maximum;
|
|
} else {
|
|
EditValue = Minimum;
|
|
}
|
|
} else {
|
|
if ((INT64) EditValue >= (INT64) Minimum + (INT64) Step) {
|
|
EditValue = (UINT64) ((INT64) EditValue - (INT64) Step);
|
|
} else if ((INT64) EditValue > (INT64) Minimum){
|
|
EditValue = Minimum;
|
|
} else {
|
|
EditValue = Maximum;
|
|
}
|
|
}
|
|
|
|
EditValue = IfrNumericConvertInt64ToValue (Question->Flags, (INT64) EditValue);
|
|
} else {
|
|
if (GoDown) {
|
|
if (EditValue + Step <= Maximum) {
|
|
EditValue = EditValue + Step;
|
|
} else if (EditValue < Maximum) {
|
|
EditValue = Maximum;
|
|
} else {
|
|
EditValue = Minimum;
|
|
}
|
|
} else {
|
|
if (EditValue >= Minimum + Step) {
|
|
EditValue = EditValue - Step;
|
|
} else if (EditValue > Minimum){
|
|
EditValue = Minimum;
|
|
} else {
|
|
EditValue = Maximum;
|
|
}
|
|
}
|
|
}
|
|
|
|
CopyMem (ResultHiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
|
|
ResultHiiValue->Value.u64 = EditValue;
|
|
Status = EFI_SUCCESS;
|
|
break;
|
|
|
|
case EFI_IFR_ONE_OF_OP:
|
|
if (Question->NumberOfOptions == 0 || Question->Options == NULL) {
|
|
break;
|
|
}
|
|
|
|
CurrentValue = Question->HiiValue.Value.u64;
|
|
OptionList = Question->Options;
|
|
OptionCount = (UINT32) Question->NumberOfOptions;
|
|
|
|
for (Index = 0; Index < OptionCount; Index++) {
|
|
if (OptionList[Index].HiiValue.Value.u64 == CurrentValue) {
|
|
break;
|
|
}
|
|
}
|
|
if (Index == OptionCount) {
|
|
break;
|
|
}
|
|
|
|
TargetOption = &OptionList[Index];
|
|
if (GoDown) {
|
|
if (Index != OptionCount - 1) {
|
|
TargetOption = &OptionList[Index + 1];
|
|
} else {
|
|
TargetOption = &OptionList[0];
|
|
}
|
|
} else {
|
|
if (Index != 0) {
|
|
TargetOption = &OptionList[Index - 1];
|
|
} else {
|
|
TargetOption = &OptionList[OptionCount - 1];
|
|
}
|
|
}
|
|
if (TargetOption == &OptionList[Index]) {
|
|
break;
|
|
}
|
|
CopyMem (ResultHiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
|
|
ResultHiiValue->Value.u64 = TargetOption->HiiValue.Value.u64;
|
|
Status = EFI_SUCCESS;
|
|
break;
|
|
|
|
case EFI_IFR_CHECKBOX_OP:
|
|
CopyMem (ResultHiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
|
|
ResultHiiValue->Value.b = (BOOLEAN) (Question->HiiValue.Value.b ? FALSE : TRUE);
|
|
Status = EFI_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
Status = EFI_UNSUPPORTED;
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get opcode value by dialog type
|
|
|
|
@param[in] DialogType Dialog type
|
|
|
|
@return opcode value or zero if dialog type is not recognized
|
|
**/
|
|
UINT8
|
|
GetOpCodeByDialogType (
|
|
IN UINT32 DialogType
|
|
)
|
|
{
|
|
switch ((DialogType & H2O_FORM_BROWSER_D_TYPE_QUESTIONS) >> 16) {
|
|
|
|
case H2O_FORM_BROWSER_D_TYPE_ONE_OF:
|
|
return EFI_IFR_ONE_OF_OP;
|
|
|
|
case H2O_FORM_BROWSER_D_TYPE_ORDERED_LIST:
|
|
return EFI_IFR_ORDERED_LIST_OP;
|
|
|
|
case H2O_FORM_BROWSER_D_TYPE_NUMERIC:
|
|
return EFI_IFR_NUMERIC_OP;
|
|
|
|
case H2O_FORM_BROWSER_D_TYPE_STRING:
|
|
return EFI_IFR_STRING_OP;
|
|
|
|
case H2O_FORM_BROWSER_D_TYPE_DATE:
|
|
return EFI_IFR_DATE_OP;
|
|
|
|
case H2O_FORM_BROWSER_D_TYPE_TIME:
|
|
return EFI_IFR_TIME_OP;
|
|
|
|
case H2O_FORM_BROWSER_D_TYPE_PASSWORD:
|
|
return EFI_IFR_PASSWORD_OP;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Get HII buffer value by buffer type and index
|
|
|
|
@param[in] Buffer Pointer to buffer
|
|
@param[in] Type Buffer type
|
|
@param[in] Index Buffer index
|
|
|
|
@return buffer value or zero if Buffer is NULL or Type is not recognized
|
|
**/
|
|
UINT64
|
|
GetHiiBufferValue (
|
|
IN UINT8 *Buffer,
|
|
IN UINT8 Type,
|
|
IN UINT32 Index
|
|
)
|
|
{
|
|
UINT64 Data;
|
|
|
|
ASSERT (Buffer != NULL);
|
|
if (Buffer == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
Data = 0;
|
|
switch (Type) {
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_8:
|
|
Data = (UINT64) *(((UINT8 *) Buffer) + Index);
|
|
break;
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_16:
|
|
Data = (UINT64) *(((UINT16 *) Buffer) + Index);
|
|
break;
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_32:
|
|
Data = (UINT64) *(((UINT32 *) Buffer) + Index);
|
|
break;
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_64:
|
|
Data = (UINT64) *(((UINT64 *) Buffer) + Index);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return Data;
|
|
}
|
|
|
|
/**
|
|
Set HII buffer value by buffer type and index
|
|
|
|
@param[in] Buffer Pointer to buffer
|
|
@param[in] Type Buffer type
|
|
@param[in] Index Buffer index
|
|
@param[in] Value The value to be set
|
|
**/
|
|
VOID
|
|
SetHiiBufferValue (
|
|
IN UINT8 *Buffer,
|
|
IN UINT8 Type,
|
|
IN UINT32 Index,
|
|
IN UINT64 Value
|
|
)
|
|
{
|
|
ASSERT (Buffer != NULL);
|
|
if (Buffer == NULL) {
|
|
return;
|
|
}
|
|
|
|
switch (Type) {
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_8:
|
|
*(((UINT8 *) Buffer) + Index) = (UINT8) Value;
|
|
break;
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_16:
|
|
*(((UINT16 *) Buffer) + Index) = (UINT16) Value;
|
|
break;
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_32:
|
|
*(((UINT32 *) Buffer) + Index) = (UINT32) Value;
|
|
break;
|
|
|
|
case EFI_IFR_TYPE_NUM_SIZE_64:
|
|
*(((UINT64 *) Buffer) + Index) = (UINT64) Value;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetSetupMenuInfoByPage (
|
|
IN H2O_FORM_BROWSER_P *Page,
|
|
OUT SETUP_MENU_INFO *SetupMenuInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
H2O_FORM_BROWSER_PROTOCOL *FBProtocol;
|
|
H2O_FORM_BROWSER_SM *SetupMenuData;
|
|
UINT32 HiiHandleIndex;
|
|
UINT32 Index;
|
|
SETUP_MENU_INFO *RootSetupMenuInfo;
|
|
|
|
if (Page == NULL || SetupMenuInfo == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (&gH2OFormBrowserProtocolGuid, NULL, (VOID **) &FBProtocol);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = FBProtocol->GetSMInfo (FBProtocol, &SetupMenuData);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
RootSetupMenuInfo = NULL;
|
|
|
|
do {
|
|
HiiHandleIndex = Page->PageId >> 16;
|
|
for (Index = 0; Index < SetupMenuData->NumberOfSetupMenus; Index++) {
|
|
if ((SetupMenuData->SetupMenuInfoList[Index].PageId >> 16) == HiiHandleIndex) {
|
|
RootSetupMenuInfo = &SetupMenuData->SetupMenuInfoList[Index];
|
|
break;
|
|
}
|
|
}
|
|
|
|
Page = Page->ParentPage;
|
|
} while (Page != NULL);
|
|
|
|
if (RootSetupMenuInfo != NULL) {
|
|
CopyMem (SetupMenuInfo, RootSetupMenuInfo, sizeof (SETUP_MENU_INFO));
|
|
}
|
|
|
|
FreeSetupMenuData (SetupMenuData);
|
|
|
|
return (RootSetupMenuInfo != NULL) ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Free form browser setup menu data
|
|
|
|
@param[in] SetupMenuData Pointer to form browser setup menu data
|
|
**/
|
|
VOID
|
|
FreeSetupMenuData (
|
|
IN H2O_FORM_BROWSER_SM *SetupMenuData
|
|
)
|
|
{
|
|
if (SetupMenuData == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (SetupMenuData->TitleString != NULL) {
|
|
FreePool (SetupMenuData->TitleString);
|
|
}
|
|
if (SetupMenuData->CoreVersionString != NULL) {
|
|
FreePool (SetupMenuData->CoreVersionString);
|
|
}
|
|
if (SetupMenuData->SetupMenuInfoList != NULL) {
|
|
FreePool (SetupMenuData->SetupMenuInfoList);
|
|
}
|
|
FreePool (SetupMenuData);
|
|
}
|
|
|
|
/**
|
|
Get display engine resolution by Pcd
|
|
|
|
@param[in] DisplayEngineGuid Display engine guid
|
|
@param[in] HorizontalResolution Pointer to horizontal resolution
|
|
@param[in] VerticalResolution Pointer to vertical resolution
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
GetDisplayEngineResolutionByPcd (
|
|
IN EFI_GUID *DisplayEngineGuid,
|
|
IN UINT32 *HorizontalResolution,
|
|
IN UINT32 *VerticalResolution
|
|
)
|
|
{
|
|
UINT32 Horizontal;
|
|
UINT32 Vertical;
|
|
OEM_LOGO_RESOLUTION_DEFINITION TempLogoResolution;
|
|
OEM_LOGO_RESOLUTION_DEFINITION *LogoResolution;
|
|
H2O_DISPLAY_ENGINE_RESOLUTION *DisplayEngineResolution;
|
|
UINTN Count;
|
|
EFI_STATUS OemSvcStatus;
|
|
|
|
LogoResolution = (OEM_LOGO_RESOLUTION_DEFINITION *) PcdGetPtr (PcdDefaultLogoResolution);
|
|
CopyMem (&TempLogoResolution, LogoResolution, sizeof (OEM_LOGO_RESOLUTION_DEFINITION));
|
|
LogoResolution = &TempLogoResolution;
|
|
|
|
Horizontal = LogoResolution->ScuResolutionX;
|
|
Vertical = LogoResolution->ScuResolutionY;
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcLogoResolution \n"));
|
|
OemSvcStatus = OemSvcLogoResolution (&LogoResolution);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcLogoResolution Status: %r\n", OemSvcStatus));
|
|
|
|
if (Horizontal == 0xFFFF && Vertical == 0xFFFF) {
|
|
DisplayEngineResolution = (H2O_DISPLAY_ENGINE_RESOLUTION *)(LogoResolution + 1);
|
|
Count = 5;
|
|
while (Count--) {
|
|
if (CompareGuid (&DisplayEngineResolution->DisplayEngineGuid, DisplayEngineGuid)) {
|
|
Horizontal = DisplayEngineResolution->HorizontalResolution;
|
|
Vertical = DisplayEngineResolution->VerticalResolution;
|
|
break;
|
|
}
|
|
if (CompareGuid (&DisplayEngineResolution->DisplayEngineGuid, &gZeroGuid)) {
|
|
break;
|
|
}
|
|
DisplayEngineResolution++;
|
|
}
|
|
} else {
|
|
Horizontal = LogoResolution->ScuResolutionX;
|
|
Vertical = LogoResolution->ScuResolutionY;
|
|
}
|
|
|
|
*HorizontalResolution = Horizontal;
|
|
*VerticalResolution = Vertical;
|
|
}
|
|
|
|
/**
|
|
Check if user input key data match key data of hot key.
|
|
|
|
@param[in] HotKeyKeyData Pointer to input key data
|
|
@param[in] UserInputKeyData Pointer to key data of hot key
|
|
|
|
@retval TRUE User input key data match key data of hot key
|
|
@retval FALSE User input key data does not match key data of hot key
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
IsHotKeyPressed (
|
|
IN EFI_KEY_DATA *HotKeyKeyData,
|
|
IN EFI_KEY_DATA *UserInputKeyData
|
|
)
|
|
{
|
|
UINT32 HotKeyState;
|
|
UINT32 UserInputState;
|
|
BOOLEAN IsMatch;
|
|
BOOLEAN CheckCharCase;
|
|
|
|
ASSERT (HotKeyKeyData != NULL);
|
|
ASSERT (UserInputKeyData != NULL);
|
|
if (HotKeyKeyData == NULL || UserInputKeyData == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
CheckCharCase = TRUE;
|
|
|
|
if (((HotKeyKeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == EFI_SHIFT_STATE_VALID) &&
|
|
((UserInputKeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == EFI_SHIFT_STATE_VALID)) {
|
|
HotKeyState = (HotKeyKeyData->KeyState.KeyShiftState & (EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED));
|
|
UserInputState = (UserInputKeyData->KeyState.KeyShiftState & (EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED));
|
|
IsMatch = (BOOLEAN) ((HotKeyState == 0 && UserInputState == 0) ||
|
|
((HotKeyState == (EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED)) && (UserInputState != 0)) ||
|
|
((HotKeyState != (EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED)) && (UserInputState == HotKeyState)));
|
|
if (!IsMatch) {
|
|
return FALSE;
|
|
}
|
|
|
|
HotKeyState = (HotKeyKeyData->KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED));
|
|
UserInputState = (UserInputKeyData->KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED));
|
|
IsMatch = (BOOLEAN) ((HotKeyState == 0 && UserInputState == 0) ||
|
|
((HotKeyState == (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)) && (UserInputState != 0)) ||
|
|
((HotKeyState != (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)) && (UserInputState == HotKeyState)));
|
|
if (!IsMatch) {
|
|
return FALSE;
|
|
}
|
|
if (HotKeyState != 0) {
|
|
CheckCharCase = FALSE;
|
|
}
|
|
|
|
HotKeyState = (HotKeyKeyData->KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED));
|
|
UserInputState = (UserInputKeyData->KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED));
|
|
IsMatch = (BOOLEAN) ((HotKeyState == 0 && UserInputState == 0) ||
|
|
((HotKeyState == (EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED)) && (UserInputState != 0)) ||
|
|
((HotKeyState != (EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED)) && (UserInputState == HotKeyState)));
|
|
if (!IsMatch) {
|
|
return FALSE;
|
|
}
|
|
if (HotKeyState != 0) {
|
|
CheckCharCase = FALSE;
|
|
}
|
|
|
|
HotKeyState = (HotKeyKeyData->KeyState.KeyShiftState & (EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED));
|
|
UserInputState = (UserInputKeyData->KeyState.KeyShiftState & (EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED));
|
|
IsMatch = (BOOLEAN) ((HotKeyState == 0 && UserInputState == 0) ||
|
|
((HotKeyState == (EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED)) && (UserInputState != 0)) ||
|
|
((HotKeyState != (EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED)) && (UserInputState == HotKeyState)));
|
|
if (!IsMatch) {
|
|
return FALSE;
|
|
}
|
|
if (HotKeyState != 0) {
|
|
CheckCharCase = FALSE;
|
|
}
|
|
|
|
HotKeyState = (HotKeyKeyData->KeyState.KeyShiftState & EFI_MENU_KEY_PRESSED);
|
|
UserInputState = (UserInputKeyData->KeyState.KeyShiftState & EFI_MENU_KEY_PRESSED);
|
|
if (HotKeyState != UserInputState) {
|
|
return FALSE;
|
|
}
|
|
if (HotKeyState != 0) {
|
|
CheckCharCase = FALSE;
|
|
}
|
|
|
|
HotKeyState = (HotKeyKeyData->KeyState.KeyShiftState & EFI_SYS_REQ_PRESSED);
|
|
UserInputState = (UserInputKeyData->KeyState.KeyShiftState & EFI_SYS_REQ_PRESSED);
|
|
if (HotKeyState != UserInputState) {
|
|
return FALSE;
|
|
}
|
|
if (HotKeyState != 0) {
|
|
CheckCharCase = FALSE;
|
|
}
|
|
}
|
|
|
|
if (HotKeyKeyData->Key.ScanCode != UserInputKeyData->Key.ScanCode ||
|
|
((CheckCharCase && HotKeyKeyData->Key.UnicodeChar != UserInputKeyData->Key.UnicodeChar) ||
|
|
(!CheckCharCase && TO_LOWER_UNICODE_CHAR (HotKeyKeyData->Key.UnicodeChar) != TO_LOWER_UNICODE_CHAR (UserInputKeyData->Key.UnicodeChar)))) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Get selected hot key info if input key data match one of input hot key info list.
|
|
|
|
@param[in] KeyData Pointer to input key data
|
|
@param[in] HotKeyInfoList Pointer to hot key info list
|
|
@param[out] SelectedHotKeyInfo Pointer to selected hot key info
|
|
|
|
@retval EFI_SUCCESS Get selected hot key info successfully
|
|
@retval EFI_NOT_FOUND Input key does not match one of input hot key info list.
|
|
@retval EFI_INVALID_PARAMETER KeyData, HotKeyInfoList or SelectedHotKeyInfo is NULL
|
|
**/
|
|
EFI_STATUS
|
|
GetSelectedHotKeyInfoByKeyData (
|
|
IN EFI_KEY_DATA *KeyData,
|
|
IN HOT_KEY_INFO *HotKeyInfoList,
|
|
OUT HOT_KEY_INFO *SelectedHotKeyInfo
|
|
)
|
|
{
|
|
if (KeyData == NULL || HotKeyInfoList == NULL || SelectedHotKeyInfo == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
while (!IS_END_OF_HOT_KEY_INFO (HotKeyInfoList)) {
|
|
if (IsHotKeyPressed (&HotKeyInfoList->KeyData, KeyData)) {
|
|
CopyMem (SelectedHotKeyInfo, HotKeyInfoList, sizeof (HOT_KEY_INFO));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
HotKeyInfoList++;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|