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