2 Implementation for handling the User Interface option processing.
5 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "FormDisplay.h"
18 #define MAX_TIME_OUT_LEN 0x10
21 Concatenate a narrow string to another string.
23 @param Destination The destination string.
24 @param Source The source string. The string to be concatenated.
25 to the end of Destination.
30 IN OUT CHAR16
*Destination
,
36 for (Length
= 0; Destination
[Length
] != 0; Length
++)
40 // We now have the length of the original string
41 // We can safely assume for now that we are concatenating a narrow value to this string.
42 // For instance, the string is "XYZ" and cat'ing ">"
43 // If this assumption changes, we need to make this routine a bit more complex
45 Destination
[Length
] = NARROW_CHAR
;
48 StrCpy (Destination
+ Length
, Source
);
52 Get UINT64 type value.
54 @param Value Input Hii value.
56 @retval UINT64 Return the UINT64 type value.
61 IN EFI_HII_VALUE
*Value
68 switch (Value
->Type
) {
69 case EFI_IFR_TYPE_NUM_SIZE_8
:
70 RetVal
= Value
->Value
.u8
;
73 case EFI_IFR_TYPE_NUM_SIZE_16
:
74 RetVal
= Value
->Value
.u16
;
77 case EFI_IFR_TYPE_NUM_SIZE_32
:
78 RetVal
= Value
->Value
.u32
;
81 case EFI_IFR_TYPE_BOOLEAN
:
82 RetVal
= Value
->Value
.b
;
85 case EFI_IFR_TYPE_DATE
:
86 RetVal
= *(UINT64
*) &Value
->Value
.date
;
89 case EFI_IFR_TYPE_TIME
:
90 RetVal
= (*(UINT64
*) &Value
->Value
.time
) & 0xffffff;
94 RetVal
= Value
->Value
.u64
;
102 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
104 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
105 EFI_IFR_TYPE_BUFFER when do the value compare.
107 @param Value Expression value to compare on.
109 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
110 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
115 IN EFI_HII_VALUE
*Value
118 switch (Value
->Type
) {
119 case EFI_IFR_TYPE_BUFFER
:
120 case EFI_IFR_TYPE_DATE
:
121 case EFI_IFR_TYPE_TIME
:
122 case EFI_IFR_TYPE_REF
:
131 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
133 @param Value Expression value to compare on.
135 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
136 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
141 IN EFI_HII_VALUE
*Value
144 switch (Value
->Type
) {
145 case EFI_IFR_TYPE_NUM_SIZE_8
:
146 case EFI_IFR_TYPE_NUM_SIZE_16
:
147 case EFI_IFR_TYPE_NUM_SIZE_32
:
148 case EFI_IFR_TYPE_NUM_SIZE_64
:
149 case EFI_IFR_TYPE_BOOLEAN
:
158 Return the buffer length and buffer pointer for this value.
160 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
161 EFI_IFR_TYPE_BUFFER when do the value compare.
163 @param Value Expression value to compare on.
164 @param Buf Return the buffer pointer.
165 @param BufLen Return the buffer length.
169 GetBufAndLenForValue (
170 IN EFI_HII_VALUE
*Value
,
175 switch (Value
->Type
) {
176 case EFI_IFR_TYPE_BUFFER
:
177 *Buf
= Value
->Buffer
;
178 *BufLen
= Value
->BufferLen
;
181 case EFI_IFR_TYPE_DATE
:
182 *Buf
= (UINT8
*) (&Value
->Value
.date
);
183 *BufLen
= (UINT16
) sizeof (EFI_HII_DATE
);
186 case EFI_IFR_TYPE_TIME
:
187 *Buf
= (UINT8
*) (&Value
->Value
.time
);
188 *BufLen
= (UINT16
) sizeof (EFI_HII_TIME
);
191 case EFI_IFR_TYPE_REF
:
192 *Buf
= (UINT8
*) (&Value
->Value
.ref
);
193 *BufLen
= (UINT16
) sizeof (EFI_HII_REF
);
203 Compare two Hii value.
205 @param Value1 Expression value to compare on left-hand.
206 @param Value2 Expression value to compare on right-hand.
207 @param Result Return value after compare.
208 retval 0 Two operators equal.
209 return Positive value if Value1 is greater than Value2.
210 retval Negative value if Value1 is less than Value2.
211 @param HiiHandle Only required for string compare.
213 @retval other Could not perform compare on two values.
214 @retval EFI_SUCCESS Compare the value success.
219 IN EFI_HII_VALUE
*Value1
,
220 IN EFI_HII_VALUE
*Value2
,
222 IN EFI_HII_HANDLE HiiHandle OPTIONAL
234 if (Value1
->Type
== EFI_IFR_TYPE_STRING
&& Value2
->Type
== EFI_IFR_TYPE_STRING
) {
235 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
237 // StringId 0 is reserved
239 return EFI_INVALID_PARAMETER
;
242 if (Value1
->Value
.string
== Value2
->Value
.string
) {
247 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
252 return EFI_NOT_FOUND
;
255 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
258 return EFI_NOT_FOUND
;
261 *Result
= StrCmp (Str1
, Str2
);
270 // Take types(date, time, ref, buffer) as buffer
272 if (IsTypeInBuffer(Value1
) && IsTypeInBuffer(Value2
)) {
273 GetBufAndLenForValue(Value1
, &Buf1
, &Buf1Len
);
274 GetBufAndLenForValue(Value2
, &Buf2
, &Buf2Len
);
276 Len
= Buf1Len
> Buf2Len
? Buf2Len
: Buf1Len
;
277 *Result
= CompareMem (Buf1
, Buf2
, Len
);
278 if ((*Result
== 0) && (Buf1Len
!= Buf2Len
)) {
280 // In this case, means base on samll number buffer, the data is same
281 // So which value has more data, which value is bigger.
283 *Result
= Buf1Len
> Buf2Len
? 1 : -1;
289 // Take remain types(integer, boolean, date/time) as integer
291 if (IsTypeInUINT64(Value1
) && IsTypeInUINT64(Value2
)) {
292 Temp64
= HiiValueToUINT64(Value1
) - HiiValueToUINT64(Value2
);
295 } else if (Temp64
< 0) {
303 return EFI_UNSUPPORTED
;
307 Search an Option of a Question by its value.
309 @param Question The Question
310 @param OptionValue Value for Option to be searched.
312 @retval Pointer Pointer to the found Option.
313 @retval NULL Option not found.
316 DISPLAY_QUESTION_OPTION
*
318 IN FORM_DISPLAY_ENGINE_STATEMENT
*Question
,
319 IN EFI_HII_VALUE
*OptionValue
323 DISPLAY_QUESTION_OPTION
*Option
;
327 Link
= GetFirstNode (&Question
->OptionListHead
);
328 while (!IsNull (&Question
->OptionListHead
, Link
)) {
329 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
331 ZeroMem (&Value
, sizeof (EFI_HII_VALUE
));
332 Value
.Type
= Option
->OptionOpCode
->Type
;
333 CopyMem (&Value
.Value
, &Option
->OptionOpCode
->Value
, Option
->OptionOpCode
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
335 if ((CompareHiiValue (&Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
339 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
347 Return data element in an Array by its Index.
349 @param Array The data array.
350 @param Type Type of the data in this array.
351 @param Index Zero based index for data in this array.
353 @retval Value The data to be returned
365 ASSERT (Array
!= NULL
);
369 case EFI_IFR_TYPE_NUM_SIZE_8
:
370 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
373 case EFI_IFR_TYPE_NUM_SIZE_16
:
374 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
377 case EFI_IFR_TYPE_NUM_SIZE_32
:
378 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
381 case EFI_IFR_TYPE_NUM_SIZE_64
:
382 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
394 Set value of a data element in an Array by its Index.
396 @param Array The data array.
397 @param Type Type of the data in this array.
398 @param Index Zero based index for data in this array.
399 @param Value The value to be set.
411 ASSERT (Array
!= NULL
);
414 case EFI_IFR_TYPE_NUM_SIZE_8
:
415 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
418 case EFI_IFR_TYPE_NUM_SIZE_16
:
419 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
422 case EFI_IFR_TYPE_NUM_SIZE_32
:
423 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
426 case EFI_IFR_TYPE_NUM_SIZE_64
:
427 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
436 Check whether this value already in the array, if yes, return the index.
438 @param Array The data array.
439 @param Type Type of the data in this array.
440 @param Value The value to be find.
441 @param Index The index in the array which has same value with Value.
443 @retval TRUE Found the value in the array.
444 @retval FALSE Not found the value.
452 OUT UINTN
*Index OPTIONAL
459 ASSERT (Array
!= NULL
);
465 case EFI_IFR_TYPE_NUM_SIZE_8
:
466 ValueComp
= (UINT8
) Value
;
469 case EFI_IFR_TYPE_NUM_SIZE_16
:
470 ValueComp
= (UINT16
) Value
;
473 case EFI_IFR_TYPE_NUM_SIZE_32
:
474 ValueComp
= (UINT32
) Value
;
477 case EFI_IFR_TYPE_NUM_SIZE_64
:
478 ValueComp
= (UINT64
) Value
;
486 while ((TmpValue
= GetArrayData (Array
, Type
, Count
)) != 0) {
487 if (ValueComp
== TmpValue
) {
501 Print Question Value according to it's storage width and display attributes.
503 @param Question The Question to be printed.
504 @param FormattedNumber Buffer for output string.
505 @param BufferSize The FormattedNumber buffer size in bytes.
507 @retval EFI_SUCCESS Print success.
508 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
512 PrintFormattedNumber (
513 IN FORM_DISPLAY_ENGINE_STATEMENT
*Question
,
514 IN OUT CHAR16
*FormattedNumber
,
520 EFI_HII_VALUE
*QuestionValue
;
521 EFI_IFR_NUMERIC
*NumericOp
;
523 if (BufferSize
< (21 * sizeof (CHAR16
))) {
524 return EFI_BUFFER_TOO_SMALL
;
527 QuestionValue
= &Question
->CurrentValue
;
528 NumericOp
= (EFI_IFR_NUMERIC
*) Question
->OpCode
;
530 Value
= (INT64
) QuestionValue
->Value
.u64
;
531 switch (NumericOp
->Flags
& EFI_IFR_DISPLAY
) {
532 case EFI_IFR_DISPLAY_INT_DEC
:
533 switch (QuestionValue
->Type
) {
534 case EFI_IFR_NUMERIC_SIZE_1
:
535 Value
= (INT64
) ((INT8
) QuestionValue
->Value
.u8
);
538 case EFI_IFR_NUMERIC_SIZE_2
:
539 Value
= (INT64
) ((INT16
) QuestionValue
->Value
.u16
);
542 case EFI_IFR_NUMERIC_SIZE_4
:
543 Value
= (INT64
) ((INT32
) QuestionValue
->Value
.u32
);
546 case EFI_IFR_NUMERIC_SIZE_8
:
559 case EFI_IFR_DISPLAY_UINT_DEC
:
563 case EFI_IFR_DISPLAY_UINT_HEX
:
568 return EFI_UNSUPPORTED
;
572 UnicodeSPrint (FormattedNumber
, BufferSize
, Format
, Value
);
579 Draw a pop up windows based on the dimension, number of lines and
582 @param RequestedWidth The width of the pop-up.
583 @param NumberOfLines The number of lines.
584 @param Marker The variable argument list for the list of string to be printed.
589 IN UINTN RequestedWidth
,
590 IN UINTN NumberOfLines
,
602 UINTN DimensionsWidth
;
603 UINTN DimensionsHeight
;
605 DimensionsWidth
= gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
;
606 DimensionsHeight
= gStatementDimensions
.BottomRow
- gStatementDimensions
.TopRow
;
608 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetPopupColor ());
610 if ((RequestedWidth
+ 2) > DimensionsWidth
) {
611 RequestedWidth
= DimensionsWidth
- 2;
615 // Subtract the PopUp width from total Columns, allow for one space extra on
616 // each end plus a border.
618 Start
= (DimensionsWidth
- RequestedWidth
- 2) / 2 + gStatementDimensions
.LeftColumn
+ 1;
619 End
= Start
+ RequestedWidth
+ 1;
621 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + gStatementDimensions
.TopRow
- 1;
622 Bottom
= Top
+ NumberOfLines
+ 2;
624 Character
= BOXDRAW_DOWN_RIGHT
;
625 PrintCharAt (Start
, Top
, Character
);
626 Character
= BOXDRAW_HORIZONTAL
;
627 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
628 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
631 Character
= BOXDRAW_DOWN_LEFT
;
632 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
633 Character
= BOXDRAW_VERTICAL
;
636 for (Index
= Top
; Index
+ 2 < Bottom
; Index
++, Count
++) {
637 String
= VA_ARG (Marker
, CHAR16
*);
640 // This will clear the background of the line - we never know who might have been
641 // here before us. This differs from the next clear in that it used the non-reverse
642 // video for normal printing.
644 if (GetStringWidth (String
) / 2 > 1) {
645 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, GetPopupColor ());
649 // Passing in a space results in the assumption that this is where typing will occur
651 if (String
[0] == L
' ') {
652 ClearLines (Start
+ 1, End
- 1, Index
+ 1, Index
+ 1, GetPopupInverseColor ());
656 // Passing in a NULL results in a blank space
658 if (String
[0] == CHAR_NULL
) {
659 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, GetPopupColor ());
663 ((DimensionsWidth
- GetStringWidth (String
) / 2) / 2) + gStatementDimensions
.LeftColumn
+ 1,
667 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetPopupColor ());
668 PrintCharAt (Start
, Index
+ 1, Character
);
669 PrintCharAt (End
- 1, Index
+ 1, Character
);
672 Character
= BOXDRAW_UP_RIGHT
;
673 PrintCharAt (Start
, Bottom
- 1, Character
);
674 Character
= BOXDRAW_HORIZONTAL
;
675 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
676 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
679 Character
= BOXDRAW_UP_LEFT
;
680 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
684 Draw a pop up windows based on the dimension, number of lines and
687 @param RequestedWidth The width of the pop-up.
688 @param NumberOfLines The number of lines.
689 @param ... A series of text strings that displayed in the pop-up.
694 CreateMultiStringPopUp (
695 IN UINTN RequestedWidth
,
696 IN UINTN NumberOfLines
,
702 VA_START (Marker
, NumberOfLines
);
704 CreateSharedPopUp (RequestedWidth
, NumberOfLines
, Marker
);
712 @param Event The Event need to be process
713 @param Context The context of the event.
726 Process for the refresh interval statement.
728 @param Event The Event need to be process
729 @param Context The context of the event.
734 RefreshTimeOutProcess (
739 WARNING_IF_CONTEXT
*EventInfo
;
740 CHAR16 TimeOutString
[MAX_TIME_OUT_LEN
];
742 EventInfo
= (WARNING_IF_CONTEXT
*) Context
;
744 if (*(EventInfo
->TimeOut
) == 0) {
745 gBS
->CloseEvent (Event
);
747 gBS
->SignalEvent (EventInfo
->SyncEvent
);
751 UnicodeSPrint(TimeOutString
, MAX_TIME_OUT_LEN
, L
"%d", *(EventInfo
->TimeOut
));
753 CreateDialog (NULL
, gEmptyString
, EventInfo
->ErrorInfo
, gPressEnter
, gEmptyString
, TimeOutString
, NULL
);
755 *(EventInfo
->TimeOut
) -= 1;
759 Display error message for invalid password.
770 // Invalid password, prompt error message
773 CreateDialog (&Key
, gEmptyString
, gPassowordInvalid
, gPressEnter
, gEmptyString
, NULL
);
774 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
778 Process password op code.
780 @param MenuOption The menu for current password op code.
782 @retval EFI_SUCCESS Question Option process success.
783 @retval Other Question Option process fail.
788 IN UI_MENU_OPTION
*MenuOption
795 EFI_IFR_PASSWORD
*PasswordInfo
;
796 FORM_DISPLAY_ENGINE_STATEMENT
*Question
;
799 Question
= MenuOption
->ThisTag
;
800 PasswordInfo
= (EFI_IFR_PASSWORD
*) Question
->OpCode
;
801 Maximum
= PasswordInfo
->MaxSize
;
802 Status
= EFI_SUCCESS
;
804 StringPtr
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
808 // Use a NULL password to test whether old password is required
811 Status
= Question
->PasswordCheck (gFormData
, Question
, StringPtr
);
812 if (Status
== EFI_NOT_AVAILABLE_YET
|| Status
== EFI_UNSUPPORTED
) {
814 // Password can't be set now.
816 FreePool (StringPtr
);
820 if (EFI_ERROR (Status
)) {
822 // Old password exist, ask user for the old password
824 Status
= ReadString (MenuOption
, gPromptForPassword
, StringPtr
);
825 if (EFI_ERROR (Status
)) {
826 FreePool (StringPtr
);
831 // Check user input old password
833 Status
= Question
->PasswordCheck (gFormData
, Question
, StringPtr
);
834 if (EFI_ERROR (Status
)) {
835 if (Status
== EFI_NOT_READY
) {
837 // Typed in old password incorrect
841 Status
= EFI_SUCCESS
;
844 FreePool (StringPtr
);
850 // Ask for new password
852 ZeroMem (StringPtr
, (Maximum
+ 1) * sizeof (CHAR16
));
853 Status
= ReadString (MenuOption
, gPromptForNewPassword
, StringPtr
);
854 if (EFI_ERROR (Status
)) {
856 // Reset state machine for password
858 Question
->PasswordCheck (gFormData
, Question
, NULL
);
859 FreePool (StringPtr
);
864 // Confirm new password
866 TempString
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
868 Status
= ReadString (MenuOption
, gConfirmPassword
, TempString
);
869 if (EFI_ERROR (Status
)) {
871 // Reset state machine for password
873 Question
->PasswordCheck (gFormData
, Question
, NULL
);
874 FreePool (StringPtr
);
875 FreePool (TempString
);
880 // Compare two typed-in new passwords
882 if (StrCmp (StringPtr
, TempString
) == 0) {
883 gUserInput
->InputValue
.Buffer
= AllocateCopyPool (Question
->CurrentValue
.BufferLen
, StringPtr
);
884 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
885 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
886 gUserInput
->InputValue
.Value
.string
= HiiSetString(gFormData
->HiiHandle
, gUserInput
->InputValue
.Value
.string
, StringPtr
, NULL
);
887 FreePool (StringPtr
);
889 Status
= EFI_SUCCESS
;
891 if (EFI_ERROR (Status
)) {
893 // Reset state machine for password
895 Question
->PasswordCheck (gFormData
, Question
, NULL
);
901 // Reset state machine for password
903 Question
->PasswordCheck (gFormData
, Question
, NULL
);
906 // Two password mismatch, prompt error message
909 CreateDialog (&Key
, gEmptyString
, gConfirmError
, gPressEnter
, gEmptyString
, NULL
);
910 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
912 Status
= EFI_INVALID_PARAMETER
;
915 FreePool (TempString
);
916 FreePool (StringPtr
);
922 Process a Question's Option (whether selected or un-selected).
924 @param MenuOption The MenuOption for this Question.
925 @param Selected TRUE: if Question is selected.
926 @param OptionString Pointer of the Option String to be displayed.
927 @param SkipErrorValue Whether need to return when value without option for it.
929 @retval EFI_SUCCESS Question Option process success.
930 @retval Other Question Option process fail.
935 IN UI_MENU_OPTION
*MenuOption
,
937 OUT CHAR16
**OptionString
,
938 IN BOOLEAN SkipErrorValue
944 FORM_DISPLAY_ENGINE_STATEMENT
*Question
;
945 CHAR16 FormattedNumber
[21];
950 DISPLAY_QUESTION_OPTION
*OneOfOption
;
952 EFI_HII_VALUE HiiValue
;
953 EFI_HII_VALUE
*QuestionValue
;
954 DISPLAY_QUESTION_OPTION
*Option
;
958 EFI_IFR_ORDERED_LIST
*OrderList
;
959 BOOLEAN ValueInvalid
;
961 Status
= EFI_SUCCESS
;
964 Character
[1] = L
'\0';
965 *OptionString
= NULL
;
966 ValueInvalid
= FALSE
;
968 ZeroMem (FormattedNumber
, 21 * sizeof (CHAR16
));
969 BufferSize
= (gOptionBlockWidth
+ 1) * 2 * gStatementDimensions
.BottomRow
;
971 Question
= MenuOption
->ThisTag
;
972 QuestionValue
= &Question
->CurrentValue
;
974 switch (Question
->OpCode
->OpCode
) {
975 case EFI_IFR_ORDERED_LIST_OP
:
978 // Check whether there are Options of this OrderedList
980 if (IsListEmpty (&Question
->OptionListHead
)) {
984 OrderList
= (EFI_IFR_ORDERED_LIST
*) Question
->OpCode
;
986 Link
= GetFirstNode (&Question
->OptionListHead
);
987 OneOfOption
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
989 ValueType
= OneOfOption
->OptionOpCode
->Type
;
990 ValueArray
= Question
->CurrentValue
.Buffer
;
996 Status
= GetSelectionInputPopUp (MenuOption
);
999 // We now know how many strings we will have, so we can allocate the
1000 // space required for the array or strings.
1002 *OptionString
= AllocateZeroPool (OrderList
->MaxContainers
* BufferSize
);
1003 ASSERT (*OptionString
);
1005 HiiValue
.Type
= ValueType
;
1006 HiiValue
.Value
.u64
= 0;
1007 for (Index
= 0; Index
< OrderList
->MaxContainers
; Index
++) {
1008 HiiValue
.Value
.u64
= GetArrayData (ValueArray
, ValueType
, Index
);
1009 if (HiiValue
.Value
.u64
== 0) {
1011 // Values for the options in ordered lists should never be a 0
1016 OneOfOption
= ValueToOption (Question
, &HiiValue
);
1017 if (OneOfOption
== NULL
) {
1018 if (SkipErrorValue
) {
1020 // Just try to get the option string, skip the value which not has option.
1026 // Show error message
1029 CreateDialog (&Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
, NULL
);
1030 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1033 // The initial value of the orderedlist is invalid, force to be valid value
1034 // Exit current DisplayForm with new value.
1036 gUserInput
->SelectedStatement
= Question
;
1038 ValueArray
= AllocateZeroPool (Question
->CurrentValue
.BufferLen
);
1039 ASSERT (ValueArray
!= NULL
);
1040 gUserInput
->InputValue
.Buffer
= ValueArray
;
1041 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
1042 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
1044 Link
= GetFirstNode (&Question
->OptionListHead
);
1046 while (!IsNull (&Question
->OptionListHead
, Link
) && Index2
< OrderList
->MaxContainers
) {
1047 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
1048 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
1049 SetArrayData (ValueArray
, ValueType
, Index2
, Option
->OptionOpCode
->Value
.u64
);
1052 SetArrayData (ValueArray
, ValueType
, Index2
, 0);
1054 FreePool (*OptionString
);
1055 *OptionString
= NULL
;
1056 return EFI_NOT_FOUND
;
1059 Character
[0] = LEFT_ONEOF_DELIMITER
;
1060 NewStrCat (OptionString
[0], Character
);
1061 StringPtr
= GetToken (OneOfOption
->OptionOpCode
->Option
, gFormData
->HiiHandle
);
1062 ASSERT (StringPtr
!= NULL
);
1063 NewStrCat (OptionString
[0], StringPtr
);
1064 Character
[0] = RIGHT_ONEOF_DELIMITER
;
1065 NewStrCat (OptionString
[0], Character
);
1066 Character
[0] = CHAR_CARRIAGE_RETURN
;
1067 NewStrCat (OptionString
[0], Character
);
1068 FreePool (StringPtr
);
1072 // If valid option more than the max container, skip these options.
1074 if (Index
>= OrderList
->MaxContainers
) {
1079 // Search the other options, try to find the one not in the container.
1081 Link
= GetFirstNode (&Question
->OptionListHead
);
1082 while (!IsNull (&Question
->OptionListHead
, Link
)) {
1083 OneOfOption
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
1084 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
1086 if (FindArrayData (ValueArray
, ValueType
, OneOfOption
->OptionOpCode
->Value
.u64
, NULL
)) {
1090 if (SkipErrorValue
) {
1092 // Not report error, just get the correct option string info.
1094 Character
[0] = LEFT_ONEOF_DELIMITER
;
1095 NewStrCat (OptionString
[0], Character
);
1096 StringPtr
= GetToken (OneOfOption
->OptionOpCode
->Option
, gFormData
->HiiHandle
);
1097 ASSERT (StringPtr
!= NULL
);
1098 NewStrCat (OptionString
[0], StringPtr
);
1099 Character
[0] = RIGHT_ONEOF_DELIMITER
;
1100 NewStrCat (OptionString
[0], Character
);
1101 Character
[0] = CHAR_CARRIAGE_RETURN
;
1102 NewStrCat (OptionString
[0], Character
);
1103 FreePool (StringPtr
);
1108 if (!ValueInvalid
) {
1109 ValueInvalid
= TRUE
;
1111 // Show error message
1114 CreateDialog (&Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
, NULL
);
1115 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1118 // The initial value of the orderedlist is invalid, force to be valid value
1119 // Exit current DisplayForm with new value.
1121 gUserInput
->SelectedStatement
= Question
;
1123 ValueArray
= AllocateCopyPool (Question
->CurrentValue
.BufferLen
, Question
->CurrentValue
.Buffer
);
1124 ASSERT (ValueArray
!= NULL
);
1125 gUserInput
->InputValue
.Buffer
= ValueArray
;
1126 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
1127 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
1130 SetArrayData (ValueArray
, ValueType
, Index
++, OneOfOption
->OptionOpCode
->Value
.u64
);
1134 FreePool (*OptionString
);
1135 *OptionString
= NULL
;
1136 return EFI_NOT_FOUND
;
1141 case EFI_IFR_ONE_OF_OP
:
1143 // Check whether there are Options of this OneOf
1145 if (IsListEmpty (&Question
->OptionListHead
)) {
1152 Status
= GetSelectionInputPopUp (MenuOption
);
1154 *OptionString
= AllocateZeroPool (BufferSize
);
1155 ASSERT (*OptionString
);
1157 OneOfOption
= ValueToOption (Question
, QuestionValue
);
1158 if (OneOfOption
== NULL
) {
1159 if (SkipErrorValue
) {
1161 // Not report error, just get the correct option string info.
1163 Link
= GetFirstNode (&Question
->OptionListHead
);
1164 OneOfOption
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
1167 // Show error message
1170 CreateDialog (&Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
, NULL
);
1171 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1174 // Force the Question value to be valid
1175 // Exit current DisplayForm with new value.
1177 Link
= GetFirstNode (&Question
->OptionListHead
);
1178 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
1180 gUserInput
->InputValue
.Type
= Option
->OptionOpCode
->Type
;
1181 switch (gUserInput
->InputValue
.Type
) {
1182 case EFI_IFR_TYPE_NUM_SIZE_8
:
1183 gUserInput
->InputValue
.Value
.u8
= Option
->OptionOpCode
->Value
.u8
;
1185 case EFI_IFR_TYPE_NUM_SIZE_16
:
1186 CopyMem (&gUserInput
->InputValue
.Value
.u16
, &Option
->OptionOpCode
->Value
.u16
, sizeof (UINT16
));
1188 case EFI_IFR_TYPE_NUM_SIZE_32
:
1189 CopyMem (&gUserInput
->InputValue
.Value
.u32
, &Option
->OptionOpCode
->Value
.u32
, sizeof (UINT32
));
1191 case EFI_IFR_TYPE_NUM_SIZE_64
:
1192 CopyMem (&gUserInput
->InputValue
.Value
.u64
, &Option
->OptionOpCode
->Value
.u64
, sizeof (UINT64
));
1198 gUserInput
->SelectedStatement
= Question
;
1200 FreePool (*OptionString
);
1201 *OptionString
= NULL
;
1202 return EFI_NOT_FOUND
;
1206 Character
[0] = LEFT_ONEOF_DELIMITER
;
1207 NewStrCat (OptionString
[0], Character
);
1208 StringPtr
= GetToken (OneOfOption
->OptionOpCode
->Option
, gFormData
->HiiHandle
);
1209 ASSERT (StringPtr
!= NULL
);
1210 NewStrCat (OptionString
[0], StringPtr
);
1211 Character
[0] = RIGHT_ONEOF_DELIMITER
;
1212 NewStrCat (OptionString
[0], Character
);
1214 FreePool (StringPtr
);
1218 case EFI_IFR_CHECKBOX_OP
:
1221 // Since this is a BOOLEAN operation, flip it upon selection
1223 gUserInput
->InputValue
.Type
= QuestionValue
->Type
;
1224 gUserInput
->InputValue
.Value
.b
= (BOOLEAN
) (QuestionValue
->Value
.b
? FALSE
: TRUE
);
1227 // Perform inconsistent check
1231 *OptionString
= AllocateZeroPool (BufferSize
);
1232 ASSERT (*OptionString
);
1234 *OptionString
[0] = LEFT_CHECKBOX_DELIMITER
;
1236 if (QuestionValue
->Value
.b
) {
1237 *(OptionString
[0] + 1) = CHECK_ON
;
1239 *(OptionString
[0] + 1) = CHECK_OFF
;
1241 *(OptionString
[0] + 2) = RIGHT_CHECKBOX_DELIMITER
;
1245 case EFI_IFR_NUMERIC_OP
:
1250 Status
= GetNumericInput (MenuOption
);
1252 *OptionString
= AllocateZeroPool (BufferSize
);
1253 ASSERT (*OptionString
);
1255 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
1260 PrintFormattedNumber (Question
, FormattedNumber
, 21 * sizeof (CHAR16
));
1261 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
1262 CopyMem (OptionString
[0] + 1, FormattedNumber
, Number
);
1264 *(OptionString
[0] + Number
/ 2) = RIGHT_NUMERIC_DELIMITER
;
1268 case EFI_IFR_DATE_OP
:
1271 // This is similar to numerics
1273 Status
= GetNumericInput (MenuOption
);
1275 *OptionString
= AllocateZeroPool (BufferSize
);
1276 ASSERT (*OptionString
);
1278 switch (MenuOption
->Sequence
) {
1280 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
1281 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Month
);
1282 *(OptionString
[0] + 3) = DATE_SEPARATOR
;
1286 SetUnicodeMem (OptionString
[0], 4, L
' ');
1287 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Day
);
1288 *(OptionString
[0] + 6) = DATE_SEPARATOR
;
1292 SetUnicodeMem (OptionString
[0], 7, L
' ');
1293 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%04d", QuestionValue
->Value
.date
.Year
);
1294 *(OptionString
[0] + 11) = RIGHT_NUMERIC_DELIMITER
;
1300 case EFI_IFR_TIME_OP
:
1303 // This is similar to numerics
1305 Status
= GetNumericInput (MenuOption
);
1307 *OptionString
= AllocateZeroPool (BufferSize
);
1308 ASSERT (*OptionString
);
1310 switch (MenuOption
->Sequence
) {
1312 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
1313 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Hour
);
1314 *(OptionString
[0] + 3) = TIME_SEPARATOR
;
1318 SetUnicodeMem (OptionString
[0], 4, L
' ');
1319 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Minute
);
1320 *(OptionString
[0] + 6) = TIME_SEPARATOR
;
1324 SetUnicodeMem (OptionString
[0], 7, L
' ');
1325 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Second
);
1326 *(OptionString
[0] + 9) = RIGHT_NUMERIC_DELIMITER
;
1332 case EFI_IFR_STRING_OP
:
1334 StringPtr
= AllocateZeroPool (Question
->CurrentValue
.BufferLen
+ sizeof (CHAR16
));
1336 CopyMem(StringPtr
, Question
->CurrentValue
.Buffer
, Question
->CurrentValue
.BufferLen
);
1338 Status
= ReadString (MenuOption
, gPromptForData
, StringPtr
);
1339 if (EFI_ERROR (Status
)) {
1340 FreePool (StringPtr
);
1344 gUserInput
->InputValue
.Buffer
= AllocateCopyPool (Question
->CurrentValue
.BufferLen
, StringPtr
);
1345 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
1346 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
1347 gUserInput
->InputValue
.Value
.string
= HiiSetString(gFormData
->HiiHandle
, gUserInput
->InputValue
.Value
.string
, StringPtr
, NULL
);
1348 FreePool (StringPtr
);
1351 *OptionString
= AllocateZeroPool (BufferSize
);
1352 ASSERT (*OptionString
);
1354 if (((CHAR16
*) Question
->CurrentValue
.Buffer
)[0] == 0x0000) {
1355 *(OptionString
[0]) = '_';
1357 if (Question
->CurrentValue
.BufferLen
< BufferSize
) {
1358 BufferSize
= Question
->CurrentValue
.BufferLen
;
1360 CopyMem (OptionString
[0], (CHAR16
*) Question
->CurrentValue
.Buffer
, BufferSize
);
1365 case EFI_IFR_PASSWORD_OP
:
1367 Status
= PasswordProcess (MenuOption
);
1380 Process the help string: Split StringPtr to several lines of strings stored in
1381 FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
1383 @param StringPtr The entire help string.
1384 @param FormattedString The oupput formatted string.
1385 @param EachLineWidth The max string length of each line in the formatted string.
1386 @param RowCount TRUE: if Question is selected.
1391 IN CHAR16
*StringPtr
,
1392 OUT CHAR16
**FormattedString
,
1393 OUT UINT16
*EachLineWidth
,
1398 CHAR16
*OutputString
;
1403 UINT16 MaxStringLen
;
1414 // Set default help string width.
1416 LineWidth
= (UINT16
) (gHelpBlockWidth
- 1);
1419 // Get row number of the String.
1421 while ((StringLen
= GetLineByWidth (StringPtr
, LineWidth
, &GlyphWidth
, &Index
, &OutputString
)) != 0) {
1422 if (StringLen
> MaxStringLen
) {
1423 MaxStringLen
= StringLen
;
1427 FreePool (OutputString
);
1429 *EachLineWidth
= MaxStringLen
;
1431 *FormattedString
= AllocateZeroPool (TotalRowNum
* MaxStringLen
* sizeof (CHAR16
));
1432 ASSERT (*FormattedString
!= NULL
);
1435 // Generate formatted help string array.
1439 while((StringLen
= GetLineByWidth (StringPtr
, LineWidth
, &GlyphWidth
, &Index
, &OutputString
)) != 0) {
1440 CopyMem (*FormattedString
+ CheckedNum
* MaxStringLen
, OutputString
, StringLen
* sizeof (CHAR16
));
1442 FreePool (OutputString
);