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