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