2 Implementation for handling the User Interface option processing.
5 Copyright (c) 2004 - 2009, Intel Corporation
6 All rights reserved. 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.
21 Process Question Config.
23 @param Selection The UI menu selection.
24 @param Question The Question to be peocessed.
26 @retval EFI_SUCCESS Question Config process success.
27 @retval Other Question Config process fail.
31 ProcessQuestionConfig (
32 IN UI_MENU_SELECTION
*Selection
,
33 IN FORM_BROWSER_STATEMENT
*Question
39 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
41 if (Question
->QuestionConfig
== 0) {
48 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
49 if (ConfigResp
== NULL
) {
54 // Send config to Configuration Driver
56 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
57 if (ConfigAccess
== NULL
) {
58 return EFI_UNSUPPORTED
;
60 Status
= ConfigAccess
->RouteConfig (
71 Search an Option of a Question by its value.
73 @param Question The Question
74 @param OptionValue Value for Option to be searched.
76 @retval Pointer Pointer to the found Option.
77 @retval NULL Option not found.
82 IN FORM_BROWSER_STATEMENT
*Question
,
83 IN EFI_HII_VALUE
*OptionValue
87 QUESTION_OPTION
*Option
;
89 Link
= GetFirstNode (&Question
->OptionListHead
);
90 while (!IsNull (&Question
->OptionListHead
, Link
)) {
91 Option
= QUESTION_OPTION_FROM_LINK (Link
);
93 if (CompareHiiValue (&Option
->Value
, OptionValue
, NULL
) == 0) {
97 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
105 Return data element in an Array by its Index.
107 @param Array The data array.
108 @param Type Type of the data in this array.
109 @param Index Zero based index for data in this array.
111 @retval Value The data to be returned
123 ASSERT (Array
!= NULL
);
127 case EFI_IFR_TYPE_NUM_SIZE_8
:
128 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
131 case EFI_IFR_TYPE_NUM_SIZE_16
:
132 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
135 case EFI_IFR_TYPE_NUM_SIZE_32
:
136 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
139 case EFI_IFR_TYPE_NUM_SIZE_64
:
140 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
152 Set value of a data element in an Array by its Index.
154 @param Array The data array.
155 @param Type Type of the data in this array.
156 @param Index Zero based index for data in this array.
157 @param Value The value to be set.
169 ASSERT (Array
!= NULL
);
172 case EFI_IFR_TYPE_NUM_SIZE_8
:
173 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
176 case EFI_IFR_TYPE_NUM_SIZE_16
:
177 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
180 case EFI_IFR_TYPE_NUM_SIZE_32
:
181 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
184 case EFI_IFR_TYPE_NUM_SIZE_64
:
185 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
195 Print Question Value according to it's storage width and display attributes.
197 @param Question The Question to be printed.
198 @param FormattedNumber Buffer for output string.
199 @param BufferSize The FormattedNumber buffer size in bytes.
201 @retval EFI_SUCCESS Print success.
202 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
206 PrintFormattedNumber (
207 IN FORM_BROWSER_STATEMENT
*Question
,
208 IN OUT CHAR16
*FormattedNumber
,
214 EFI_HII_VALUE
*QuestionValue
;
216 if (BufferSize
< (21 * sizeof (CHAR16
))) {
217 return EFI_BUFFER_TOO_SMALL
;
220 QuestionValue
= &Question
->HiiValue
;
222 Value
= (INT64
) QuestionValue
->Value
.u64
;
223 switch (Question
->Flags
& EFI_IFR_DISPLAY
) {
224 case EFI_IFR_DISPLAY_INT_DEC
:
225 switch (QuestionValue
->Type
) {
226 case EFI_IFR_NUMERIC_SIZE_1
:
227 Value
= (INT64
) ((INT8
) QuestionValue
->Value
.u8
);
230 case EFI_IFR_NUMERIC_SIZE_2
:
231 Value
= (INT64
) ((INT16
) QuestionValue
->Value
.u16
);
234 case EFI_IFR_NUMERIC_SIZE_4
:
235 Value
= (INT64
) ((INT32
) QuestionValue
->Value
.u32
);
238 case EFI_IFR_NUMERIC_SIZE_8
:
251 case EFI_IFR_DISPLAY_UINT_DEC
:
255 case EFI_IFR_DISPLAY_UINT_HEX
:
260 return EFI_UNSUPPORTED
;
264 UnicodeSPrint (FormattedNumber
, BufferSize
, Format
, Value
);
271 Password may be stored as encrypted by Configuration Driver. When change a
272 password, user will be challenged with old password. To validate user input old
273 password, we will send the clear text to Configuration Driver via Callback().
274 Configuration driver is responsible to check the passed in password and return
275 the validation result. If validation pass, state machine in password Callback()
276 will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.
277 After user type in new password twice, Callback() will be invoked to send the
278 new password to Configuration Driver.
280 @param Selection Pointer to UI_MENU_SELECTION.
281 @param MenuOption The MenuOption for this password Question.
282 @param String The clear text of password.
284 @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.
285 @return In state of BROWSER_STATE_VALIDATE_PASSWORD:
286 @retval EFI_SUCCESS Password correct, Browser will prompt for new
288 @retval EFI_NOT_READY Password incorrect, Browser will show error
290 @retval Other Browser will do nothing.
291 @return In state of BROWSER_STATE_SET_PASSWORD:
292 @retval EFI_SUCCESS Set password success.
293 @retval Other Set password failed.
298 IN UI_MENU_SELECTION
*Selection
,
299 IN UI_MENU_OPTION
*MenuOption
,
304 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
305 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
306 EFI_HII_VALUE
*QuestionValue
;
308 QuestionValue
= &MenuOption
->ThisTag
->HiiValue
;
309 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
310 if (ConfigAccess
== NULL
) {
311 return EFI_UNSUPPORTED
;
315 // Prepare password string in HII database
317 if (String
!= NULL
) {
318 QuestionValue
->Value
.string
= NewString (String
, Selection
->FormSet
->HiiHandle
);
320 QuestionValue
->Value
.string
= 0;
324 // Send password to Configuration Driver for validation
326 Status
= ConfigAccess
->Callback (
328 EFI_BROWSER_ACTION_CHANGING
,
329 MenuOption
->ThisTag
->QuestionId
,
331 &QuestionValue
->Value
,
336 // Remove password string from HII database
338 if (String
!= NULL
) {
339 DeleteString (QuestionValue
->Value
.string
, Selection
->FormSet
->HiiHandle
);
347 Display error message for invalid password.
358 // Invalid password, prompt error message
361 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gPassowordInvalid
, gPressEnter
, gEmptyString
);
362 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
367 Process a Question's Option (whether selected or un-selected).
369 @param Selection Pointer to UI_MENU_SELECTION.
370 @param MenuOption The MenuOption for this Question.
371 @param Selected TRUE: if Question is selected.
372 @param OptionString Pointer of the Option String to be displayed.
374 @retval EFI_SUCCESS Question Option process success.
375 @retval Other Question Option process fail.
380 IN UI_MENU_SELECTION
*Selection
,
381 IN UI_MENU_OPTION
*MenuOption
,
383 OUT CHAR16
**OptionString
390 FORM_BROWSER_STATEMENT
*Question
;
391 CHAR16 FormattedNumber
[21];
396 QUESTION_OPTION
*OneOfOption
;
398 EFI_HII_VALUE HiiValue
;
399 EFI_HII_VALUE
*QuestionValue
;
402 QUESTION_OPTION
*Option
;
407 Status
= EFI_SUCCESS
;
410 Character
[1] = L
'\0';
411 *OptionString
= NULL
;
413 ZeroMem (FormattedNumber
, 21 * sizeof (CHAR16
));
414 BufferSize
= (gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
;
416 Question
= MenuOption
->ThisTag
;
417 QuestionValue
= &Question
->HiiValue
;
418 Maximum
= (UINT16
) Question
->Maximum
;
420 ValueArray
= Question
->BufferValue
;
421 ValueType
= Question
->ValueType
;
423 switch (Question
->Operand
) {
424 case EFI_IFR_ORDERED_LIST_OP
:
426 // Initialize Option value array
428 if (GetArrayData (ValueArray
, ValueType
, 0) == 0) {
429 GetQuestionDefault (Selection
->FormSet
, Selection
->Form
, Question
, 0);
436 Status
= GetSelectionInputPopUp (Selection
, MenuOption
);
439 // We now know how many strings we will have, so we can allocate the
440 // space required for the array or strings.
442 *OptionString
= AllocateZeroPool (Question
->MaxContainers
* BufferSize
);
443 ASSERT (*OptionString
);
445 HiiValue
.Type
= ValueType
;
446 HiiValue
.Value
.u64
= 0;
447 for (Index
= 0; Index
< Question
->MaxContainers
; Index
++) {
448 HiiValue
.Value
.u64
= GetArrayData (ValueArray
, ValueType
, Index
);
449 if (HiiValue
.Value
.u64
== 0) {
451 // Values for the options in ordered lists should never be a 0
456 OneOfOption
= ValueToOption (Question
, &HiiValue
);
457 if (OneOfOption
== NULL
) {
459 // Show error message
462 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
);
463 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
466 // The initial value of the orderedlist is invalid, force to be valid value
468 Link
= GetFirstNode (&Question
->OptionListHead
);
470 while (!IsNull (&Question
->OptionListHead
, Link
) && Index2
< Question
->MaxContainers
) {
471 Option
= QUESTION_OPTION_FROM_LINK (Link
);
472 SetArrayData (ValueArray
, ValueType
, Index2
, Option
->Value
.Value
.u64
);
474 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
476 SetArrayData (ValueArray
, ValueType
, Index2
, 0);
478 Status
= SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
479 UpdateStatusBar (NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
481 FreePool (*OptionString
);
482 *OptionString
= NULL
;
483 return EFI_NOT_FOUND
;
487 if ((OneOfOption
->SuppressExpression
!= NULL
) &&
488 (OneOfOption
->SuppressExpression
->Result
.Value
.b
)) {
490 // This option is suppressed
496 Character
[0] = LEFT_ONEOF_DELIMITER
;
497 NewStrCat (OptionString
[0], Character
);
498 StringPtr
= GetToken (OneOfOption
->Text
, Selection
->Handle
);
499 NewStrCat (OptionString
[0], StringPtr
);
500 Character
[0] = RIGHT_ONEOF_DELIMITER
;
501 NewStrCat (OptionString
[0], Character
);
502 Character
[0] = CHAR_CARRIAGE_RETURN
;
503 NewStrCat (OptionString
[0], Character
);
505 FreePool (StringPtr
);
511 case EFI_IFR_ONE_OF_OP
:
516 Status
= GetSelectionInputPopUp (Selection
, MenuOption
);
518 *OptionString
= AllocateZeroPool (BufferSize
);
519 ASSERT (*OptionString
);
521 OneOfOption
= ValueToOption (Question
, QuestionValue
);
522 if (OneOfOption
== NULL
) {
524 // Show error message
527 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
);
528 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
531 // Force the Question value to be valid
533 Link
= GetFirstNode (&Question
->OptionListHead
);
534 while (!IsNull (&Question
->OptionListHead
, Link
)) {
535 Option
= QUESTION_OPTION_FROM_LINK (Link
);
537 if ((Option
->SuppressExpression
== NULL
) ||
538 !Option
->SuppressExpression
->Result
.Value
.b
) {
539 CopyMem (QuestionValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
540 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
541 UpdateStatusBar (NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
545 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
548 FreePool (*OptionString
);
549 *OptionString
= NULL
;
550 return EFI_NOT_FOUND
;
553 if ((OneOfOption
->SuppressExpression
!= NULL
) &&
554 (OneOfOption
->SuppressExpression
->Result
.Value
.b
)) {
556 // This option is suppressed
565 // Current selected option happen to be suppressed,
566 // enforce to select on a non-suppressed option
568 Link
= GetFirstNode (&Question
->OptionListHead
);
569 while (!IsNull (&Question
->OptionListHead
, Link
)) {
570 OneOfOption
= QUESTION_OPTION_FROM_LINK (Link
);
572 if ((OneOfOption
->SuppressExpression
== NULL
) ||
573 !OneOfOption
->SuppressExpression
->Result
.Value
.b
) {
575 CopyMem (QuestionValue
, &OneOfOption
->Value
, sizeof (EFI_HII_VALUE
));
576 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
577 UpdateStatusBar (NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
578 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
582 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
587 Character
[0] = LEFT_ONEOF_DELIMITER
;
588 NewStrCat (OptionString
[0], Character
);
589 StringPtr
= GetToken (OneOfOption
->Text
, Selection
->Handle
);
590 NewStrCat (OptionString
[0], StringPtr
);
591 Character
[0] = RIGHT_ONEOF_DELIMITER
;
592 NewStrCat (OptionString
[0], Character
);
594 FreePool (StringPtr
);
599 case EFI_IFR_CHECKBOX_OP
:
600 *OptionString
= AllocateZeroPool (BufferSize
);
601 ASSERT (*OptionString
);
603 *OptionString
[0] = LEFT_CHECKBOX_DELIMITER
;
607 // Since this is a BOOLEAN operation, flip it upon selection
609 QuestionValue
->Value
.b
= (BOOLEAN
) (QuestionValue
->Value
.b
? FALSE
: TRUE
);
612 // Perform inconsistent check
614 Status
= ValidateQuestion (Selection
->FormSet
, Selection
->Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
615 if (EFI_ERROR (Status
)) {
617 // Inconsistent check fail, restore Question Value
619 QuestionValue
->Value
.b
= (BOOLEAN
) (QuestionValue
->Value
.b
? FALSE
: TRUE
);
620 FreePool (*OptionString
);
621 *OptionString
= NULL
;
626 // Save Question value
628 Status
= SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
629 UpdateStatusBar (NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
632 if (QuestionValue
->Value
.b
) {
633 *(OptionString
[0] + 1) = CHECK_ON
;
635 *(OptionString
[0] + 1) = CHECK_OFF
;
637 *(OptionString
[0] + 2) = RIGHT_CHECKBOX_DELIMITER
;
640 case EFI_IFR_NUMERIC_OP
:
645 Status
= GetNumericInput (Selection
, MenuOption
);
647 *OptionString
= AllocateZeroPool (BufferSize
);
648 ASSERT (*OptionString
);
650 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
655 PrintFormattedNumber (Question
, FormattedNumber
, 21 * sizeof (CHAR16
));
656 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
657 CopyMem (OptionString
[0] + 1, FormattedNumber
, Number
);
659 *(OptionString
[0] + Number
/ 2) = RIGHT_NUMERIC_DELIMITER
;
663 case EFI_IFR_DATE_OP
:
666 // This is similar to numerics
668 Status
= GetNumericInput (Selection
, MenuOption
);
670 *OptionString
= AllocateZeroPool (BufferSize
);
671 ASSERT (*OptionString
);
673 switch (MenuOption
->Sequence
) {
675 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
676 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Month
);
677 *(OptionString
[0] + 3) = DATE_SEPARATOR
;
681 SetUnicodeMem (OptionString
[0], 4, L
' ');
682 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Day
);
683 *(OptionString
[0] + 6) = DATE_SEPARATOR
;
687 SetUnicodeMem (OptionString
[0], 7, L
' ');
688 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%4d", QuestionValue
->Value
.date
.Year
);
689 *(OptionString
[0] + 11) = RIGHT_NUMERIC_DELIMITER
;
695 case EFI_IFR_TIME_OP
:
698 // This is similar to numerics
700 Status
= GetNumericInput (Selection
, MenuOption
);
702 *OptionString
= AllocateZeroPool (BufferSize
);
703 ASSERT (*OptionString
);
705 switch (MenuOption
->Sequence
) {
707 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
708 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Hour
);
709 *(OptionString
[0] + 3) = TIME_SEPARATOR
;
713 SetUnicodeMem (OptionString
[0], 4, L
' ');
714 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Minute
);
715 *(OptionString
[0] + 6) = TIME_SEPARATOR
;
719 SetUnicodeMem (OptionString
[0], 7, L
' ');
720 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Second
);
721 *(OptionString
[0] + 9) = RIGHT_NUMERIC_DELIMITER
;
727 case EFI_IFR_STRING_OP
:
729 StringPtr
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
732 Status
= ReadString (MenuOption
, gPromptForData
, StringPtr
);
733 if (!EFI_ERROR (Status
)) {
734 CopyMem (Question
->BufferValue
, StringPtr
, Maximum
* sizeof (CHAR16
));
735 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
737 UpdateStatusBar (NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
740 FreePool (StringPtr
);
742 *OptionString
= AllocateZeroPool (BufferSize
);
743 ASSERT (*OptionString
);
745 if (((CHAR16
*) Question
->BufferValue
)[0] == 0x0000) {
746 *(OptionString
[0]) = '_';
748 if ((Maximum
* sizeof (CHAR16
)) < BufferSize
) {
749 BufferSize
= Maximum
* sizeof (CHAR16
);
751 CopyMem (OptionString
[0], (CHAR16
*) Question
->BufferValue
, BufferSize
);
756 case EFI_IFR_PASSWORD_OP
:
758 StringPtr
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
762 // For interactive passwords, old password is validated by callback
764 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
766 // Use a NULL password to test whether old password is required
769 Status
= PasswordCallback (Selection
, MenuOption
, StringPtr
);
770 if (Status
== EFI_NOT_AVAILABLE_YET
) {
772 // Callback request to terminate password input
774 FreePool (StringPtr
);
778 if (EFI_ERROR (Status
)) {
780 // Old password exist, ask user for the old password
782 Status
= ReadString (MenuOption
, gPromptForPassword
, StringPtr
);
783 if (EFI_ERROR (Status
)) {
784 FreePool (StringPtr
);
789 // Check user input old password
791 Status
= PasswordCallback (Selection
, MenuOption
, StringPtr
);
792 if (EFI_ERROR (Status
)) {
793 if (Status
== EFI_NOT_READY
) {
795 // Typed in old password incorrect
799 Status
= EFI_SUCCESS
;
802 FreePool (StringPtr
);
808 // For non-interactive password, validate old password in local
810 if (*((CHAR16
*) Question
->BufferValue
) != 0) {
812 // There is something there! Prompt for password
814 Status
= ReadString (MenuOption
, gPromptForPassword
, StringPtr
);
815 if (EFI_ERROR (Status
)) {
816 FreePool (StringPtr
);
820 TempString
= AllocateCopyPool ((Maximum
+ 1) * sizeof (CHAR16
), Question
->BufferValue
);
821 ASSERT (TempString
!= NULL
);
823 TempString
[Maximum
] = L
'\0';
825 if (StrCmp (StringPtr
, TempString
) != 0) {
827 // Typed in old password incorrect
831 FreePool (StringPtr
);
832 FreePool (TempString
);
836 FreePool (TempString
);
841 // Ask for new password
843 ZeroMem (StringPtr
, (Maximum
+ 1) * sizeof (CHAR16
));
844 Status
= ReadString (MenuOption
, gPromptForNewPassword
, StringPtr
);
845 if (EFI_ERROR (Status
)) {
847 // Reset state machine for interactive password
849 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
850 PasswordCallback (Selection
, MenuOption
, NULL
);
853 FreePool (StringPtr
);
858 // Confirm new password
860 TempString
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
862 Status
= ReadString (MenuOption
, gConfirmPassword
, TempString
);
863 if (EFI_ERROR (Status
)) {
865 // Reset state machine for interactive password
867 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
868 PasswordCallback (Selection
, MenuOption
, NULL
);
871 FreePool (StringPtr
);
872 FreePool (TempString
);
877 // Compare two typed-in new passwords
879 if (StrCmp (StringPtr
, TempString
) == 0) {
881 // Two password match, send it to Configuration Driver
883 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
884 PasswordCallback (Selection
, MenuOption
, StringPtr
);
886 CopyMem (Question
->BufferValue
, StringPtr
, Maximum
* sizeof (CHAR16
));
887 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, FALSE
);
891 // Reset state machine for interactive password
893 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
894 PasswordCallback (Selection
, MenuOption
, NULL
);
898 // Two password mismatch, prompt error message
901 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gConfirmError
, gPressEnter
, gEmptyString
);
902 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
905 FreePool (TempString
);
906 FreePool (StringPtr
);
919 Process the help string: Split StringPtr to several lines of strings stored in
920 FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
922 @param StringPtr The entire help string.
923 @param FormattedString The oupput formatted string.
924 @param RowCount TRUE: if Question is selected.
929 IN CHAR16
*StringPtr
,
930 OUT CHAR16
**FormattedString
,
937 // [PrevCurrIndex, CurrIndex) forms a range of a screen-line
942 UINTN VirtualLineCount
;
944 // GlyphOffset stores glyph width of current screen-line
948 // GlyphWidth equals to 2 if we meet width directive
952 // during scanning, we remember the position of last space character
953 // in case that if next word cannot put in current line, we could restore back to the position
954 // of last space character
955 // while we should also remmeber the glyph width of the last space character for restoring
957 UINTN LastSpaceIndex
;
958 UINTN LastSpaceGlyphWidth
;
960 // every time we begin to form a new screen-line, we should remember glyph width of single character
963 UINTN LineStartGlyphWidth
;
965 UINTN
*OldIndexArray
;
967 BlockWidth
= (UINTN
) gHelpBlockWidth
- 1;
970 // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )
971 // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want
972 // to bring the width directive of the last line to current screen-line.
973 // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line
974 // different from that of "\wideabcde", we should remember the width directive.
977 IndexArray
= AllocatePool (AllocateSize
* sizeof (UINTN
) * 3);
978 ASSERT (IndexArray
!= NULL
);
980 if (*FormattedString
!= NULL
) {
981 FreePool (*FormattedString
);
982 *FormattedString
= NULL
;
985 for (PrevCurrIndex
= 0, CurrIndex
= 0, LineCount
= 0, LastSpaceIndex
= 0,
986 IndexArray
[0] = 0, GlyphWidth
= 1, GlyphOffset
= 0, LastSpaceGlyphWidth
= 1, LineStartGlyphWidth
= 1;
987 (StringPtr
[CurrIndex
] != CHAR_NULL
);
990 if (LineCount
== AllocateSize
) {
991 AllocateSize
+= 0x10;
992 OldIndexArray
= IndexArray
;
993 IndexArray
= AllocatePool (AllocateSize
* sizeof (UINTN
) * 3);
994 ASSERT (IndexArray
!= NULL
);
996 CopyMem (IndexArray
, OldIndexArray
, LineCount
* sizeof (UINTN
) * 3);
997 FreePool (OldIndexArray
);
999 switch (StringPtr
[CurrIndex
]) {
1003 GlyphWidth
= ((StringPtr
[CurrIndex
] == WIDE_CHAR
) ? 2 : 1);
1004 if (CurrIndex
== 0) {
1005 LineStartGlyphWidth
= GlyphWidth
;
1011 // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN
1015 // Store a range of string as a line
1017 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1018 IndexArray
[LineCount
*3+1] = CurrIndex
;
1019 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1022 // Reset offset and save begin position of line
1025 LineStartGlyphWidth
= GlyphWidth
;
1026 PrevCurrIndex
= CurrIndex
+ 1;
1031 // "\r\n" and "\r" both are handled here
1033 case CHAR_CARRIAGE_RETURN
:
1034 if (StringPtr
[CurrIndex
+ 1] == CHAR_LINEFEED
) {
1036 // next char is '\n'
1038 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1039 IndexArray
[LineCount
*3+1] = CurrIndex
;
1040 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1045 LineStartGlyphWidth
= GlyphWidth
;
1046 PrevCurrIndex
= CurrIndex
+ 1;
1050 // char is space or other char
1053 GlyphOffset
+= GlyphWidth
;
1054 if (GlyphOffset
>= BlockWidth
) {
1055 if (LastSpaceIndex
> PrevCurrIndex
) {
1057 // LastSpaceIndex points to space inside current screen-line,
1058 // restore to LastSpaceIndex
1059 // (Otherwise the word is too long to fit one screen-line, just cut it)
1061 CurrIndex
= LastSpaceIndex
;
1062 GlyphWidth
= LastSpaceGlyphWidth
;
1063 } else if (GlyphOffset
> BlockWidth
) {
1065 // the word is too long to fit one screen-line and we don't get the chance
1066 // of GlyphOffset == BlockWidth because GlyphWidth = 2
1071 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1072 IndexArray
[LineCount
*3+1] = CurrIndex
+ 1;
1073 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1074 LineStartGlyphWidth
= GlyphWidth
;
1077 // Reset offset and save begin position of line
1080 PrevCurrIndex
= CurrIndex
+ 1;
1084 // LastSpaceIndex: remember position of last space
1086 if (StringPtr
[CurrIndex
] == CHAR_SPACE
) {
1087 LastSpaceIndex
= CurrIndex
;
1088 LastSpaceGlyphWidth
= GlyphWidth
;
1094 if (GlyphOffset
> 0) {
1095 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1096 IndexArray
[LineCount
*3+1] = CurrIndex
;
1097 IndexArray
[LineCount
*3+2] = GlyphWidth
;
1101 if (LineCount
== 0) {
1103 // in case we meet null string
1108 // we assume null string's glyph width is 1
1114 VirtualLineCount
= RowCount
* (LineCount
/ RowCount
+ (LineCount
% RowCount
> 0));
1115 *FormattedString
= AllocateZeroPool (VirtualLineCount
* (BlockWidth
+ 1) * sizeof (CHAR16
) * 2);
1116 ASSERT (*FormattedString
!= NULL
);
1118 for (CurrIndex
= 0; CurrIndex
< LineCount
; CurrIndex
++) {
1119 *(*FormattedString
+ CurrIndex
* 2 * (BlockWidth
+ 1)) = (CHAR16
) ((IndexArray
[CurrIndex
*3+2] == 2) ? WIDE_CHAR
: NARROW_CHAR
);
1121 *FormattedString
+ CurrIndex
* 2 * (BlockWidth
+ 1) + 1,
1122 StringPtr
+ IndexArray
[CurrIndex
*3],
1123 IndexArray
[CurrIndex
*3+1]-IndexArray
[CurrIndex
*3]
1127 FreePool (IndexArray
);