2 Implementation for handling the User Interface option processing.
5 Copyright (c) 2004 - 2011, 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.
20 Process Question Config.
22 @param Selection The UI menu selection.
23 @param Question The Question to be peocessed.
25 @retval EFI_SUCCESS Question Config process success.
26 @retval Other Question Config process fail.
30 ProcessQuestionConfig (
31 IN UI_MENU_SELECTION
*Selection
,
32 IN FORM_BROWSER_STATEMENT
*Question
38 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
40 if (Question
->QuestionConfig
== 0) {
47 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
48 if (ConfigResp
== NULL
) {
53 // Send config to Configuration Driver
55 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
56 if (ConfigAccess
== NULL
) {
57 return EFI_UNSUPPORTED
;
59 Status
= ConfigAccess
->RouteConfig (
70 Search an Option of a Question by its value.
72 @param Question The Question
73 @param OptionValue Value for Option to be searched.
75 @retval Pointer Pointer to the found Option.
76 @retval NULL Option not found.
81 IN FORM_BROWSER_STATEMENT
*Question
,
82 IN EFI_HII_VALUE
*OptionValue
86 QUESTION_OPTION
*Option
;
88 Link
= GetFirstNode (&Question
->OptionListHead
);
89 while (!IsNull (&Question
->OptionListHead
, Link
)) {
90 Option
= QUESTION_OPTION_FROM_LINK (Link
);
92 if (CompareHiiValue (&Option
->Value
, OptionValue
, NULL
) == 0) {
96 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
104 Return data element in an Array by its Index.
106 @param Array The data array.
107 @param Type Type of the data in this array.
108 @param Index Zero based index for data in this array.
110 @retval Value The data to be returned
122 ASSERT (Array
!= NULL
);
126 case EFI_IFR_TYPE_NUM_SIZE_8
:
127 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
130 case EFI_IFR_TYPE_NUM_SIZE_16
:
131 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
134 case EFI_IFR_TYPE_NUM_SIZE_32
:
135 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
138 case EFI_IFR_TYPE_NUM_SIZE_64
:
139 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
151 Set value of a data element in an Array by its Index.
153 @param Array The data array.
154 @param Type Type of the data in this array.
155 @param Index Zero based index for data in this array.
156 @param Value The value to be set.
168 ASSERT (Array
!= NULL
);
171 case EFI_IFR_TYPE_NUM_SIZE_8
:
172 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
175 case EFI_IFR_TYPE_NUM_SIZE_16
:
176 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
179 case EFI_IFR_TYPE_NUM_SIZE_32
:
180 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
183 case EFI_IFR_TYPE_NUM_SIZE_64
:
184 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
194 Print Question Value according to it's storage width and display attributes.
196 @param Question The Question to be printed.
197 @param FormattedNumber Buffer for output string.
198 @param BufferSize The FormattedNumber buffer size in bytes.
200 @retval EFI_SUCCESS Print success.
201 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
205 PrintFormattedNumber (
206 IN FORM_BROWSER_STATEMENT
*Question
,
207 IN OUT CHAR16
*FormattedNumber
,
213 EFI_HII_VALUE
*QuestionValue
;
215 if (BufferSize
< (21 * sizeof (CHAR16
))) {
216 return EFI_BUFFER_TOO_SMALL
;
219 QuestionValue
= &Question
->HiiValue
;
221 Value
= (INT64
) QuestionValue
->Value
.u64
;
222 switch (Question
->Flags
& EFI_IFR_DISPLAY
) {
223 case EFI_IFR_DISPLAY_INT_DEC
:
224 switch (QuestionValue
->Type
) {
225 case EFI_IFR_NUMERIC_SIZE_1
:
226 Value
= (INT64
) ((INT8
) QuestionValue
->Value
.u8
);
229 case EFI_IFR_NUMERIC_SIZE_2
:
230 Value
= (INT64
) ((INT16
) QuestionValue
->Value
.u16
);
233 case EFI_IFR_NUMERIC_SIZE_4
:
234 Value
= (INT64
) ((INT32
) QuestionValue
->Value
.u32
);
237 case EFI_IFR_NUMERIC_SIZE_8
:
250 case EFI_IFR_DISPLAY_UINT_DEC
:
254 case EFI_IFR_DISPLAY_UINT_HEX
:
259 return EFI_UNSUPPORTED
;
263 UnicodeSPrint (FormattedNumber
, BufferSize
, Format
, Value
);
270 Password may be stored as encrypted by Configuration Driver. When change a
271 password, user will be challenged with old password. To validate user input old
272 password, we will send the clear text to Configuration Driver via Callback().
273 Configuration driver is responsible to check the passed in password and return
274 the validation result. If validation pass, state machine in password Callback()
275 will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.
276 After user type in new password twice, Callback() will be invoked to send the
277 new password to Configuration Driver.
279 @param Selection Pointer to UI_MENU_SELECTION.
280 @param MenuOption The MenuOption for this password Question.
281 @param String The clear text of password.
283 @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.
284 @return In state of BROWSER_STATE_VALIDATE_PASSWORD:
285 @retval EFI_SUCCESS Password correct, Browser will prompt for new
287 @retval EFI_NOT_READY Password incorrect, Browser will show error
289 @retval Other Browser will do nothing.
290 @return In state of BROWSER_STATE_SET_PASSWORD:
291 @retval EFI_SUCCESS Set password success.
292 @retval Other Set password failed.
297 IN UI_MENU_SELECTION
*Selection
,
298 IN UI_MENU_OPTION
*MenuOption
,
303 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
304 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
305 EFI_IFR_TYPE_VALUE IfrTypeValue
;
307 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
308 if (ConfigAccess
== NULL
) {
309 return EFI_UNSUPPORTED
;
313 // Prepare password string in HII database
315 if (String
!= NULL
) {
316 IfrTypeValue
.string
= NewString (String
, Selection
->FormSet
->HiiHandle
);
318 IfrTypeValue
.string
= 0;
322 // Send password to Configuration Driver for validation
324 Status
= ConfigAccess
->Callback (
326 EFI_BROWSER_ACTION_CHANGING
,
327 MenuOption
->ThisTag
->QuestionId
,
328 MenuOption
->ThisTag
->HiiValue
.Type
,
334 // Remove password string from HII database
336 if (String
!= NULL
) {
337 DeleteString (IfrTypeValue
.string
, Selection
->FormSet
->HiiHandle
);
345 Display error message for invalid password.
356 // Invalid password, prompt error message
359 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gPassowordInvalid
, gPressEnter
, gEmptyString
);
360 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
365 Process a Question's Option (whether selected or un-selected).
367 @param Selection Pointer to UI_MENU_SELECTION.
368 @param MenuOption The MenuOption for this Question.
369 @param Selected TRUE: if Question is selected.
370 @param OptionString Pointer of the Option String to be displayed.
372 @retval EFI_SUCCESS Question Option process success.
373 @retval Other Question Option process fail.
378 IN UI_MENU_SELECTION
*Selection
,
379 IN UI_MENU_OPTION
*MenuOption
,
381 OUT CHAR16
**OptionString
388 FORM_BROWSER_STATEMENT
*Question
;
389 CHAR16 FormattedNumber
[21];
394 QUESTION_OPTION
*OneOfOption
;
396 EFI_HII_VALUE HiiValue
;
397 EFI_HII_VALUE
*QuestionValue
;
400 QUESTION_OPTION
*Option
;
404 EFI_STRING_ID StringId
;
406 Status
= EFI_SUCCESS
;
409 Character
[1] = L
'\0';
410 *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 // Check whether there are Options of this OrderedList
428 if (IsListEmpty (&Question
->OptionListHead
)) {
432 // Initialize Option value array
434 if (GetArrayData (ValueArray
, ValueType
, 0) == 0) {
435 GetQuestionDefault (Selection
->FormSet
, Selection
->Form
, Question
, 0);
442 Status
= GetSelectionInputPopUp (Selection
, MenuOption
);
445 // We now know how many strings we will have, so we can allocate the
446 // space required for the array or strings.
448 *OptionString
= AllocateZeroPool (Question
->MaxContainers
* BufferSize
);
449 ASSERT (*OptionString
);
451 HiiValue
.Type
= ValueType
;
452 HiiValue
.Value
.u64
= 0;
453 for (Index
= 0; Index
< Question
->MaxContainers
; Index
++) {
454 HiiValue
.Value
.u64
= GetArrayData (ValueArray
, ValueType
, Index
);
455 if (HiiValue
.Value
.u64
== 0) {
457 // Values for the options in ordered lists should never be a 0
462 OneOfOption
= ValueToOption (Question
, &HiiValue
);
463 if (OneOfOption
== NULL
) {
465 // Show error message
468 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
);
469 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
472 // The initial value of the orderedlist is invalid, force to be valid value
474 Link
= GetFirstNode (&Question
->OptionListHead
);
476 while (!IsNull (&Question
->OptionListHead
, Link
) && Index2
< Question
->MaxContainers
) {
477 Option
= QUESTION_OPTION_FROM_LINK (Link
);
478 SetArrayData (ValueArray
, ValueType
, Index2
, Option
->Value
.Value
.u64
);
480 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
482 SetArrayData (ValueArray
, ValueType
, Index2
, 0);
484 Status
= SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
485 UpdateStatusBar (Selection
, NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
487 FreePool (*OptionString
);
488 *OptionString
= NULL
;
489 return EFI_NOT_FOUND
;
493 if ((OneOfOption
->SuppressExpression
!= NULL
) &&
494 (OneOfOption
->SuppressExpression
->Result
.Value
.b
)) {
496 // This option is suppressed
502 Character
[0] = LEFT_ONEOF_DELIMITER
;
503 NewStrCat (OptionString
[0], Character
);
504 StringPtr
= GetToken (OneOfOption
->Text
, Selection
->Handle
);
505 ASSERT (StringPtr
!= NULL
);
506 NewStrCat (OptionString
[0], StringPtr
);
507 Character
[0] = RIGHT_ONEOF_DELIMITER
;
508 NewStrCat (OptionString
[0], Character
);
509 Character
[0] = CHAR_CARRIAGE_RETURN
;
510 NewStrCat (OptionString
[0], Character
);
512 FreePool (StringPtr
);
518 case EFI_IFR_ONE_OF_OP
:
520 // Check whether there are Options of this OneOf
522 if (IsListEmpty (&Question
->OptionListHead
)) {
529 Status
= GetSelectionInputPopUp (Selection
, MenuOption
);
531 *OptionString
= AllocateZeroPool (BufferSize
);
532 ASSERT (*OptionString
);
534 OneOfOption
= ValueToOption (Question
, QuestionValue
);
535 if (OneOfOption
== NULL
) {
537 // Show error message
540 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
);
541 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
544 // Force the Question value to be valid
546 Link
= GetFirstNode (&Question
->OptionListHead
);
547 while (!IsNull (&Question
->OptionListHead
, Link
)) {
548 Option
= QUESTION_OPTION_FROM_LINK (Link
);
550 if ((Option
->SuppressExpression
== NULL
) ||
551 !Option
->SuppressExpression
->Result
.Value
.b
) {
552 CopyMem (QuestionValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
553 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
554 UpdateStatusBar (Selection
, NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
558 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
561 FreePool (*OptionString
);
562 *OptionString
= NULL
;
563 return EFI_NOT_FOUND
;
566 if ((OneOfOption
->SuppressExpression
!= NULL
) &&
567 (OneOfOption
->SuppressExpression
->Result
.Value
.b
)) {
569 // This option is suppressed
578 // Current selected option happen to be suppressed,
579 // enforce to select on a non-suppressed option
581 Link
= GetFirstNode (&Question
->OptionListHead
);
582 while (!IsNull (&Question
->OptionListHead
, Link
)) {
583 OneOfOption
= QUESTION_OPTION_FROM_LINK (Link
);
585 if ((OneOfOption
->SuppressExpression
== NULL
) ||
586 !OneOfOption
->SuppressExpression
->Result
.Value
.b
) {
588 CopyMem (QuestionValue
, &OneOfOption
->Value
, sizeof (EFI_HII_VALUE
));
589 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
590 UpdateStatusBar (Selection
, NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
591 gST
->ConOut
->SetAttribute (gST
->ConOut
, PcdGet8 (PcdBrowserFieldTextColor
) | FIELD_BACKGROUND
);
595 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
600 Character
[0] = LEFT_ONEOF_DELIMITER
;
601 NewStrCat (OptionString
[0], Character
);
602 StringPtr
= GetToken (OneOfOption
->Text
, Selection
->Handle
);
603 ASSERT (StringPtr
!= NULL
);
604 NewStrCat (OptionString
[0], StringPtr
);
605 Character
[0] = RIGHT_ONEOF_DELIMITER
;
606 NewStrCat (OptionString
[0], Character
);
608 FreePool (StringPtr
);
613 case EFI_IFR_CHECKBOX_OP
:
614 *OptionString
= AllocateZeroPool (BufferSize
);
615 ASSERT (*OptionString
);
617 *OptionString
[0] = LEFT_CHECKBOX_DELIMITER
;
621 // Since this is a BOOLEAN operation, flip it upon selection
623 QuestionValue
->Value
.b
= (BOOLEAN
) (QuestionValue
->Value
.b
? FALSE
: TRUE
);
626 // Perform inconsistent check
628 Status
= ValidateQuestion (Selection
->FormSet
, Selection
->Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
629 if (EFI_ERROR (Status
)) {
631 // Inconsistent check fail, restore Question Value
633 QuestionValue
->Value
.b
= (BOOLEAN
) (QuestionValue
->Value
.b
? FALSE
: TRUE
);
634 FreePool (*OptionString
);
635 *OptionString
= NULL
;
640 // Save Question value
642 Status
= SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
643 UpdateStatusBar (Selection
, NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
646 if (QuestionValue
->Value
.b
) {
647 *(OptionString
[0] + 1) = CHECK_ON
;
649 *(OptionString
[0] + 1) = CHECK_OFF
;
651 *(OptionString
[0] + 2) = RIGHT_CHECKBOX_DELIMITER
;
654 case EFI_IFR_NUMERIC_OP
:
659 Status
= GetNumericInput (Selection
, MenuOption
);
661 *OptionString
= AllocateZeroPool (BufferSize
);
662 ASSERT (*OptionString
);
664 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
669 PrintFormattedNumber (Question
, FormattedNumber
, 21 * sizeof (CHAR16
));
670 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
671 CopyMem (OptionString
[0] + 1, FormattedNumber
, Number
);
673 *(OptionString
[0] + Number
/ 2) = RIGHT_NUMERIC_DELIMITER
;
677 case EFI_IFR_DATE_OP
:
680 // This is similar to numerics
682 Status
= GetNumericInput (Selection
, MenuOption
);
684 *OptionString
= AllocateZeroPool (BufferSize
);
685 ASSERT (*OptionString
);
687 switch (MenuOption
->Sequence
) {
689 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
690 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Month
);
691 *(OptionString
[0] + 3) = DATE_SEPARATOR
;
695 SetUnicodeMem (OptionString
[0], 4, L
' ');
696 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Day
);
697 *(OptionString
[0] + 6) = DATE_SEPARATOR
;
701 SetUnicodeMem (OptionString
[0], 7, L
' ');
702 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%04d", QuestionValue
->Value
.date
.Year
);
703 *(OptionString
[0] + 11) = RIGHT_NUMERIC_DELIMITER
;
709 case EFI_IFR_TIME_OP
:
712 // This is similar to numerics
714 Status
= GetNumericInput (Selection
, MenuOption
);
716 *OptionString
= AllocateZeroPool (BufferSize
);
717 ASSERT (*OptionString
);
719 switch (MenuOption
->Sequence
) {
721 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
722 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Hour
);
723 *(OptionString
[0] + 3) = TIME_SEPARATOR
;
727 SetUnicodeMem (OptionString
[0], 4, L
' ');
728 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Minute
);
729 *(OptionString
[0] + 6) = TIME_SEPARATOR
;
733 SetUnicodeMem (OptionString
[0], 7, L
' ');
734 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Second
);
735 *(OptionString
[0] + 9) = RIGHT_NUMERIC_DELIMITER
;
741 case EFI_IFR_STRING_OP
:
743 StringPtr
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
745 CopyMem(StringPtr
, Question
->BufferValue
, Maximum
* sizeof (CHAR16
));
747 Status
= ReadString (MenuOption
, gPromptForData
, StringPtr
);
748 if (!EFI_ERROR (Status
)) {
749 HiiSetString(Selection
->FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, StringPtr
, NULL
);
750 Status
= ValidateQuestion(Selection
->FormSet
, Selection
->Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
751 if (EFI_ERROR (Status
)) {
752 HiiSetString(Selection
->FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
754 CopyMem (Question
->BufferValue
, StringPtr
, Maximum
* sizeof (CHAR16
));
755 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, TRUE
);
757 UpdateStatusBar (Selection
, NV_UPDATE_REQUIRED
, Question
->QuestionFlags
, TRUE
);
761 FreePool (StringPtr
);
763 *OptionString
= AllocateZeroPool (BufferSize
);
764 ASSERT (*OptionString
);
766 if (((CHAR16
*) Question
->BufferValue
)[0] == 0x0000) {
767 *(OptionString
[0]) = '_';
769 if ((Maximum
* sizeof (CHAR16
)) < BufferSize
) {
770 BufferSize
= Maximum
* sizeof (CHAR16
);
772 CopyMem (OptionString
[0], (CHAR16
*) Question
->BufferValue
, BufferSize
);
777 case EFI_IFR_PASSWORD_OP
:
779 StringPtr
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
783 // For interactive passwords, old password is validated by callback
785 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
787 // Use a NULL password to test whether old password is required
790 Status
= PasswordCallback (Selection
, MenuOption
, StringPtr
);
791 if (Status
== EFI_NOT_AVAILABLE_YET
|| Status
== EFI_UNSUPPORTED
) {
793 // Callback is not supported, or
794 // Callback request to terminate password input
796 FreePool (StringPtr
);
800 if (EFI_ERROR (Status
)) {
802 // Old password exist, ask user for the old password
804 Status
= ReadString (MenuOption
, gPromptForPassword
, StringPtr
);
805 if (EFI_ERROR (Status
)) {
806 FreePool (StringPtr
);
811 // Check user input old password
813 Status
= PasswordCallback (Selection
, MenuOption
, StringPtr
);
814 if (EFI_ERROR (Status
)) {
815 if (Status
== EFI_NOT_READY
) {
817 // Typed in old password incorrect
821 Status
= EFI_SUCCESS
;
824 FreePool (StringPtr
);
830 // For non-interactive password, validate old password in local
832 if (*((CHAR16
*) Question
->BufferValue
) != 0) {
834 // There is something there! Prompt for password
836 Status
= ReadString (MenuOption
, gPromptForPassword
, StringPtr
);
837 if (EFI_ERROR (Status
)) {
838 FreePool (StringPtr
);
842 TempString
= AllocateCopyPool ((Maximum
+ 1) * sizeof (CHAR16
), Question
->BufferValue
);
843 ASSERT (TempString
!= NULL
);
845 TempString
[Maximum
] = L
'\0';
847 if (StrCmp (StringPtr
, TempString
) != 0) {
849 // Typed in old password incorrect
853 FreePool (StringPtr
);
854 FreePool (TempString
);
858 FreePool (TempString
);
863 // Ask for new password
865 ZeroMem (StringPtr
, (Maximum
+ 1) * sizeof (CHAR16
));
866 Status
= ReadString (MenuOption
, gPromptForNewPassword
, StringPtr
);
867 if (EFI_ERROR (Status
)) {
869 // Reset state machine for interactive password
871 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
872 PasswordCallback (Selection
, MenuOption
, NULL
);
875 FreePool (StringPtr
);
880 // Confirm new password
882 TempString
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
884 Status
= ReadString (MenuOption
, gConfirmPassword
, TempString
);
885 if (EFI_ERROR (Status
)) {
887 // Reset state machine for interactive password
889 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
890 PasswordCallback (Selection
, MenuOption
, NULL
);
893 FreePool (StringPtr
);
894 FreePool (TempString
);
899 // Compare two typed-in new passwords
901 if (StrCmp (StringPtr
, TempString
) == 0) {
903 // Prepare the Question->HiiValue.Value.string for ValidateQuestion use.
905 if((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
906 StringId
= Question
->HiiValue
.Value
.string
;
907 Question
->HiiValue
.Value
.string
= NewString (StringPtr
, Selection
->FormSet
->HiiHandle
);
909 HiiSetString(Selection
->FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, StringPtr
, NULL
);
912 Status
= ValidateQuestion(Selection
->FormSet
, Selection
->Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
915 // Researve the Question->HiiValue.Value.string.
917 if((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
918 DeleteString(Question
->HiiValue
.Value
.string
, Selection
->FormSet
->HiiHandle
);
919 Question
->HiiValue
.Value
.string
= StringId
;
922 if (EFI_ERROR (Status
)) {
924 // Reset state machine for interactive password
926 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
927 PasswordCallback (Selection
, MenuOption
, NULL
);
930 // Researve the Question->HiiValue.Value.string.
932 HiiSetString(Selection
->FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
936 // Two password match, send it to Configuration Driver
938 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
939 PasswordCallback (Selection
, MenuOption
, StringPtr
);
941 CopyMem (Question
->BufferValue
, StringPtr
, Maximum
* sizeof (CHAR16
));
942 SetQuestionValue (Selection
->FormSet
, Selection
->Form
, Question
, FALSE
);
947 // Reset state machine for interactive password
949 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
950 PasswordCallback (Selection
, MenuOption
, NULL
);
954 // Two password mismatch, prompt error message
957 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, gConfirmError
, gPressEnter
, gEmptyString
);
958 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
961 FreePool (TempString
);
962 FreePool (StringPtr
);
975 Process the help string: Split StringPtr to several lines of strings stored in
976 FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
978 @param StringPtr The entire help string.
979 @param FormattedString The oupput formatted string.
980 @param RowCount TRUE: if Question is selected.
985 IN CHAR16
*StringPtr
,
986 OUT CHAR16
**FormattedString
,
993 // [PrevCurrIndex, CurrIndex) forms a range of a screen-line
998 UINTN VirtualLineCount
;
1000 // GlyphOffset stores glyph width of current screen-line
1004 // GlyphWidth equals to 2 if we meet width directive
1008 // during scanning, we remember the position of last space character
1009 // in case that if next word cannot put in current line, we could restore back to the position
1010 // of last space character
1011 // while we should also remmeber the glyph width of the last space character for restoring
1013 UINTN LastSpaceIndex
;
1014 UINTN LastSpaceGlyphWidth
;
1016 // every time we begin to form a new screen-line, we should remember glyph width of single character
1019 UINTN LineStartGlyphWidth
;
1021 UINTN
*OldIndexArray
;
1023 BlockWidth
= (UINTN
) gHelpBlockWidth
- 1;
1026 // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )
1027 // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want
1028 // to bring the width directive of the last line to current screen-line.
1029 // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line
1030 // different from that of "\wideabcde", we should remember the width directive.
1032 AllocateSize
= 0x20;
1033 IndexArray
= AllocatePool (AllocateSize
* sizeof (UINTN
) * 3);
1034 ASSERT (IndexArray
!= NULL
);
1036 if (*FormattedString
!= NULL
) {
1037 FreePool (*FormattedString
);
1038 *FormattedString
= NULL
;
1041 for (PrevCurrIndex
= 0, CurrIndex
= 0, LineCount
= 0, LastSpaceIndex
= 0,
1042 IndexArray
[0] = 0, GlyphWidth
= 1, GlyphOffset
= 0, LastSpaceGlyphWidth
= 1, LineStartGlyphWidth
= 1;
1043 (StringPtr
[CurrIndex
] != CHAR_NULL
);
1046 if (LineCount
== AllocateSize
) {
1047 AllocateSize
+= 0x10;
1048 OldIndexArray
= IndexArray
;
1049 IndexArray
= AllocatePool (AllocateSize
* sizeof (UINTN
) * 3);
1050 ASSERT (IndexArray
!= NULL
);
1052 CopyMem (IndexArray
, OldIndexArray
, LineCount
* sizeof (UINTN
) * 3);
1053 FreePool (OldIndexArray
);
1055 switch (StringPtr
[CurrIndex
]) {
1059 GlyphWidth
= ((StringPtr
[CurrIndex
] == WIDE_CHAR
) ? 2 : 1);
1060 if (CurrIndex
== 0) {
1061 LineStartGlyphWidth
= GlyphWidth
;
1067 // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN
1071 // Store a range of string as a line
1073 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1074 IndexArray
[LineCount
*3+1] = CurrIndex
;
1075 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1078 // Reset offset and save begin position of line
1081 LineStartGlyphWidth
= GlyphWidth
;
1082 PrevCurrIndex
= CurrIndex
+ 1;
1087 // "\r\n" and "\r" both are handled here
1089 case CHAR_CARRIAGE_RETURN
:
1090 if (StringPtr
[CurrIndex
+ 1] == CHAR_LINEFEED
) {
1092 // next char is '\n'
1094 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1095 IndexArray
[LineCount
*3+1] = CurrIndex
;
1096 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1101 LineStartGlyphWidth
= GlyphWidth
;
1102 PrevCurrIndex
= CurrIndex
+ 1;
1106 // char is space or other char
1109 GlyphOffset
+= GlyphWidth
;
1110 if (GlyphOffset
>= BlockWidth
) {
1111 if (LastSpaceIndex
> PrevCurrIndex
) {
1113 // LastSpaceIndex points to space inside current screen-line,
1114 // restore to LastSpaceIndex
1115 // (Otherwise the word is too long to fit one screen-line, just cut it)
1117 CurrIndex
= LastSpaceIndex
;
1118 GlyphWidth
= LastSpaceGlyphWidth
;
1119 } else if (GlyphOffset
> BlockWidth
) {
1121 // the word is too long to fit one screen-line and we don't get the chance
1122 // of GlyphOffset == BlockWidth because GlyphWidth = 2
1127 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1128 IndexArray
[LineCount
*3+1] = CurrIndex
+ 1;
1129 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1130 LineStartGlyphWidth
= GlyphWidth
;
1133 // Reset offset and save begin position of line
1136 PrevCurrIndex
= CurrIndex
+ 1;
1140 // LastSpaceIndex: remember position of last space
1142 if (StringPtr
[CurrIndex
] == CHAR_SPACE
) {
1143 LastSpaceIndex
= CurrIndex
;
1144 LastSpaceGlyphWidth
= GlyphWidth
;
1150 if (GlyphOffset
> 0) {
1151 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1152 IndexArray
[LineCount
*3+1] = CurrIndex
;
1153 IndexArray
[LineCount
*3+2] = GlyphWidth
;
1157 if (LineCount
== 0) {
1159 // in case we meet null string
1164 // we assume null string's glyph width is 1
1170 VirtualLineCount
= RowCount
* (LineCount
/ RowCount
+ (LineCount
% RowCount
> 0));
1171 *FormattedString
= AllocateZeroPool (VirtualLineCount
* (BlockWidth
+ 1) * sizeof (CHAR16
) * 2);
1172 ASSERT (*FormattedString
!= NULL
);
1174 for (CurrIndex
= 0; CurrIndex
< LineCount
; CurrIndex
++) {
1175 *(*FormattedString
+ CurrIndex
* 2 * (BlockWidth
+ 1)) = (CHAR16
) ((IndexArray
[CurrIndex
*3+2] == 2) ? WIDE_CHAR
: NARROW_CHAR
);
1177 *FormattedString
+ CurrIndex
* 2 * (BlockWidth
+ 1) + 1,
1178 StringPtr
+ IndexArray
[CurrIndex
*3],
1179 IndexArray
[CurrIndex
*3+1]-IndexArray
[CurrIndex
*3]
1183 FreePool (IndexArray
);