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