]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe: Add support for PCD PcdPteMemoryEn...
[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
4b7345a7 5Copyright (c) 2004 - 2016, 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
01a9598e 24 @param DestMax The Max length of destination string.\r
7c6c064c
ED
25 @param Source The source string. The string to be concatenated.\r
26 to the end of Destination.\r
27\r
28**/\r
29VOID\r
30NewStrCat (\r
31 IN OUT CHAR16 *Destination,\r
5ad66ec6 32 IN UINTN DestMax,\r
7c6c064c
ED
33 IN CHAR16 *Source\r
34 )\r
35{\r
36 UINTN Length;\r
37\r
38 for (Length = 0; Destination[Length] != 0; Length++)\r
39 ;\r
40\r
41 //\r
42 // We now have the length of the original string\r
43 // We can safely assume for now that we are concatenating a narrow value to this string.\r
44 // For instance, the string is "XYZ" and cat'ing ">"\r
45 // If this assumption changes, we need to make this routine a bit more complex\r
46 //\r
47 Destination[Length] = NARROW_CHAR;\r
48 Length++;\r
49\r
5ad66ec6 50 StrCpyS (Destination + Length, DestMax - Length, Source);\r
7c6c064c
ED
51}\r
52\r
d63a9eb4
ED
53/**\r
54 Get UINT64 type value.\r
55\r
56 @param Value Input Hii value.\r
57\r
58 @retval UINT64 Return the UINT64 type value.\r
59\r
60**/\r
61UINT64\r
62HiiValueToUINT64 (\r
63 IN EFI_HII_VALUE *Value\r
64 )\r
65{\r
66 UINT64 RetVal;\r
67\r
68 RetVal = 0;\r
69\r
70 switch (Value->Type) {\r
71 case EFI_IFR_TYPE_NUM_SIZE_8:\r
72 RetVal = Value->Value.u8;\r
73 break;\r
74\r
75 case EFI_IFR_TYPE_NUM_SIZE_16:\r
76 RetVal = Value->Value.u16;\r
77 break;\r
78\r
79 case EFI_IFR_TYPE_NUM_SIZE_32:\r
80 RetVal = Value->Value.u32;\r
81 break;\r
82\r
83 case EFI_IFR_TYPE_BOOLEAN:\r
84 RetVal = Value->Value.b;\r
85 break;\r
86\r
87 case EFI_IFR_TYPE_DATE:\r
88 RetVal = *(UINT64*) &Value->Value.date;\r
89 break;\r
90\r
91 case EFI_IFR_TYPE_TIME:\r
92 RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;\r
93 break;\r
94\r
95 default:\r
96 RetVal = Value->Value.u64;\r
97 break;\r
98 }\r
99\r
100 return RetVal;\r
101}\r
102\r
40578d09
ED
103/**\r
104 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
105 \r
106 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
107 EFI_IFR_TYPE_BUFFER when do the value compare.\r
108\r
109 @param Value Expression value to compare on.\r
110\r
111 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
112 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
113\r
114**/\r
115BOOLEAN\r
116IsTypeInBuffer (\r
117 IN EFI_HII_VALUE *Value\r
118 )\r
119{\r
120 switch (Value->Type) {\r
121 case EFI_IFR_TYPE_BUFFER:\r
122 case EFI_IFR_TYPE_DATE:\r
123 case EFI_IFR_TYPE_TIME:\r
124 case EFI_IFR_TYPE_REF:\r
125 return TRUE;\r
126\r
127 default:\r
128 return FALSE;\r
129 }\r
130}\r
131\r
132/**\r
133 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
134\r
135 @param Value Expression value to compare on.\r
136\r
137 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
138 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
139\r
140**/\r
141BOOLEAN\r
142IsTypeInUINT64 (\r
143 IN EFI_HII_VALUE *Value\r
144 )\r
145{\r
146 switch (Value->Type) {\r
147 case EFI_IFR_TYPE_NUM_SIZE_8:\r
148 case EFI_IFR_TYPE_NUM_SIZE_16:\r
149 case EFI_IFR_TYPE_NUM_SIZE_32:\r
150 case EFI_IFR_TYPE_NUM_SIZE_64:\r
151 case EFI_IFR_TYPE_BOOLEAN:\r
152 return TRUE;\r
153\r
154 default:\r
155 return FALSE;\r
156 }\r
157}\r
158\r
159/**\r
160 Return the buffer length and buffer pointer for this value.\r
161 \r
162 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
163 EFI_IFR_TYPE_BUFFER when do the value compare.\r
164\r
165 @param Value Expression value to compare on.\r
166 @param Buf Return the buffer pointer.\r
167 @param BufLen Return the buffer length.\r
168\r
169**/\r
170VOID\r
171GetBufAndLenForValue (\r
172 IN EFI_HII_VALUE *Value,\r
173 OUT UINT8 **Buf,\r
174 OUT UINT16 *BufLen\r
175 )\r
176{\r
177 switch (Value->Type) {\r
178 case EFI_IFR_TYPE_BUFFER:\r
179 *Buf = Value->Buffer;\r
180 *BufLen = Value->BufferLen;\r
181 break;\r
182\r
183 case EFI_IFR_TYPE_DATE:\r
184 *Buf = (UINT8 *) (&Value->Value.date);\r
185 *BufLen = (UINT16) sizeof (EFI_HII_DATE);\r
186 break;\r
187\r
188 case EFI_IFR_TYPE_TIME:\r
189 *Buf = (UINT8 *) (&Value->Value.time);\r
190 *BufLen = (UINT16) sizeof (EFI_HII_TIME);\r
191 break;\r
192\r
193 case EFI_IFR_TYPE_REF:\r
194 *Buf = (UINT8 *) (&Value->Value.ref);\r
195 *BufLen = (UINT16) sizeof (EFI_HII_REF);\r
196 break;\r
197\r
198 default:\r
199 *Buf = NULL;\r
200 *BufLen = 0;\r
201 }\r
202}\r
203\r
7c6c064c
ED
204/**\r
205 Compare two Hii value.\r
206\r
207 @param Value1 Expression value to compare on left-hand.\r
208 @param Value2 Expression value to compare on right-hand.\r
209 @param Result Return value after compare.\r
210 retval 0 Two operators equal.\r
211 return Positive value if Value1 is greater than Value2.\r
212 retval Negative value if Value1 is less than Value2.\r
213 @param HiiHandle Only required for string compare.\r
214\r
215 @retval other Could not perform compare on two values.\r
216 @retval EFI_SUCCESS Compare the value success.\r
217\r
218**/\r
219EFI_STATUS\r
220CompareHiiValue (\r
221 IN EFI_HII_VALUE *Value1,\r
222 IN EFI_HII_VALUE *Value2,\r
223 OUT INTN *Result,\r
224 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
225 )\r
226{\r
227 INT64 Temp64;\r
228 CHAR16 *Str1;\r
229 CHAR16 *Str2;\r
230 UINTN Len;\r
40578d09
ED
231 UINT8 *Buf1;\r
232 UINT16 Buf1Len;\r
233 UINT8 *Buf2;\r
234 UINT16 Buf2Len;\r
7c6c064c 235\r
40578d09 236 if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {\r
7c6c064c
ED
237 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
238 //\r
239 // StringId 0 is reserved\r
240 //\r
241 return EFI_INVALID_PARAMETER;\r
242 }\r
243\r
244 if (Value1->Value.string == Value2->Value.string) {\r
245 *Result = 0;\r
246 return EFI_SUCCESS;\r
247 }\r
248\r
249 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
250 if (Str1 == NULL) {\r
251 //\r
252 // String not found\r
253 //\r
254 return EFI_NOT_FOUND;\r
255 }\r
256\r
257 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
258 if (Str2 == NULL) {\r
259 FreePool (Str1);\r
260 return EFI_NOT_FOUND;\r
261 }\r
262\r
263 *Result = StrCmp (Str1, Str2);\r
264\r
265 FreePool (Str1);\r
266 FreePool (Str2);\r
267\r
268 return EFI_SUCCESS;\r
269 }\r
270\r
40578d09
ED
271 //\r
272 // Take types(date, time, ref, buffer) as buffer\r
273 //\r
274 if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {\r
275 GetBufAndLenForValue(Value1, &Buf1, &Buf1Len);\r
276 GetBufAndLenForValue(Value2, &Buf2, &Buf2Len);\r
277\r
278 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
279 *Result = CompareMem (Buf1, Buf2, Len);\r
280 if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
7c6c064c
ED
281 //\r
282 // In this case, means base on samll number buffer, the data is same\r
283 // So which value has more data, which value is bigger.\r
284 //\r
40578d09 285 *Result = Buf1Len > Buf2Len ? 1 : -1;\r
7c6c064c
ED
286 }\r
287 return EFI_SUCCESS;\r
288 } \r
289\r
290 //\r
291 // Take remain types(integer, boolean, date/time) as integer\r
292 //\r
40578d09
ED
293 if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {\r
294 Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);\r
295 if (Temp64 > 0) {\r
296 *Result = 1;\r
297 } else if (Temp64 < 0) {\r
298 *Result = -1;\r
299 } else {\r
300 *Result = 0;\r
301 }\r
302 return EFI_SUCCESS;\r
7c6c064c
ED
303 }\r
304\r
40578d09 305 return EFI_UNSUPPORTED;\r
7c6c064c
ED
306}\r
307\r
308/**\r
309 Search an Option of a Question by its value.\r
310\r
311 @param Question The Question\r
312 @param OptionValue Value for Option to be searched.\r
313\r
314 @retval Pointer Pointer to the found Option.\r
315 @retval NULL Option not found.\r
316\r
317**/\r
318DISPLAY_QUESTION_OPTION *\r
319ValueToOption (\r
320 IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
321 IN EFI_HII_VALUE *OptionValue\r
322 )\r
323{\r
324 LIST_ENTRY *Link;\r
325 DISPLAY_QUESTION_OPTION *Option;\r
326 INTN Result;\r
327 EFI_HII_VALUE Value;\r
328\r
329 Link = GetFirstNode (&Question->OptionListHead);\r
330 while (!IsNull (&Question->OptionListHead, Link)) {\r
331 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
332\r
333 ZeroMem (&Value, sizeof (EFI_HII_VALUE));\r
334 Value.Type = Option->OptionOpCode->Type;\r
335 CopyMem (&Value.Value, &Option->OptionOpCode->Value, Option->OptionOpCode->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
336 \r
337 if ((CompareHiiValue (&Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
338 return Option;\r
339 }\r
340\r
341 Link = GetNextNode (&Question->OptionListHead, Link);\r
342 }\r
343\r
344 return NULL;\r
345}\r
346\r
347\r
348/**\r
349 Return data element in an Array by its Index.\r
350\r
351 @param Array The data array.\r
352 @param Type Type of the data in this array.\r
353 @param Index Zero based index for data in this array.\r
354\r
355 @retval Value The data to be returned\r
356\r
357**/\r
358UINT64\r
359GetArrayData (\r
360 IN VOID *Array,\r
361 IN UINT8 Type,\r
362 IN UINTN Index\r
363 )\r
364{\r
365 UINT64 Data;\r
366\r
367 ASSERT (Array != NULL);\r
368\r
369 Data = 0;\r
370 switch (Type) {\r
371 case EFI_IFR_TYPE_NUM_SIZE_8:\r
372 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
373 break;\r
374\r
375 case EFI_IFR_TYPE_NUM_SIZE_16:\r
376 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
377 break;\r
378\r
379 case EFI_IFR_TYPE_NUM_SIZE_32:\r
380 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
381 break;\r
382\r
383 case EFI_IFR_TYPE_NUM_SIZE_64:\r
384 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
385 break;\r
386\r
387 default:\r
388 break;\r
389 }\r
390\r
391 return Data;\r
392}\r
393\r
394\r
395/**\r
396 Set value of a data element in an Array by its Index.\r
397\r
398 @param Array The data array.\r
399 @param Type Type of the data in this array.\r
400 @param Index Zero based index for data in this array.\r
401 @param Value The value to be set.\r
402\r
403**/\r
404VOID\r
405SetArrayData (\r
406 IN VOID *Array,\r
407 IN UINT8 Type,\r
408 IN UINTN Index,\r
409 IN UINT64 Value\r
410 )\r
411{\r
412\r
413 ASSERT (Array != NULL);\r
414\r
415 switch (Type) {\r
416 case EFI_IFR_TYPE_NUM_SIZE_8:\r
417 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
418 break;\r
419\r
420 case EFI_IFR_TYPE_NUM_SIZE_16:\r
421 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
422 break;\r
423\r
424 case EFI_IFR_TYPE_NUM_SIZE_32:\r
425 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
426 break;\r
427\r
428 case EFI_IFR_TYPE_NUM_SIZE_64:\r
429 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
430 break;\r
431\r
432 default:\r
433 break;\r
434 }\r
435}\r
436\r
437/**\r
438 Check whether this value already in the array, if yes, return the index.\r
439\r
440 @param Array The data array.\r
441 @param Type Type of the data in this array.\r
442 @param Value The value to be find.\r
443 @param Index The index in the array which has same value with Value.\r
444 \r
445 @retval TRUE Found the value in the array.\r
446 @retval FALSE Not found the value.\r
447\r
448**/\r
449BOOLEAN \r
450FindArrayData (\r
451 IN VOID *Array,\r
452 IN UINT8 Type,\r
453 IN UINT64 Value,\r
454 OUT UINTN *Index OPTIONAL\r
455 )\r
456{\r
457 UINTN Count;\r
458 UINT64 TmpValue;\r
459 UINT64 ValueComp;\r
460 \r
461 ASSERT (Array != NULL);\r
462\r
463 Count = 0;\r
464 TmpValue = 0;\r
465\r
466 switch (Type) {\r
467 case EFI_IFR_TYPE_NUM_SIZE_8:\r
468 ValueComp = (UINT8) Value;\r
469 break;\r
470\r
471 case EFI_IFR_TYPE_NUM_SIZE_16:\r
472 ValueComp = (UINT16) Value;\r
473 break;\r
474\r
475 case EFI_IFR_TYPE_NUM_SIZE_32:\r
476 ValueComp = (UINT32) Value;\r
477 break;\r
478\r
479 case EFI_IFR_TYPE_NUM_SIZE_64:\r
480 ValueComp = (UINT64) Value;\r
481 break;\r
482\r
483 default:\r
484 ValueComp = 0;\r
485 break;\r
486 }\r
487\r
488 while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {\r
489 if (ValueComp == TmpValue) {\r
490 if (Index != NULL) {\r
491 *Index = Count;\r
492 }\r
493 return TRUE;\r
494 }\r
495\r
496 Count ++;\r
497 }\r
498\r
499 return FALSE;\r
500}\r
501\r
502/**\r
503 Print Question Value according to it's storage width and display attributes.\r
504\r
505 @param Question The Question to be printed.\r
506 @param FormattedNumber Buffer for output string.\r
507 @param BufferSize The FormattedNumber buffer size in bytes.\r
508\r
509 @retval EFI_SUCCESS Print success.\r
510 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
511\r
512**/\r
513EFI_STATUS\r
514PrintFormattedNumber (\r
515 IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
516 IN OUT CHAR16 *FormattedNumber,\r
517 IN UINTN BufferSize\r
518 )\r
519{\r
520 INT64 Value;\r
521 CHAR16 *Format;\r
522 EFI_HII_VALUE *QuestionValue;\r
523 EFI_IFR_NUMERIC *NumericOp;\r
524\r
525 if (BufferSize < (21 * sizeof (CHAR16))) {\r
526 return EFI_BUFFER_TOO_SMALL;\r
527 }\r
528\r
529 QuestionValue = &Question->CurrentValue;\r
530 NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;\r
531\r
532 Value = (INT64) QuestionValue->Value.u64;\r
533 switch (NumericOp->Flags & EFI_IFR_DISPLAY) {\r
534 case EFI_IFR_DISPLAY_INT_DEC:\r
535 switch (QuestionValue->Type) {\r
536 case EFI_IFR_NUMERIC_SIZE_1:\r
537 Value = (INT64) ((INT8) QuestionValue->Value.u8);\r
538 break;\r
539\r
540 case EFI_IFR_NUMERIC_SIZE_2:\r
541 Value = (INT64) ((INT16) QuestionValue->Value.u16);\r
542 break;\r
543\r
544 case EFI_IFR_NUMERIC_SIZE_4:\r
545 Value = (INT64) ((INT32) QuestionValue->Value.u32);\r
546 break;\r
547\r
548 case EFI_IFR_NUMERIC_SIZE_8:\r
549 default:\r
550 break;\r
551 }\r
552\r
553 if (Value < 0) {\r
554 Value = -Value;\r
555 Format = L"-%ld";\r
556 } else {\r
557 Format = L"%ld";\r
558 }\r
559 break;\r
560\r
561 case EFI_IFR_DISPLAY_UINT_DEC:\r
562 Format = L"%ld";\r
563 break;\r
564\r
565 case EFI_IFR_DISPLAY_UINT_HEX:\r
566 Format = L"%lx";\r
567 break;\r
568\r
569 default:\r
570 return EFI_UNSUPPORTED;\r
7c6c064c
ED
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
88f0c4e2
DB
817 if (Status == EFI_UNSUPPORTED) {\r
818 do {\r
819 CreateDialog (&Key, gEmptyString, gPasswordUnsupported, gPressEnter, gEmptyString, NULL);\r
820 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
821 }\r
7c6c064c
ED
822 FreePool (StringPtr);\r
823 return EFI_SUCCESS;\r
824 }\r
825\r
826 if (EFI_ERROR (Status)) {\r
827 //\r
828 // Old password exist, ask user for the old password\r
829 //\r
830 Status = ReadString (MenuOption, gPromptForPassword, StringPtr);\r
831 if (EFI_ERROR (Status)) {\r
832 FreePool (StringPtr);\r
833 return Status;\r
834 }\r
835\r
836 //\r
837 // Check user input old password\r
838 //\r
839 Status = Question->PasswordCheck (gFormData, Question, StringPtr);\r
840 if (EFI_ERROR (Status)) {\r
841 if (Status == EFI_NOT_READY) {\r
842 //\r
843 // Typed in old password incorrect\r
844 //\r
845 PasswordInvalid ();\r
846 } else {\r
847 Status = EFI_SUCCESS;\r
848 }\r
849\r
850 FreePool (StringPtr);\r
851 return Status;\r
852 }\r
853 }\r
854 \r
855 //\r
856 // Ask for new password\r
857 //\r
858 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));\r
859 Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);\r
860 if (EFI_ERROR (Status)) {\r
861 //\r
862 // Reset state machine for password\r
863 //\r
864 Question->PasswordCheck (gFormData, Question, NULL);\r
865 FreePool (StringPtr);\r
866 return Status;\r
867 }\r
868 \r
869 //\r
870 // Confirm new password\r
871 //\r
872 TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
873 ASSERT (TempString);\r
874 Status = ReadString (MenuOption, gConfirmPassword, TempString);\r
875 if (EFI_ERROR (Status)) {\r
876 //\r
877 // Reset state machine for password\r
878 //\r
879 Question->PasswordCheck (gFormData, Question, NULL);\r
880 FreePool (StringPtr);\r
881 FreePool (TempString);\r
882 return Status;\r
883 }\r
884 \r
885 //\r
886 // Compare two typed-in new passwords\r
887 //\r
888 if (StrCmp (StringPtr, TempString) == 0) { \r
889 gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);\r
890 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
891 gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
892 gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);\r
7c6c064c 893\r
bfae1330 894 Status = EFI_SUCCESS;\r
7c6c064c
ED
895 } else {\r
896 //\r
897 // Reset state machine for password\r
898 //\r
899 Question->PasswordCheck (gFormData, Question, NULL);\r
900 \r
901 //\r
902 // Two password mismatch, prompt error message\r
903 //\r
904 do {\r
905 CreateDialog (&Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString, NULL);\r
906 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
907\r
908 Status = EFI_INVALID_PARAMETER;\r
909 }\r
a275df8f
DB
910 ZeroMem (TempString, (Maximum + 1) * sizeof (CHAR16));\r
911 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));\r
7c6c064c
ED
912 FreePool (TempString);\r
913 FreePool (StringPtr);\r
914\r
915 return Status;\r
916}\r
917\r
918/**\r
919 Process a Question's Option (whether selected or un-selected).\r
920\r
921 @param MenuOption The MenuOption for this Question.\r
922 @param Selected TRUE: if Question is selected.\r
923 @param OptionString Pointer of the Option String to be displayed.\r
924 @param SkipErrorValue Whether need to return when value without option for it.\r
925\r
926 @retval EFI_SUCCESS Question Option process success.\r
927 @retval Other Question Option process fail.\r
928\r
929**/\r
930EFI_STATUS\r
931ProcessOptions (\r
932 IN UI_MENU_OPTION *MenuOption,\r
933 IN BOOLEAN Selected,\r
934 OUT CHAR16 **OptionString,\r
935 IN BOOLEAN SkipErrorValue\r
936 )\r
937{\r
938 EFI_STATUS Status;\r
939 CHAR16 *StringPtr;\r
940 UINTN Index;\r
941 FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
942 CHAR16 FormattedNumber[21];\r
943 UINT16 Number;\r
944 CHAR16 Character[2];\r
945 EFI_INPUT_KEY Key;\r
946 UINTN BufferSize;\r
947 DISPLAY_QUESTION_OPTION *OneOfOption;\r
948 LIST_ENTRY *Link;\r
949 EFI_HII_VALUE HiiValue;\r
950 EFI_HII_VALUE *QuestionValue;\r
951 DISPLAY_QUESTION_OPTION *Option;\r
952 UINTN Index2;\r
953 UINT8 *ValueArray;\r
954 UINT8 ValueType;\r
7c6c064c
ED
955 EFI_IFR_ORDERED_LIST *OrderList;\r
956 BOOLEAN ValueInvalid;\r
5ad66ec6 957 UINTN MaxLen;\r
7c6c064c
ED
958\r
959 Status = EFI_SUCCESS;\r
960\r
961 StringPtr = NULL;\r
962 Character[1] = L'\0';\r
963 *OptionString = NULL;\r
7c6c064c
ED
964 ValueInvalid = FALSE;\r
965\r
966 ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
967 BufferSize = (gOptionBlockWidth + 1) * 2 * gStatementDimensions.BottomRow;\r
968\r
969 Question = MenuOption->ThisTag;\r
970 QuestionValue = &Question->CurrentValue;\r
971\r
972 switch (Question->OpCode->OpCode) {\r
973 case EFI_IFR_ORDERED_LIST_OP:\r
974\r
975 //\r
976 // Check whether there are Options of this OrderedList\r
977 //\r
978 if (IsListEmpty (&Question->OptionListHead)) {\r
979 break;\r
980 }\r
981\r
982 OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;\r
983\r
984 Link = GetFirstNode (&Question->OptionListHead);\r
985 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
986\r
987 ValueType = OneOfOption->OptionOpCode->Type;\r
988 ValueArray = Question->CurrentValue.Buffer;\r
989\r
990 if (Selected) {\r
991 //\r
992 // Go ask for input\r
993 //\r
994 Status = GetSelectionInputPopUp (MenuOption);\r
995 } else {\r
996 //\r
997 // We now know how many strings we will have, so we can allocate the\r
998 // space required for the array or strings.\r
999 //\r
5ad66ec6
DB
1000 MaxLen = OrderList->MaxContainers * BufferSize / sizeof (CHAR16);\r
1001 *OptionString = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
7c6c064c
ED
1002 ASSERT (*OptionString);\r
1003\r
1004 HiiValue.Type = ValueType;\r
1005 HiiValue.Value.u64 = 0;\r
1006 for (Index = 0; Index < OrderList->MaxContainers; Index++) {\r
1007 HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
1008 if (HiiValue.Value.u64 == 0) {\r
1009 //\r
1010 // Values for the options in ordered lists should never be a 0\r
1011 //\r
1012 break;\r
1013 }\r
1014\r
1015 OneOfOption = ValueToOption (Question, &HiiValue);\r
1016 if (OneOfOption == NULL) {\r
1017 if (SkipErrorValue) {\r
1018 //\r
1019 // Just try to get the option string, skip the value which not has option.\r
1020 //\r
1021 continue;\r
1022 }\r
1023\r
1024 //\r
1025 // Show error message\r
1026 //\r
1027 do {\r
1028 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
1029 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1030\r
1031 //\r
1032 // The initial value of the orderedlist is invalid, force to be valid value\r
1033 // Exit current DisplayForm with new value.\r
1034 //\r
1035 gUserInput->SelectedStatement = Question;\r
42645c3d 1036 gMisMatch = TRUE;\r
7c6c064c
ED
1037 ValueArray = AllocateZeroPool (Question->CurrentValue.BufferLen);\r
1038 ASSERT (ValueArray != NULL);\r
1039 gUserInput->InputValue.Buffer = ValueArray;\r
1040 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
1041 gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
1042 \r
1043 Link = GetFirstNode (&Question->OptionListHead);\r
1044 Index2 = 0;\r
1045 while (!IsNull (&Question->OptionListHead, Link) && Index2 < OrderList->MaxContainers) {\r
1046 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
1047 Link = GetNextNode (&Question->OptionListHead, Link);\r
1048 SetArrayData (ValueArray, ValueType, Index2, Option->OptionOpCode->Value.u64);\r
1049 Index2++;\r
1050 }\r
1051 SetArrayData (ValueArray, ValueType, Index2, 0);\r
1052\r
1053 FreePool (*OptionString);\r
1054 *OptionString = NULL;\r
1055 return EFI_NOT_FOUND;\r
1056 }\r
1057\r
1058 Character[0] = LEFT_ONEOF_DELIMITER;\r
5ad66ec6 1059 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1060 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
1061 ASSERT (StringPtr != NULL);\r
5ad66ec6 1062 NewStrCat (OptionString[0], MaxLen, StringPtr);\r
7c6c064c 1063 Character[0] = RIGHT_ONEOF_DELIMITER;\r
5ad66ec6 1064 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c 1065 Character[0] = CHAR_CARRIAGE_RETURN;\r
5ad66ec6 1066 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1067 FreePool (StringPtr);\r
1068 }\r
1069\r
1070 //\r
1071 // If valid option more than the max container, skip these options.\r
1072 //\r
1073 if (Index >= OrderList->MaxContainers) {\r
1074 break;\r
1075 }\r
1076\r
1077 //\r
1078 // Search the other options, try to find the one not in the container.\r
1079 //\r
1080 Link = GetFirstNode (&Question->OptionListHead);\r
1081 while (!IsNull (&Question->OptionListHead, Link)) {\r
1082 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
1083 Link = GetNextNode (&Question->OptionListHead, Link);\r
1084\r
1085 if (FindArrayData (ValueArray, ValueType, OneOfOption->OptionOpCode->Value.u64, NULL)) {\r
1086 continue;\r
1087 }\r
1088\r
1089 if (SkipErrorValue) {\r
1090 //\r
1091 // Not report error, just get the correct option string info.\r
1092 //\r
1093 Character[0] = LEFT_ONEOF_DELIMITER;\r
5ad66ec6 1094 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1095 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
1096 ASSERT (StringPtr != NULL);\r
5ad66ec6 1097 NewStrCat (OptionString[0], MaxLen, StringPtr);\r
7c6c064c 1098 Character[0] = RIGHT_ONEOF_DELIMITER;\r
5ad66ec6 1099 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c 1100 Character[0] = CHAR_CARRIAGE_RETURN;\r
5ad66ec6 1101 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1102 FreePool (StringPtr);\r
1103\r
1104 continue;\r
1105 }\r
1106\r
1107 if (!ValueInvalid) {\r
1108 ValueInvalid = TRUE;\r
1109 //\r
1110 // Show error message\r
1111 //\r
1112 do {\r
1113 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
1114 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1115\r
1116 //\r
1117 // The initial value of the orderedlist is invalid, force to be valid value\r
1118 // Exit current DisplayForm with new value.\r
1119 //\r
1120 gUserInput->SelectedStatement = Question;\r
42645c3d 1121 gMisMatch = TRUE;\r
7c6c064c
ED
1122 ValueArray = AllocateCopyPool (Question->CurrentValue.BufferLen, Question->CurrentValue.Buffer);\r
1123 ASSERT (ValueArray != NULL);\r
1124 gUserInput->InputValue.Buffer = ValueArray;\r
1125 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
1126 gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
1127 }\r
1128 \r
1129 SetArrayData (ValueArray, ValueType, Index++, OneOfOption->OptionOpCode->Value.u64);\r
1130 }\r
1131\r
1132 if (ValueInvalid) {\r
1133 FreePool (*OptionString);\r
1134 *OptionString = NULL;\r
1135 return EFI_NOT_FOUND;\r
1136 }\r
1137 }\r
1138 break;\r
1139\r
1140 case EFI_IFR_ONE_OF_OP:\r
1141 //\r
1142 // Check whether there are Options of this OneOf\r
1143 //\r
1144 if (IsListEmpty (&Question->OptionListHead)) {\r
1145 break;\r
1146 }\r
1147 if (Selected) {\r
1148 //\r
1149 // Go ask for input\r
1150 //\r
1151 Status = GetSelectionInputPopUp (MenuOption);\r
1152 } else {\r
5ad66ec6 1153 MaxLen = BufferSize / sizeof(CHAR16);\r
7c6c064c
ED
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
5ad66ec6 1207 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1208 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
1209 ASSERT (StringPtr != NULL);\r
5ad66ec6 1210 NewStrCat (OptionString[0], MaxLen, StringPtr);\r
7c6c064c 1211 Character[0] = RIGHT_ONEOF_DELIMITER;\r
5ad66ec6 1212 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
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