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