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