VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c@ 89989

Last change on this file since 89989 was 89983, checked in by vboxsync, 4 years ago

Devices/EFI: Merge edk-stable202105 and openssl 1.1.1j and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 45.3 KB
Line 
1/** @file
2Implementation for handling the User Interface option processing.
3
4
5Copyright (c) 2004 - 2020, Intel Corporation. All rights reserved.<BR>
6SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include "FormDisplay.h"
11
12#define MAX_TIME_OUT_LEN 0x10
13
14/**
15 Concatenate a narrow string to another string.
16
17 @param Destination The destination string.
18 @param DestMax The Max length of destination string.
19 @param Source The source string. The string to be concatenated.
20 to the end of Destination.
21
22**/
23VOID
24NewStrCat (
25 IN OUT CHAR16 *Destination,
26 IN UINTN DestMax,
27 IN CHAR16 *Source
28 )
29{
30 UINTN Length;
31
32 for (Length = 0; Destination[Length] != 0; Length++)
33 ;
34
35 //
36 // We now have the length of the original string
37 // We can safely assume for now that we are concatenating a narrow value to this string.
38 // For instance, the string is "XYZ" and cat'ing ">"
39 // If this assumption changes, we need to make this routine a bit more complex
40 //
41 Destination[Length] = NARROW_CHAR;
42 Length++;
43
44 StrCpyS (Destination + Length, DestMax - Length, Source);
45}
46
47/**
48 Get UINT64 type value.
49
50 @param Value Input Hii value.
51
52 @retval UINT64 Return the UINT64 type value.
53
54**/
55UINT64
56HiiValueToUINT64 (
57 IN EFI_HII_VALUE *Value
58 )
59{
60 UINT64 RetVal;
61
62 RetVal = 0;
63
64 switch (Value->Type) {
65 case EFI_IFR_TYPE_NUM_SIZE_8:
66 RetVal = Value->Value.u8;
67 break;
68
69 case EFI_IFR_TYPE_NUM_SIZE_16:
70 RetVal = Value->Value.u16;
71 break;
72
73 case EFI_IFR_TYPE_NUM_SIZE_32:
74 RetVal = Value->Value.u32;
75 break;
76
77 case EFI_IFR_TYPE_BOOLEAN:
78 RetVal = Value->Value.b;
79 break;
80
81 case EFI_IFR_TYPE_DATE:
82 RetVal = *(UINT64*) &Value->Value.date;
83 break;
84
85 case EFI_IFR_TYPE_TIME:
86 RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;
87 break;
88
89 default:
90 RetVal = Value->Value.u64;
91 break;
92 }
93
94 return RetVal;
95}
96
97/**
98 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
99
100 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
101 EFI_IFR_TYPE_BUFFER when do the value compare.
102
103 @param Value Expression value to compare on.
104
105 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
106 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
107
108**/
109BOOLEAN
110IsTypeInBuffer (
111 IN EFI_HII_VALUE *Value
112 )
113{
114 switch (Value->Type) {
115 case EFI_IFR_TYPE_BUFFER:
116 case EFI_IFR_TYPE_DATE:
117 case EFI_IFR_TYPE_TIME:
118 case EFI_IFR_TYPE_REF:
119 return TRUE;
120
121 default:
122 return FALSE;
123 }
124}
125
126/**
127 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
128
129 @param Value Expression value to compare on.
130
131 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
132 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
133
134**/
135BOOLEAN
136IsTypeInUINT64 (
137 IN EFI_HII_VALUE *Value
138 )
139{
140 switch (Value->Type) {
141 case EFI_IFR_TYPE_NUM_SIZE_8:
142 case EFI_IFR_TYPE_NUM_SIZE_16:
143 case EFI_IFR_TYPE_NUM_SIZE_32:
144 case EFI_IFR_TYPE_NUM_SIZE_64:
145 case EFI_IFR_TYPE_BOOLEAN:
146 return TRUE;
147
148 default:
149 return FALSE;
150 }
151}
152
153/**
154 Return the buffer length and buffer pointer for this value.
155
156 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
157 EFI_IFR_TYPE_BUFFER when do the value compare.
158
159 @param Value Expression value to compare on.
160 @param Buf Return the buffer pointer.
161 @param BufLen Return the buffer length.
162
163**/
164VOID
165GetBufAndLenForValue (
166 IN EFI_HII_VALUE *Value,
167 OUT UINT8 **Buf,
168 OUT UINT16 *BufLen
169 )
170{
171 switch (Value->Type) {
172 case EFI_IFR_TYPE_BUFFER:
173 *Buf = Value->Buffer;
174 *BufLen = Value->BufferLen;
175 break;
176
177 case EFI_IFR_TYPE_DATE:
178 *Buf = (UINT8 *) (&Value->Value.date);
179 *BufLen = (UINT16) sizeof (EFI_HII_DATE);
180 break;
181
182 case EFI_IFR_TYPE_TIME:
183 *Buf = (UINT8 *) (&Value->Value.time);
184 *BufLen = (UINT16) sizeof (EFI_HII_TIME);
185 break;
186
187 case EFI_IFR_TYPE_REF:
188 *Buf = (UINT8 *) (&Value->Value.ref);
189 *BufLen = (UINT16) sizeof (EFI_HII_REF);
190 break;
191
192 default:
193 *Buf = NULL;
194 *BufLen = 0;
195 }
196}
197
198/**
199 Compare two Hii value.
200
201 @param Value1 Expression value to compare on left-hand.
202 @param Value2 Expression value to compare on right-hand.
203 @param Result Return value after compare.
204 retval 0 Two operators equal.
205 return Positive value if Value1 is greater than Value2.
206 retval Negative value if Value1 is less than Value2.
207 @param HiiHandle Only required for string compare.
208
209 @retval other Could not perform compare on two values.
210 @retval EFI_SUCCESS Compare the value success.
211
212**/
213EFI_STATUS
214CompareHiiValue (
215 IN EFI_HII_VALUE *Value1,
216 IN EFI_HII_VALUE *Value2,
217 OUT INTN *Result,
218 IN EFI_HII_HANDLE HiiHandle OPTIONAL
219 )
220{
221 INT64 Temp64;
222 CHAR16 *Str1;
223 CHAR16 *Str2;
224 UINTN Len;
225 UINT8 *Buf1;
226 UINT16 Buf1Len;
227 UINT8 *Buf2;
228 UINT16 Buf2Len;
229
230 if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {
231 if (Value1->Value.string == 0 || Value2->Value.string == 0) {
232 //
233 // StringId 0 is reserved
234 //
235 return EFI_INVALID_PARAMETER;
236 }
237
238 if (Value1->Value.string == Value2->Value.string) {
239 *Result = 0;
240 return EFI_SUCCESS;
241 }
242
243 Str1 = GetToken (Value1->Value.string, HiiHandle);
244 if (Str1 == NULL) {
245 //
246 // String not found
247 //
248 return EFI_NOT_FOUND;
249 }
250
251 Str2 = GetToken (Value2->Value.string, HiiHandle);
252 if (Str2 == NULL) {
253 FreePool (Str1);
254 return EFI_NOT_FOUND;
255 }
256
257 *Result = StrCmp (Str1, Str2);
258
259 FreePool (Str1);
260 FreePool (Str2);
261
262 return EFI_SUCCESS;
263 }
264
265 //
266 // Take types(date, time, ref, buffer) as buffer
267 //
268 if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {
269 GetBufAndLenForValue(Value1, &Buf1, &Buf1Len);
270 GetBufAndLenForValue(Value2, &Buf2, &Buf2Len);
271
272 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;
273 *Result = CompareMem (Buf1, Buf2, Len);
274 if ((*Result == 0) && (Buf1Len != Buf2Len)) {
275 //
276 // In this case, means base on samll number buffer, the data is same
277 // So which value has more data, which value is bigger.
278 //
279 *Result = Buf1Len > Buf2Len ? 1 : -1;
280 }
281 return EFI_SUCCESS;
282 }
283
284 //
285 // Take remain types(integer, boolean, date/time) as integer
286 //
287 if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {
288 Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);
289 if (Temp64 > 0) {
290 *Result = 1;
291 } else if (Temp64 < 0) {
292 *Result = -1;
293 } else {
294 *Result = 0;
295 }
296 return EFI_SUCCESS;
297 }
298
299 return EFI_UNSUPPORTED;
300}
301
302/**
303 Search an Option of a Question by its value.
304
305 @param Question The Question
306 @param OptionValue Value for Option to be searched.
307
308 @retval Pointer Pointer to the found Option.
309 @retval NULL Option not found.
310
311**/
312DISPLAY_QUESTION_OPTION *
313ValueToOption (
314 IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
315 IN EFI_HII_VALUE *OptionValue
316 )
317{
318 LIST_ENTRY *Link;
319 DISPLAY_QUESTION_OPTION *Option;
320 INTN Result;
321 EFI_HII_VALUE Value;
322
323 Link = GetFirstNode (&Question->OptionListHead);
324 while (!IsNull (&Question->OptionListHead, Link)) {
325 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
326
327 ZeroMem (&Value, sizeof (EFI_HII_VALUE));
328 Value.Type = Option->OptionOpCode->Type;
329 CopyMem (&Value.Value, &Option->OptionOpCode->Value, Option->OptionOpCode->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
330
331 if ((CompareHiiValue (&Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
332 return Option;
333 }
334
335 Link = GetNextNode (&Question->OptionListHead, Link);
336 }
337
338 return NULL;
339}
340
341
342/**
343 Return data element in an Array by its Index.
344
345 @param Array The data array.
346 @param Type Type of the data in this array.
347 @param Index Zero based index for data in this array.
348
349 @retval Value The data to be returned
350
351**/
352UINT64
353GetArrayData (
354 IN VOID *Array,
355 IN UINT8 Type,
356 IN UINTN Index
357 )
358{
359 UINT64 Data;
360
361 ASSERT (Array != NULL);
362
363 Data = 0;
364 switch (Type) {
365 case EFI_IFR_TYPE_NUM_SIZE_8:
366 Data = (UINT64) *(((UINT8 *) Array) + Index);
367 break;
368
369 case EFI_IFR_TYPE_NUM_SIZE_16:
370 Data = (UINT64) *(((UINT16 *) Array) + Index);
371 break;
372
373 case EFI_IFR_TYPE_NUM_SIZE_32:
374 Data = (UINT64) *(((UINT32 *) Array) + Index);
375 break;
376
377 case EFI_IFR_TYPE_NUM_SIZE_64:
378 Data = (UINT64) *(((UINT64 *) Array) + Index);
379 break;
380
381 default:
382 break;
383 }
384
385 return Data;
386}
387
388
389/**
390 Set value of a data element in an Array by its Index.
391
392 @param Array The data array.
393 @param Type Type of the data in this array.
394 @param Index Zero based index for data in this array.
395 @param Value The value to be set.
396
397**/
398VOID
399SetArrayData (
400 IN VOID *Array,
401 IN UINT8 Type,
402 IN UINTN Index,
403 IN UINT64 Value
404 )
405{
406
407 ASSERT (Array != NULL);
408
409 switch (Type) {
410 case EFI_IFR_TYPE_NUM_SIZE_8:
411 *(((UINT8 *) Array) + Index) = (UINT8) Value;
412 break;
413
414 case EFI_IFR_TYPE_NUM_SIZE_16:
415 *(((UINT16 *) Array) + Index) = (UINT16) Value;
416 break;
417
418 case EFI_IFR_TYPE_NUM_SIZE_32:
419 *(((UINT32 *) Array) + Index) = (UINT32) Value;
420 break;
421
422 case EFI_IFR_TYPE_NUM_SIZE_64:
423 *(((UINT64 *) Array) + Index) = (UINT64) Value;
424 break;
425
426 default:
427 break;
428 }
429}
430
431/**
432 Check whether this value already in the array, if yes, return the index.
433
434 @param Array The data array.
435 @param Type Type of the data in this array.
436 @param Value The value to be find.
437 @param Index The index in the array which has same value with Value.
438
439 @retval TRUE Found the value in the array.
440 @retval FALSE Not found the value.
441
442**/
443BOOLEAN
444FindArrayData (
445 IN VOID *Array,
446 IN UINT8 Type,
447 IN UINT64 Value,
448 OUT UINTN *Index OPTIONAL
449 )
450{
451 UINTN Count;
452 UINT64 TmpValue;
453 UINT64 ValueComp;
454
455 ASSERT (Array != NULL);
456
457 Count = 0;
458 TmpValue = 0;
459
460 switch (Type) {
461 case EFI_IFR_TYPE_NUM_SIZE_8:
462 ValueComp = (UINT8) Value;
463 break;
464
465 case EFI_IFR_TYPE_NUM_SIZE_16:
466 ValueComp = (UINT16) Value;
467 break;
468
469 case EFI_IFR_TYPE_NUM_SIZE_32:
470 ValueComp = (UINT32) Value;
471 break;
472
473 case EFI_IFR_TYPE_NUM_SIZE_64:
474 ValueComp = (UINT64) Value;
475 break;
476
477 default:
478 ValueComp = 0;
479 break;
480 }
481
482 while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {
483 if (ValueComp == TmpValue) {
484 if (Index != NULL) {
485 *Index = Count;
486 }
487 return TRUE;
488 }
489
490 Count ++;
491 }
492
493 return FALSE;
494}
495
496/**
497 Print Question Value according to it's storage width and display attributes.
498
499 @param Question The Question to be printed.
500 @param FormattedNumber Buffer for output string.
501 @param BufferSize The FormattedNumber buffer size in bytes.
502
503 @retval EFI_SUCCESS Print success.
504 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
505
506**/
507EFI_STATUS
508PrintFormattedNumber (
509 IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
510 IN OUT CHAR16 *FormattedNumber,
511 IN UINTN BufferSize
512 )
513{
514 INT64 Value;
515 CHAR16 *Format;
516 EFI_HII_VALUE *QuestionValue;
517 EFI_IFR_NUMERIC *NumericOp;
518
519 if (BufferSize < (21 * sizeof (CHAR16))) {
520 return EFI_BUFFER_TOO_SMALL;
521 }
522
523 QuestionValue = &Question->CurrentValue;
524 NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;
525
526 Value = (INT64) QuestionValue->Value.u64;
527 switch (NumericOp->Flags & EFI_IFR_DISPLAY) {
528 case EFI_IFR_DISPLAY_INT_DEC:
529 switch (QuestionValue->Type) {
530 case EFI_IFR_NUMERIC_SIZE_1:
531 Value = (INT64) ((INT8) QuestionValue->Value.u8);
532 break;
533
534 case EFI_IFR_NUMERIC_SIZE_2:
535 Value = (INT64) ((INT16) QuestionValue->Value.u16);
536 break;
537
538 case EFI_IFR_NUMERIC_SIZE_4:
539 Value = (INT64) ((INT32) QuestionValue->Value.u32);
540 break;
541
542 case EFI_IFR_NUMERIC_SIZE_8:
543 default:
544 break;
545 }
546
547 if (Value < 0) {
548 Value = -Value;
549 Format = L"-%ld";
550 } else {
551 Format = L"%ld";
552 }
553 break;
554
555 case EFI_IFR_DISPLAY_UINT_DEC:
556 Format = L"%ld";
557 break;
558
559 case EFI_IFR_DISPLAY_UINT_HEX:
560 Format = L"%lx";
561 break;
562
563 default:
564 return EFI_UNSUPPORTED;
565 }
566
567 UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);
568
569 return EFI_SUCCESS;
570}
571
572
573/**
574 Draw a pop up windows based on the dimension, number of lines and
575 strings specified.
576
577 @param RequestedWidth The width of the pop-up.
578 @param NumberOfLines The number of lines.
579 @param Marker The variable argument list for the list of string to be printed.
580
581**/
582VOID
583CreateSharedPopUp (
584 IN UINTN RequestedWidth,
585 IN UINTN NumberOfLines,
586 IN VA_LIST Marker
587 )
588{
589 UINTN Index;
590 UINTN Count;
591 CHAR16 Character;
592 UINTN Start;
593 UINTN End;
594 UINTN Top;
595 UINTN Bottom;
596 CHAR16 *String;
597 UINTN DimensionsWidth;
598 UINTN DimensionsHeight;
599
600 DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;
601 DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;
602
603 gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
604
605 if ((RequestedWidth + 2) > DimensionsWidth) {
606 RequestedWidth = DimensionsWidth - 2;
607 }
608
609 //
610 // Subtract the PopUp width from total Columns, allow for one space extra on
611 // each end plus a border.
612 //
613 Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gStatementDimensions.LeftColumn + 1;
614 End = Start + RequestedWidth + 1;
615
616 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gStatementDimensions.TopRow - 1;
617 Bottom = Top + NumberOfLines + 2;
618
619 Character = BOXDRAW_DOWN_RIGHT;
620 PrintCharAt (Start, Top, Character);
621 Character = BOXDRAW_HORIZONTAL;
622 for (Index = Start; Index + 2 < End; Index++) {
623 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
624 }
625
626 Character = BOXDRAW_DOWN_LEFT;
627 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
628 Character = BOXDRAW_VERTICAL;
629
630 Count = 0;
631 for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
632 String = VA_ARG (Marker, CHAR16*);
633
634 //
635 // This will clear the background of the line - we never know who might have been
636 // here before us. This differs from the next clear in that it used the non-reverse
637 // video for normal printing.
638 //
639 if (GetStringWidth (String) / 2 > 1) {
640 ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
641 }
642
643 //
644 // Passing in a space results in the assumption that this is where typing will occur
645 //
646 if (String[0] == L' ') {
647 ClearLines (Start + 1, End - 1, Index + 1, Index + 1, GetPopupInverseColor ());
648 }
649
650 //
651 // Passing in a NULL results in a blank space
652 //
653 if (String[0] == CHAR_NULL) {
654 ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
655 }
656
657 PrintStringAt (
658 ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gStatementDimensions.LeftColumn + 1,
659 Index + 1,
660 String
661 );
662 gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
663 PrintCharAt (Start, Index + 1, Character);
664 PrintCharAt (End - 1, Index + 1, Character);
665 }
666
667 Character = BOXDRAW_UP_RIGHT;
668 PrintCharAt (Start, Bottom - 1, Character);
669 Character = BOXDRAW_HORIZONTAL;
670 for (Index = Start; Index + 2 < End; Index++) {
671 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
672 }
673
674 Character = BOXDRAW_UP_LEFT;
675 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
676}
677
678/**
679 Draw a pop up windows based on the dimension, number of lines and
680 strings specified.
681
682 @param RequestedWidth The width of the pop-up.
683 @param NumberOfLines The number of lines.
684 @param ... A series of text strings that displayed in the pop-up.
685
686**/
687VOID
688EFIAPI
689CreateMultiStringPopUp (
690 IN UINTN RequestedWidth,
691 IN UINTN NumberOfLines,
692 ...
693 )
694{
695 VA_LIST Marker;
696
697 VA_START (Marker, NumberOfLines);
698
699 CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);
700
701 VA_END (Marker);
702}
703
704/**
705 Process nothing.
706
707 @param Event The Event need to be process
708 @param Context The context of the event.
709
710**/
711VOID
712EFIAPI
713EmptyEventProcess (
714 IN EFI_EVENT Event,
715 IN VOID *Context
716 )
717{
718}
719
720/**
721 Process for the refresh interval statement.
722
723 @param Event The Event need to be process
724 @param Context The context of the event.
725
726**/
727VOID
728EFIAPI
729RefreshTimeOutProcess (
730 IN EFI_EVENT Event,
731 IN VOID *Context
732 )
733{
734 WARNING_IF_CONTEXT *EventInfo;
735 CHAR16 TimeOutString[MAX_TIME_OUT_LEN];
736
737 EventInfo = (WARNING_IF_CONTEXT *) Context;
738
739 if (*(EventInfo->TimeOut) == 0) {
740 gBS->CloseEvent (Event);
741
742 gBS->SignalEvent (EventInfo->SyncEvent);
743 return;
744 }
745
746 UnicodeSPrint(TimeOutString, MAX_TIME_OUT_LEN, L"%d", *(EventInfo->TimeOut));
747
748 CreateDialog (NULL, gEmptyString, EventInfo->ErrorInfo, gPressEnter, gEmptyString, TimeOutString, NULL);
749
750 *(EventInfo->TimeOut) -= 1;
751}
752
753/**
754 Display error message for invalid password.
755
756**/
757VOID
758PasswordInvalid (
759 VOID
760 )
761{
762 EFI_INPUT_KEY Key;
763
764 //
765 // Invalid password, prompt error message
766 //
767 do {
768 CreateDialog (&Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString, NULL);
769 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
770}
771
772/**
773 Process password op code.
774
775 @param MenuOption The menu for current password op code.
776
777 @retval EFI_SUCCESS Question Option process success.
778 @retval Other Question Option process fail.
779
780**/
781EFI_STATUS
782PasswordProcess (
783 IN UI_MENU_OPTION *MenuOption
784 )
785{
786 CHAR16 *StringPtr;
787 CHAR16 *TempString;
788 UINTN Maximum;
789 EFI_STATUS Status;
790 EFI_IFR_PASSWORD *PasswordInfo;
791 FORM_DISPLAY_ENGINE_STATEMENT *Question;
792 EFI_INPUT_KEY Key;
793
794 Question = MenuOption->ThisTag;
795 PasswordInfo = (EFI_IFR_PASSWORD *) Question->OpCode;
796 Maximum = PasswordInfo->MaxSize;
797 Status = EFI_SUCCESS;
798
799 StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
800 ASSERT (StringPtr);
801
802 //
803 // Use a NULL password to test whether old password is required
804 //
805 *StringPtr = 0;
806 Status = Question->PasswordCheck (gFormData, Question, StringPtr);
807 if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {
808 //
809 // Password can't be set now.
810 //
811 if (Status == EFI_UNSUPPORTED) {
812 do {
813 CreateDialog (&Key, gEmptyString, gPasswordUnsupported, gPressEnter, gEmptyString, NULL);
814 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
815 }
816 FreePool (StringPtr);
817 return EFI_SUCCESS;
818 }
819
820 if (EFI_ERROR (Status)) {
821 //
822 // Old password exist, ask user for the old password
823 //
824 Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
825 if (EFI_ERROR (Status)) {
826 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
827 FreePool (StringPtr);
828 return Status;
829 }
830
831 //
832 // Check user input old password
833 //
834 Status = Question->PasswordCheck (gFormData, Question, StringPtr);
835 if (EFI_ERROR (Status)) {
836 if (Status == EFI_NOT_READY) {
837 //
838 // Typed in old password incorrect
839 //
840 PasswordInvalid ();
841 } else {
842 Status = EFI_SUCCESS;
843 }
844 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
845 FreePool (StringPtr);
846 return Status;
847 }
848 }
849
850 //
851 // Ask for new password
852 //
853 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
854 Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);
855 if (EFI_ERROR (Status)) {
856 //
857 // Reset state machine for password
858 //
859 Question->PasswordCheck (gFormData, Question, NULL);
860 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
861 FreePool (StringPtr);
862 return Status;
863 }
864
865 //
866 // Confirm new password
867 //
868 TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
869 ASSERT (TempString);
870 Status = ReadString (MenuOption, gConfirmPassword, TempString);
871 if (EFI_ERROR (Status)) {
872 //
873 // Reset state machine for password
874 //
875 Question->PasswordCheck (gFormData, Question, NULL);
876 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
877 ZeroMem (TempString, (Maximum + 1) * sizeof (CHAR16));
878 FreePool (StringPtr);
879 FreePool (TempString);
880 return Status;
881 }
882
883 //
884 // Compare two typed-in new passwords
885 //
886 if (StrCmp (StringPtr, TempString) == 0) {
887 gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);
888 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
889 gUserInput->InputValue.Type = Question->CurrentValue.Type;
890 gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
891
892 Status = EFI_SUCCESS;
893 } else {
894 //
895 // Reset state machine for password
896 //
897 Question->PasswordCheck (gFormData, Question, NULL);
898
899 //
900 // Two password mismatch, prompt error message
901 //
902 do {
903 CreateDialog (&Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString, NULL);
904 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
905
906 Status = EFI_INVALID_PARAMETER;
907 }
908 ZeroMem (TempString, (Maximum + 1) * sizeof (CHAR16));
909 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
910 FreePool (TempString);
911 FreePool (StringPtr);
912
913 return Status;
914}
915
916/**
917 Print some debug message about mismatched menu info.
918
919 @param MenuOption The MenuOption for this Question.
920
921**/
922VOID
923PrintMismatchMenuInfo (
924 IN UI_MENU_OPTION *MenuOption
925)
926{
927 CHAR16 *FormTitleStr;
928 CHAR16 *FormSetTitleStr;
929 CHAR16 *OneOfOptionStr;
930 CHAR16 *QuestionName;
931 LIST_ENTRY *Link;
932 FORM_DISPLAY_ENGINE_STATEMENT *Question;
933 EFI_IFR_ORDERED_LIST *OrderList;
934 UINT8 Index;
935 EFI_HII_VALUE HiiValue;
936 EFI_HII_VALUE *QuestionValue;
937 DISPLAY_QUESTION_OPTION *Option;
938 UINT8 *ValueArray;
939 UINT8 ValueType;
940 EFI_IFR_FORM_SET *FormsetBuffer;
941 UINTN FormsetBufferSize;
942
943 Question = MenuOption->ThisTag;
944 HiiGetFormSetFromHiiHandle (gFormData->HiiHandle, &FormsetBuffer, &FormsetBufferSize);
945
946 FormSetTitleStr = GetToken (FormsetBuffer->FormSetTitle, gFormData->HiiHandle);
947 FormTitleStr = GetToken (gFormData->FormTitle, gFormData->HiiHandle);
948
949 DEBUG ((DEBUG_ERROR, "\n[%a]: Mismatch Formset : Formset Guid = %g, FormSet title = %s\n", gEfiCallerBaseName, &gFormData->FormSetGuid, FormSetTitleStr));
950 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Form : FormId = %d, Form title = %s.\n", gEfiCallerBaseName, gFormData->FormId, FormTitleStr));
951
952 if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
953 QuestionName = GetToken (((EFI_IFR_ORDERED_LIST*)MenuOption->ThisTag->OpCode)->Question.Header.Prompt, gFormData->HiiHandle);
954 Link = GetFirstNode (&Question->OptionListHead);
955 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
956 ValueType = Option->OptionOpCode->Type;
957 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Error : OrderedList value in the array doesn't match with option value.\n", gEfiCallerBaseName));
958 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OrderedList: Name = %s.\n", gEfiCallerBaseName, QuestionName));
959 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OrderedList: OrderedList array value :\n", gEfiCallerBaseName));
960
961 OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;
962 for (Index = 0; Index < OrderList->MaxContainers; Index++) {
963 ValueArray = Question->CurrentValue.Buffer;
964 HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
965 DEBUG ((DEBUG_ERROR, " Value[%d] =%ld.\n", Index, HiiValue.Value.u64));
966 }
967 } else if (Question->OpCode->OpCode == EFI_IFR_ONE_OF_OP) {
968 QuestionName = GetToken (((EFI_IFR_ONE_OF*)MenuOption->ThisTag->OpCode)->Question.Header.Prompt, gFormData->HiiHandle);
969 QuestionValue = &Question->CurrentValue;
970 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Error : OneOf value doesn't match with option value.\n", gEfiCallerBaseName));
971 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : Name = %s.\n", gEfiCallerBaseName, QuestionName));
972 switch (QuestionValue->Type) {
973 case EFI_IFR_TYPE_NUM_SIZE_64:
974 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %ld.\n",gEfiCallerBaseName, QuestionValue->Value.u64));
975 break;
976
977 case EFI_IFR_TYPE_NUM_SIZE_32:
978 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n",gEfiCallerBaseName, QuestionValue->Value.u32));
979 break;
980
981 case EFI_IFR_TYPE_NUM_SIZE_16:
982 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n",gEfiCallerBaseName, QuestionValue->Value.u16));
983 break;
984
985 case EFI_IFR_TYPE_NUM_SIZE_8:
986 DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n",gEfiCallerBaseName, QuestionValue->Value.u8));
987 break;
988
989 default:
990 ASSERT (FALSE);
991 break;
992 }
993 }
994
995 Index = 0;
996 Link = GetFirstNode (&Question->OptionListHead);
997 while (!IsNull (&Question->OptionListHead, Link)) {
998 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
999 OneOfOptionStr = GetToken (Option->OptionOpCode->Option, gFormData->HiiHandle);
1000 switch (Option->OptionOpCode->Type) {
1001 case EFI_IFR_TYPE_NUM_SIZE_64:
1002 DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %ld, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u64, OneOfOptionStr));
1003 break;
1004
1005 case EFI_IFR_TYPE_NUM_SIZE_32:
1006 DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u32, OneOfOptionStr));
1007 break;
1008
1009 case EFI_IFR_TYPE_NUM_SIZE_16:
1010 DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u16, OneOfOptionStr));
1011 break;
1012
1013 case EFI_IFR_TYPE_NUM_SIZE_8:
1014 DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u8, OneOfOptionStr));
1015 break;
1016
1017 default:
1018 ASSERT (FALSE);
1019 break;
1020 }
1021 Link = GetNextNode (&Question->OptionListHead, Link);
1022 Index++;
1023 }
1024}
1025
1026/**
1027 Process a Question's Option (whether selected or un-selected).
1028
1029 @param MenuOption The MenuOption for this Question.
1030 @param Selected TRUE: if Question is selected.
1031 @param OptionString Pointer of the Option String to be displayed.
1032 @param SkipErrorValue Whether need to return when value without option for it.
1033
1034 @retval EFI_SUCCESS Question Option process success.
1035 @retval Other Question Option process fail.
1036
1037**/
1038EFI_STATUS
1039ProcessOptions (
1040 IN UI_MENU_OPTION *MenuOption,
1041 IN BOOLEAN Selected,
1042 OUT CHAR16 **OptionString,
1043 IN BOOLEAN SkipErrorValue
1044 )
1045{
1046 EFI_STATUS Status;
1047 CHAR16 *StringPtr;
1048 UINTN Index;
1049 FORM_DISPLAY_ENGINE_STATEMENT *Question;
1050 CHAR16 FormattedNumber[21];
1051 UINT16 Number;
1052 CHAR16 Character[2];
1053 EFI_INPUT_KEY Key;
1054 UINTN BufferSize;
1055 DISPLAY_QUESTION_OPTION *OneOfOption;
1056 LIST_ENTRY *Link;
1057 EFI_HII_VALUE HiiValue;
1058 EFI_HII_VALUE *QuestionValue;
1059 DISPLAY_QUESTION_OPTION *Option;
1060 UINTN Index2;
1061 UINT8 *ValueArray;
1062 UINT8 ValueType;
1063 EFI_IFR_ORDERED_LIST *OrderList;
1064 BOOLEAN ValueInvalid;
1065 UINTN MaxLen;
1066
1067 Status = EFI_SUCCESS;
1068
1069 StringPtr = NULL;
1070 Character[1] = L'\0';
1071 *OptionString = NULL;
1072 ValueInvalid = FALSE;
1073
1074 ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
1075 BufferSize = (gOptionBlockWidth + 1) * 2 * gStatementDimensions.BottomRow;
1076
1077 Question = MenuOption->ThisTag;
1078 QuestionValue = &Question->CurrentValue;
1079
1080 switch (Question->OpCode->OpCode) {
1081 case EFI_IFR_ORDERED_LIST_OP:
1082
1083 //
1084 // Check whether there are Options of this OrderedList
1085 //
1086 if (IsListEmpty (&Question->OptionListHead)) {
1087 break;
1088 }
1089
1090 OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;
1091
1092 Link = GetFirstNode (&Question->OptionListHead);
1093 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
1094
1095 ValueType = OneOfOption->OptionOpCode->Type;
1096 ValueArray = Question->CurrentValue.Buffer;
1097
1098 if (Selected) {
1099 //
1100 // Go ask for input
1101 //
1102 Status = GetSelectionInputPopUp (MenuOption);
1103 } else {
1104 //
1105 // We now know how many strings we will have, so we can allocate the
1106 // space required for the array or strings.
1107 //
1108 MaxLen = OrderList->MaxContainers * BufferSize / sizeof (CHAR16);
1109 *OptionString = AllocateZeroPool (MaxLen * sizeof (CHAR16));
1110 ASSERT (*OptionString);
1111
1112 HiiValue.Type = ValueType;
1113 HiiValue.Value.u64 = 0;
1114 for (Index = 0; Index < OrderList->MaxContainers; Index++) {
1115 HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
1116 if (HiiValue.Value.u64 == 0) {
1117 //
1118 // Values for the options in ordered lists should never be a 0
1119 //
1120 break;
1121 }
1122
1123 OneOfOption = ValueToOption (Question, &HiiValue);
1124 if (OneOfOption == NULL) {
1125 //
1126 // Print debug msg for the mistach menu.
1127 //
1128 PrintMismatchMenuInfo (MenuOption);
1129
1130 if (SkipErrorValue) {
1131 //
1132 // Just try to get the option string, skip the value which not has option.
1133 //
1134 continue;
1135 }
1136
1137 //
1138 // Show error message
1139 //
1140 do {
1141 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
1142 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1143
1144 //
1145 // The initial value of the orderedlist is invalid, force to be valid value
1146 // Exit current DisplayForm with new value.
1147 //
1148 gUserInput->SelectedStatement = Question;
1149 gMisMatch = TRUE;
1150 ValueArray = AllocateZeroPool (Question->CurrentValue.BufferLen);
1151 ASSERT (ValueArray != NULL);
1152 gUserInput->InputValue.Buffer = ValueArray;
1153 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
1154 gUserInput->InputValue.Type = Question->CurrentValue.Type;
1155
1156 Link = GetFirstNode (&Question->OptionListHead);
1157 Index2 = 0;
1158 while (!IsNull (&Question->OptionListHead, Link) && Index2 < OrderList->MaxContainers) {
1159 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
1160 Link = GetNextNode (&Question->OptionListHead, Link);
1161 SetArrayData (ValueArray, ValueType, Index2, Option->OptionOpCode->Value.u64);
1162 Index2++;
1163 }
1164 SetArrayData (ValueArray, ValueType, Index2, 0);
1165
1166 FreePool (*OptionString);
1167 *OptionString = NULL;
1168 return EFI_NOT_FOUND;
1169 }
1170
1171 Character[0] = LEFT_ONEOF_DELIMITER;
1172 NewStrCat (OptionString[0], MaxLen, Character);
1173 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
1174 ASSERT (StringPtr != NULL);
1175 NewStrCat (OptionString[0], MaxLen, StringPtr);
1176 Character[0] = RIGHT_ONEOF_DELIMITER;
1177 NewStrCat (OptionString[0], MaxLen, Character);
1178 Character[0] = CHAR_CARRIAGE_RETURN;
1179 NewStrCat (OptionString[0], MaxLen, Character);
1180 FreePool (StringPtr);
1181 }
1182
1183 //
1184 // If valid option more than the max container, skip these options.
1185 //
1186 if (Index >= OrderList->MaxContainers) {
1187 break;
1188 }
1189
1190 //
1191 // Search the other options, try to find the one not in the container.
1192 //
1193 Link = GetFirstNode (&Question->OptionListHead);
1194 while (!IsNull (&Question->OptionListHead, Link)) {
1195 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
1196 Link = GetNextNode (&Question->OptionListHead, Link);
1197
1198 if (FindArrayData (ValueArray, ValueType, OneOfOption->OptionOpCode->Value.u64, NULL)) {
1199 continue;
1200 }
1201
1202 //
1203 // Print debug msg for the mistach menu.
1204 //
1205 PrintMismatchMenuInfo (MenuOption);
1206
1207 if (SkipErrorValue) {
1208 //
1209 // Not report error, just get the correct option string info.
1210 //
1211 Character[0] = LEFT_ONEOF_DELIMITER;
1212 NewStrCat (OptionString[0], MaxLen, Character);
1213 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
1214 ASSERT (StringPtr != NULL);
1215 NewStrCat (OptionString[0], MaxLen, StringPtr);
1216 Character[0] = RIGHT_ONEOF_DELIMITER;
1217 NewStrCat (OptionString[0], MaxLen, Character);
1218 Character[0] = CHAR_CARRIAGE_RETURN;
1219 NewStrCat (OptionString[0], MaxLen, Character);
1220 FreePool (StringPtr);
1221
1222 continue;
1223 }
1224
1225 if (!ValueInvalid) {
1226 ValueInvalid = TRUE;
1227 //
1228 // Show error message
1229 //
1230 do {
1231 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
1232 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1233
1234 //
1235 // The initial value of the orderedlist is invalid, force to be valid value
1236 // Exit current DisplayForm with new value.
1237 //
1238 gUserInput->SelectedStatement = Question;
1239 gMisMatch = TRUE;
1240 ValueArray = AllocateCopyPool (Question->CurrentValue.BufferLen, Question->CurrentValue.Buffer);
1241 ASSERT (ValueArray != NULL);
1242 gUserInput->InputValue.Buffer = ValueArray;
1243 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
1244 gUserInput->InputValue.Type = Question->CurrentValue.Type;
1245 }
1246
1247 SetArrayData (ValueArray, ValueType, Index++, OneOfOption->OptionOpCode->Value.u64);
1248 }
1249
1250 if (ValueInvalid) {
1251 FreePool (*OptionString);
1252 *OptionString = NULL;
1253 return EFI_NOT_FOUND;
1254 }
1255 }
1256 break;
1257
1258 case EFI_IFR_ONE_OF_OP:
1259 //
1260 // Check whether there are Options of this OneOf
1261 //
1262 if (IsListEmpty (&Question->OptionListHead)) {
1263 break;
1264 }
1265 if (Selected) {
1266 //
1267 // Go ask for input
1268 //
1269 Status = GetSelectionInputPopUp (MenuOption);
1270 } else {
1271 MaxLen = BufferSize / sizeof(CHAR16);
1272 *OptionString = AllocateZeroPool (BufferSize);
1273 ASSERT (*OptionString);
1274
1275 OneOfOption = ValueToOption (Question, QuestionValue);
1276 if (OneOfOption == NULL) {
1277 //
1278 // Print debug msg for the mistach menu.
1279 //
1280 PrintMismatchMenuInfo (MenuOption);
1281
1282 if (SkipErrorValue) {
1283 //
1284 // Not report error, just get the correct option string info.
1285 //
1286 Link = GetFirstNode (&Question->OptionListHead);
1287 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
1288 } else {
1289 //
1290 // Show error message
1291 //
1292 do {
1293 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
1294 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1295
1296 //
1297 // Force the Question value to be valid
1298 // Exit current DisplayForm with new value.
1299 //
1300 Link = GetFirstNode (&Question->OptionListHead);
1301 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
1302
1303 gUserInput->InputValue.Type = Option->OptionOpCode->Type;
1304 switch (gUserInput->InputValue.Type) {
1305 case EFI_IFR_TYPE_NUM_SIZE_8:
1306 gUserInput->InputValue.Value.u8 = Option->OptionOpCode->Value.u8;
1307 break;
1308 case EFI_IFR_TYPE_NUM_SIZE_16:
1309 CopyMem (&gUserInput->InputValue.Value.u16, &Option->OptionOpCode->Value.u16, sizeof (UINT16));
1310 break;
1311 case EFI_IFR_TYPE_NUM_SIZE_32:
1312 CopyMem (&gUserInput->InputValue.Value.u32, &Option->OptionOpCode->Value.u32, sizeof (UINT32));
1313 break;
1314 case EFI_IFR_TYPE_NUM_SIZE_64:
1315 CopyMem (&gUserInput->InputValue.Value.u64, &Option->OptionOpCode->Value.u64, sizeof (UINT64));
1316 break;
1317 default:
1318 ASSERT (FALSE);
1319 break;
1320 }
1321 gUserInput->SelectedStatement = Question;
1322 gMisMatch = TRUE;
1323 FreePool (*OptionString);
1324 *OptionString = NULL;
1325 return EFI_NOT_FOUND;
1326 }
1327 }
1328
1329 Character[0] = LEFT_ONEOF_DELIMITER;
1330 NewStrCat (OptionString[0], MaxLen, Character);
1331 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
1332 ASSERT (StringPtr != NULL);
1333 NewStrCat (OptionString[0], MaxLen, StringPtr);
1334 Character[0] = RIGHT_ONEOF_DELIMITER;
1335 NewStrCat (OptionString[0], MaxLen, Character);
1336
1337 FreePool (StringPtr);
1338 }
1339 break;
1340
1341 case EFI_IFR_CHECKBOX_OP:
1342 if (Selected) {
1343 //
1344 // Since this is a BOOLEAN operation, flip it upon selection
1345 //
1346 gUserInput->InputValue.Type = QuestionValue->Type;
1347 gUserInput->InputValue.Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
1348
1349 //
1350 // Perform inconsistent check
1351 //
1352 return EFI_SUCCESS;
1353 } else {
1354 *OptionString = AllocateZeroPool (BufferSize);
1355 ASSERT (*OptionString);
1356
1357 *OptionString[0] = LEFT_CHECKBOX_DELIMITER;
1358
1359 if (QuestionValue->Value.b) {
1360 *(OptionString[0] + 1) = CHECK_ON;
1361 } else {
1362 *(OptionString[0] + 1) = CHECK_OFF;
1363 }
1364 *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;
1365 }
1366 break;
1367
1368 case EFI_IFR_NUMERIC_OP:
1369 if (Selected) {
1370 //
1371 // Go ask for input
1372 //
1373 Status = GetNumericInput (MenuOption);
1374 } else {
1375 *OptionString = AllocateZeroPool (BufferSize);
1376 ASSERT (*OptionString);
1377
1378 *OptionString[0] = LEFT_NUMERIC_DELIMITER;
1379
1380 //
1381 // Formatted print
1382 //
1383 PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
1384 Number = (UINT16) GetStringWidth (FormattedNumber);
1385 CopyMem (OptionString[0] + 1, FormattedNumber, Number);
1386
1387 *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;
1388 }
1389 break;
1390
1391 case EFI_IFR_DATE_OP:
1392 if (Selected) {
1393 //
1394 // This is similar to numerics
1395 //
1396 Status = GetNumericInput (MenuOption);
1397 } else {
1398 *OptionString = AllocateZeroPool (BufferSize);
1399 ASSERT (*OptionString);
1400
1401 switch (MenuOption->Sequence) {
1402 case 0:
1403 *OptionString[0] = LEFT_NUMERIC_DELIMITER;
1404 if (QuestionValue->Value.date.Month == 0xff){
1405 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"??");
1406 } else {
1407 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);
1408 }
1409 *(OptionString[0] + 3) = DATE_SEPARATOR;
1410 break;
1411
1412 case 1:
1413 SetUnicodeMem (OptionString[0], 4, L' ');
1414 if (QuestionValue->Value.date.Day == 0xff){
1415 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"??");
1416 } else {
1417 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);
1418 }
1419 *(OptionString[0] + 6) = DATE_SEPARATOR;
1420 break;
1421
1422 case 2:
1423 SetUnicodeMem (OptionString[0], 7, L' ');
1424 if (QuestionValue->Value.date.Year == 0xff){
1425 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"????");
1426 } else {
1427 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);
1428 }
1429 *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;
1430 break;
1431 }
1432 }
1433 break;
1434
1435 case EFI_IFR_TIME_OP:
1436 if (Selected) {
1437 //
1438 // This is similar to numerics
1439 //
1440 Status = GetNumericInput (MenuOption);
1441 } else {
1442 *OptionString = AllocateZeroPool (BufferSize);
1443 ASSERT (*OptionString);
1444
1445 switch (MenuOption->Sequence) {
1446 case 0:
1447 *OptionString[0] = LEFT_NUMERIC_DELIMITER;
1448 if (QuestionValue->Value.time.Hour == 0xff){
1449 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"??");
1450 } else {
1451 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);
1452 }
1453 *(OptionString[0] + 3) = TIME_SEPARATOR;
1454 break;
1455
1456 case 1:
1457 SetUnicodeMem (OptionString[0], 4, L' ');
1458 if (QuestionValue->Value.time.Minute == 0xff){
1459 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"??");
1460 } else {
1461 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);
1462 }
1463 *(OptionString[0] + 6) = TIME_SEPARATOR;
1464 break;
1465
1466 case 2:
1467 SetUnicodeMem (OptionString[0], 7, L' ');
1468 if (QuestionValue->Value.time.Second == 0xff){
1469 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"??");
1470 } else {
1471 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);
1472 }
1473 *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;
1474 break;
1475 }
1476 }
1477 break;
1478
1479 case EFI_IFR_STRING_OP:
1480 if (Selected) {
1481 StringPtr = AllocateZeroPool (Question->CurrentValue.BufferLen + sizeof (CHAR16));
1482 ASSERT (StringPtr);
1483 CopyMem(StringPtr, Question->CurrentValue.Buffer, Question->CurrentValue.BufferLen);
1484
1485 Status = ReadString (MenuOption, gPromptForData, StringPtr);
1486 if (EFI_ERROR (Status)) {
1487 FreePool (StringPtr);
1488 return Status;
1489 }
1490
1491 gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);
1492 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
1493 gUserInput->InputValue.Type = Question->CurrentValue.Type;
1494 gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
1495 FreePool (StringPtr);
1496 return EFI_SUCCESS;
1497 } else {
1498 *OptionString = AllocateZeroPool (BufferSize);
1499 ASSERT (*OptionString);
1500
1501 if (((CHAR16 *) Question->CurrentValue.Buffer)[0] == 0x0000) {
1502 *(OptionString[0]) = '_';
1503 } else {
1504 if (Question->CurrentValue.BufferLen < BufferSize) {
1505 BufferSize = Question->CurrentValue.BufferLen;
1506 }
1507 CopyMem (OptionString[0], (CHAR16 *) Question->CurrentValue.Buffer, BufferSize);
1508 }
1509 }
1510 break;
1511
1512 case EFI_IFR_PASSWORD_OP:
1513 if (Selected) {
1514 Status = PasswordProcess (MenuOption);
1515 }
1516 break;
1517
1518 default:
1519 break;
1520 }
1521
1522 return Status;
1523}
1524
1525
1526/**
1527 Process the help string: Split StringPtr to several lines of strings stored in
1528 FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
1529
1530 @param StringPtr The entire help string.
1531 @param FormattedString The oupput formatted string.
1532 @param EachLineWidth The max string length of each line in the formatted string.
1533 @param RowCount TRUE: if Question is selected.
1534
1535**/
1536UINTN
1537ProcessHelpString (
1538 IN CHAR16 *StringPtr,
1539 OUT CHAR16 **FormattedString,
1540 OUT UINT16 *EachLineWidth,
1541 IN UINTN RowCount
1542 )
1543{
1544 UINTN Index;
1545 CHAR16 *OutputString;
1546 UINTN TotalRowNum;
1547 UINTN CheckedNum;
1548 UINT16 GlyphWidth;
1549 UINT16 LineWidth;
1550 UINT16 MaxStringLen;
1551 UINT16 StringLen;
1552
1553 TotalRowNum = 0;
1554 CheckedNum = 0;
1555 GlyphWidth = 1;
1556 Index = 0;
1557 MaxStringLen = 0;
1558 StringLen = 0;
1559
1560 //
1561 // Set default help string width.
1562 //
1563 LineWidth = (UINT16) (gHelpBlockWidth - 1);
1564
1565 //
1566 // Get row number of the String.
1567 //
1568 while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
1569 if (StringLen > MaxStringLen) {
1570 MaxStringLen = StringLen;
1571 }
1572
1573 TotalRowNum ++;
1574 FreePool (OutputString);
1575 }
1576 *EachLineWidth = MaxStringLen;
1577
1578 *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));
1579 ASSERT (*FormattedString != NULL);
1580
1581 //
1582 // Generate formatted help string array.
1583 //
1584 GlyphWidth = 1;
1585 Index = 0;
1586 while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
1587 CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));
1588 CheckedNum ++;
1589 FreePool (OutputString);
1590 }
1591
1592 return TotalRowNum;
1593}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette