]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
Refine code to follow coding style.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / ProcessOptions.c
CommitLineData
c60a0616 1/** @file\r
2Implementation for handling the User Interface option processing.\r
3\r
4\r
31585af4 5Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 6This program and the accompanying materials\r
c60a0616 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
c60a0616 16#include "Setup.h"\r
17\r
18\r
19/**\r
20 Process Question Config.\r
21\r
22 @param Selection The UI menu selection.\r
23 @param Question The Question to be peocessed.\r
24\r
25 @retval EFI_SUCCESS Question Config process success.\r
26 @retval Other Question Config process fail.\r
27\r
28**/\r
29EFI_STATUS\r
30ProcessQuestionConfig (\r
31 IN UI_MENU_SELECTION *Selection,\r
32 IN FORM_BROWSER_STATEMENT *Question\r
33 )\r
34{\r
35 EFI_STATUS Status;\r
36 CHAR16 *ConfigResp;\r
37 CHAR16 *Progress;\r
38 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
39\r
40 if (Question->QuestionConfig == 0) {\r
41 return EFI_SUCCESS;\r
42 }\r
43\r
44 //\r
45 // Get <ConfigResp>\r
46 //\r
47 ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
48 if (ConfigResp == NULL) {\r
49 return EFI_NOT_FOUND;\r
50 }\r
51\r
52 //\r
53 // Send config to Configuration Driver\r
54 //\r
55 ConfigAccess = Selection->FormSet->ConfigAccess;\r
56 if (ConfigAccess == NULL) {\r
57 return EFI_UNSUPPORTED;\r
58 }\r
59 Status = ConfigAccess->RouteConfig (\r
60 ConfigAccess,\r
61 ConfigResp,\r
62 &Progress\r
63 );\r
64\r
65 return Status;\r
66}\r
67\r
68\r
69/**\r
70 Search an Option of a Question by its value.\r
71\r
72 @param Question The Question\r
73 @param OptionValue Value for Option to be searched.\r
74\r
75 @retval Pointer Pointer to the found Option.\r
76 @retval NULL Option not found.\r
77\r
78**/\r
79QUESTION_OPTION *\r
80ValueToOption (\r
81 IN FORM_BROWSER_STATEMENT *Question,\r
82 IN EFI_HII_VALUE *OptionValue\r
83 )\r
84{\r
85 LIST_ENTRY *Link;\r
86 QUESTION_OPTION *Option;\r
8f420676 87 INTN Result;\r
c60a0616 88\r
89 Link = GetFirstNode (&Question->OptionListHead);\r
90 while (!IsNull (&Question->OptionListHead, Link)) {\r
91 Option = QUESTION_OPTION_FROM_LINK (Link);\r
92\r
8f420676 93 if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
82612023
ED
94 //\r
95 // Check the suppressif condition, only a valid option can be return.\r
96 //\r
97 if ((Option->SuppressExpression == NULL) ||\r
98 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
99 return Option;\r
100 }\r
c60a0616 101 }\r
102\r
103 Link = GetNextNode (&Question->OptionListHead, Link);\r
104 }\r
105\r
106 return NULL;\r
107}\r
108\r
109\r
d02847d3 110/**\r
111 Return data element in an Array by its Index.\r
112\r
113 @param Array The data array.\r
114 @param Type Type of the data in this array.\r
115 @param Index Zero based index for data in this array.\r
116\r
117 @retval Value The data to be returned\r
118\r
119**/\r
120UINT64\r
121GetArrayData (\r
122 IN VOID *Array,\r
123 IN UINT8 Type,\r
124 IN UINTN Index\r
125 )\r
126{\r
127 UINT64 Data;\r
128\r
129 ASSERT (Array != NULL);\r
130\r
131 Data = 0;\r
132 switch (Type) {\r
133 case EFI_IFR_TYPE_NUM_SIZE_8:\r
134 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
135 break;\r
136\r
137 case EFI_IFR_TYPE_NUM_SIZE_16:\r
138 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
139 break;\r
140\r
141 case EFI_IFR_TYPE_NUM_SIZE_32:\r
142 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
143 break;\r
144\r
145 case EFI_IFR_TYPE_NUM_SIZE_64:\r
146 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
147 break;\r
148\r
149 default:\r
150 break;\r
151 }\r
152\r
153 return Data;\r
154}\r
155\r
156\r
157/**\r
158 Set value of a data element in an Array by its Index.\r
159\r
160 @param Array The data array.\r
161 @param Type Type of the data in this array.\r
162 @param Index Zero based index for data in this array.\r
163 @param Value The value to be set.\r
164\r
165**/\r
166VOID\r
167SetArrayData (\r
168 IN VOID *Array,\r
169 IN UINT8 Type,\r
170 IN UINTN Index,\r
171 IN UINT64 Value\r
172 )\r
173{\r
174\r
175 ASSERT (Array != NULL);\r
176\r
177 switch (Type) {\r
178 case EFI_IFR_TYPE_NUM_SIZE_8:\r
179 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
180 break;\r
181\r
182 case EFI_IFR_TYPE_NUM_SIZE_16:\r
183 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
184 break;\r
185\r
186 case EFI_IFR_TYPE_NUM_SIZE_32:\r
187 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
188 break;\r
189\r
190 case EFI_IFR_TYPE_NUM_SIZE_64:\r
191 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
192 break;\r
193\r
194 default:\r
195 break;\r
196 }\r
197}\r
198\r
82612023
ED
199/**\r
200 Check whether this value already in the array, if yes, return the index.\r
201\r
202 @param Array The data array.\r
203 @param Type Type of the data in this array.\r
204 @param Value The value to be find.\r
205 @param Index The index in the array which has same value with Value.\r
206 \r
207 @retval TRUE Found the value in the array.\r
208 @retval FALSE Not found the value.\r
209\r
210**/\r
211BOOLEAN \r
212FindArrayData (\r
213 IN VOID *Array,\r
214 IN UINT8 Type,\r
215 IN UINT64 Value,\r
216 OUT UINTN *Index OPTIONAL\r
217 )\r
218{\r
219 UINTN Count;\r
220 UINT64 TmpValue;\r
221 \r
222 ASSERT (Array != NULL);\r
223\r
224 Count = 0;\r
225 TmpValue = 0;\r
226\r
227 while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {\r
228 if (Value == TmpValue) {\r
229 if (Index != NULL) {\r
230 *Index = Count;\r
231 }\r
232 return TRUE;\r
233 }\r
234\r
235 Count ++;\r
236 }\r
237\r
238 return FALSE;\r
239}\r
d02847d3 240\r
c60a0616 241/**\r
242 Print Question Value according to it's storage width and display attributes.\r
243\r
244 @param Question The Question to be printed.\r
245 @param FormattedNumber Buffer for output string.\r
246 @param BufferSize The FormattedNumber buffer size in bytes.\r
247\r
248 @retval EFI_SUCCESS Print success.\r
249 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
250\r
251**/\r
252EFI_STATUS\r
253PrintFormattedNumber (\r
254 IN FORM_BROWSER_STATEMENT *Question,\r
255 IN OUT CHAR16 *FormattedNumber,\r
256 IN UINTN BufferSize\r
257 )\r
258{\r
259 INT64 Value;\r
260 CHAR16 *Format;\r
261 EFI_HII_VALUE *QuestionValue;\r
262\r
263 if (BufferSize < (21 * sizeof (CHAR16))) {\r
264 return EFI_BUFFER_TOO_SMALL;\r
265 }\r
266\r
267 QuestionValue = &Question->HiiValue;\r
268\r
269 Value = (INT64) QuestionValue->Value.u64;\r
270 switch (Question->Flags & EFI_IFR_DISPLAY) {\r
271 case EFI_IFR_DISPLAY_INT_DEC:\r
272 switch (QuestionValue->Type) {\r
273 case EFI_IFR_NUMERIC_SIZE_1:\r
274 Value = (INT64) ((INT8) QuestionValue->Value.u8);\r
275 break;\r
276\r
277 case EFI_IFR_NUMERIC_SIZE_2:\r
278 Value = (INT64) ((INT16) QuestionValue->Value.u16);\r
279 break;\r
280\r
281 case EFI_IFR_NUMERIC_SIZE_4:\r
282 Value = (INT64) ((INT32) QuestionValue->Value.u32);\r
283 break;\r
284\r
285 case EFI_IFR_NUMERIC_SIZE_8:\r
286 default:\r
287 break;\r
288 }\r
289\r
290 if (Value < 0) {\r
291 Value = -Value;\r
292 Format = L"-%ld";\r
293 } else {\r
294 Format = L"%ld";\r
295 }\r
296 break;\r
297\r
298 case EFI_IFR_DISPLAY_UINT_DEC:\r
299 Format = L"%ld";\r
300 break;\r
301\r
302 case EFI_IFR_DISPLAY_UINT_HEX:\r
303 Format = L"%lx";\r
304 break;\r
305\r
306 default:\r
307 return EFI_UNSUPPORTED;\r
308 break;\r
309 }\r
310\r
311 UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);\r
312\r
313 return EFI_SUCCESS;\r
314}\r
315\r
316\r
317/**\r
318 Password may be stored as encrypted by Configuration Driver. When change a\r
319 password, user will be challenged with old password. To validate user input old\r
320 password, we will send the clear text to Configuration Driver via Callback().\r
321 Configuration driver is responsible to check the passed in password and return\r
322 the validation result. If validation pass, state machine in password Callback()\r
323 will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.\r
324 After user type in new password twice, Callback() will be invoked to send the\r
325 new password to Configuration Driver.\r
326\r
327 @param Selection Pointer to UI_MENU_SELECTION.\r
328 @param MenuOption The MenuOption for this password Question.\r
329 @param String The clear text of password.\r
330\r
331 @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.\r
332 @return In state of BROWSER_STATE_VALIDATE_PASSWORD:\r
333 @retval EFI_SUCCESS Password correct, Browser will prompt for new\r
334 password.\r
335 @retval EFI_NOT_READY Password incorrect, Browser will show error\r
336 message.\r
337 @retval Other Browser will do nothing.\r
338 @return In state of BROWSER_STATE_SET_PASSWORD:\r
339 @retval EFI_SUCCESS Set password success.\r
340 @retval Other Set password failed.\r
341\r
342**/\r
343EFI_STATUS\r
344PasswordCallback (\r
345 IN UI_MENU_SELECTION *Selection,\r
346 IN UI_MENU_OPTION *MenuOption,\r
347 IN CHAR16 *String\r
348 )\r
349{\r
350 EFI_STATUS Status;\r
351 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
352 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
e2100bfa 353 EFI_IFR_TYPE_VALUE IfrTypeValue;\r
c60a0616 354\r
c60a0616 355 ConfigAccess = Selection->FormSet->ConfigAccess;\r
356 if (ConfigAccess == NULL) {\r
357 return EFI_UNSUPPORTED;\r
358 }\r
359\r
360 //\r
361 // Prepare password string in HII database\r
362 //\r
363 if (String != NULL) {\r
e2100bfa 364 IfrTypeValue.string = NewString (String, Selection->FormSet->HiiHandle);\r
c60a0616 365 } else {\r
e2100bfa 366 IfrTypeValue.string = 0;\r
c60a0616 367 }\r
368\r
369 //\r
370 // Send password to Configuration Driver for validation\r
371 //\r
372 Status = ConfigAccess->Callback (\r
373 ConfigAccess,\r
374 EFI_BROWSER_ACTION_CHANGING,\r
375 MenuOption->ThisTag->QuestionId,\r
e2100bfa
ED
376 MenuOption->ThisTag->HiiValue.Type,\r
377 &IfrTypeValue,\r
c60a0616 378 &ActionRequest\r
379 );\r
380\r
381 //\r
382 // Remove password string from HII database\r
383 //\r
384 if (String != NULL) {\r
e2100bfa 385 DeleteString (IfrTypeValue.string, Selection->FormSet->HiiHandle);\r
c60a0616 386 }\r
387\r
388 return Status;\r
389}\r
390\r
391\r
392/**\r
393 Display error message for invalid password.\r
394\r
395**/\r
396VOID\r
397PasswordInvalid (\r
398 VOID\r
399 )\r
400{\r
401 EFI_INPUT_KEY Key;\r
402\r
403 //\r
404 // Invalid password, prompt error message\r
405 //\r
406 do {\r
407 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString);\r
408 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
409}\r
410\r
411\r
412/**\r
413 Process a Question's Option (whether selected or un-selected).\r
414\r
415 @param Selection Pointer to UI_MENU_SELECTION.\r
416 @param MenuOption The MenuOption for this Question.\r
417 @param Selected TRUE: if Question is selected.\r
418 @param OptionString Pointer of the Option String to be displayed.\r
419\r
420 @retval EFI_SUCCESS Question Option process success.\r
421 @retval Other Question Option process fail.\r
422\r
423**/\r
424EFI_STATUS\r
425ProcessOptions (\r
426 IN UI_MENU_SELECTION *Selection,\r
427 IN UI_MENU_OPTION *MenuOption,\r
428 IN BOOLEAN Selected,\r
429 OUT CHAR16 **OptionString\r
430 )\r
431{\r
432 EFI_STATUS Status;\r
433 CHAR16 *StringPtr;\r
434 CHAR16 *TempString;\r
435 UINTN Index;\r
436 FORM_BROWSER_STATEMENT *Question;\r
437 CHAR16 FormattedNumber[21];\r
438 UINT16 Number;\r
439 CHAR16 Character[2];\r
440 EFI_INPUT_KEY Key;\r
441 UINTN BufferSize;\r
442 QUESTION_OPTION *OneOfOption;\r
443 LIST_ENTRY *Link;\r
444 EFI_HII_VALUE HiiValue;\r
445 EFI_HII_VALUE *QuestionValue;\r
c60a0616 446 UINT16 Maximum;\r
8d00a0f1 447 QUESTION_OPTION *Option;\r
448 UINTN Index2;\r
d02847d3 449 UINT8 *ValueArray;\r
450 UINT8 ValueType;\r
e2100bfa 451 EFI_STRING_ID StringId;\r
c60a0616 452\r
453 Status = EFI_SUCCESS;\r
454\r
455 StringPtr = NULL;\r
456 Character[1] = L'\0';\r
457 *OptionString = NULL;\r
e2100bfa 458 StringId = 0;\r
c60a0616 459\r
460 ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
461 BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow;\r
462\r
463 Question = MenuOption->ThisTag;\r
464 QuestionValue = &Question->HiiValue;\r
465 Maximum = (UINT16) Question->Maximum;\r
466\r
d02847d3 467 ValueArray = Question->BufferValue;\r
468 ValueType = Question->ValueType;\r
469\r
c60a0616 470 switch (Question->Operand) {\r
471 case EFI_IFR_ORDERED_LIST_OP:\r
b86b413a
LG
472 //\r
473 // Check whether there are Options of this OrderedList\r
474 //\r
475 if (IsListEmpty (&Question->OptionListHead)) {\r
476 break;\r
477 }\r
c60a0616 478 //\r
479 // Initialize Option value array\r
480 //\r
d02847d3 481 if (GetArrayData (ValueArray, ValueType, 0) == 0) {\r
c60a0616 482 GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0);\r
483 }\r
484\r
485 if (Selected) {\r
486 //\r
487 // Go ask for input\r
488 //\r
489 Status = GetSelectionInputPopUp (Selection, MenuOption);\r
490 } else {\r
491 //\r
492 // We now know how many strings we will have, so we can allocate the\r
493 // space required for the array or strings.\r
494 //\r
495 *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize);\r
496 ASSERT (*OptionString);\r
497\r
d02847d3 498 HiiValue.Type = ValueType;\r
c60a0616 499 HiiValue.Value.u64 = 0;\r
500 for (Index = 0; Index < Question->MaxContainers; Index++) {\r
d02847d3 501 HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
502 if (HiiValue.Value.u64 == 0) {\r
c60a0616 503 //\r
504 // Values for the options in ordered lists should never be a 0\r
505 //\r
506 break;\r
507 }\r
508\r
509 OneOfOption = ValueToOption (Question, &HiiValue);\r
510 if (OneOfOption == NULL) {\r
8d00a0f1 511 //\r
512 // Show error message\r
513 //\r
514 do {\r
515 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString);\r
516 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
517\r
518 //\r
519 // The initial value of the orderedlist is invalid, force to be valid value\r
520 //\r
521 Link = GetFirstNode (&Question->OptionListHead);\r
522 Index2 = 0;\r
523 while (!IsNull (&Question->OptionListHead, Link) && Index2 < Question->MaxContainers) {\r
524 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
525 Link = GetNextNode (&Question->OptionListHead, Link);\r
526 if ((Option->SuppressExpression != NULL) &&\r
527 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
528 continue;\r
529 }\r
d02847d3 530 SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64);\r
531 Index2++;\r
8d00a0f1 532 }\r
d02847d3 533 SetArrayData (ValueArray, ValueType, Index2, 0);\r
8d00a0f1 534\r
816a7110 535 Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
b18e7050 536 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
8d00a0f1 537\r
f4113e1f 538 FreePool (*OptionString);\r
8d00a0f1 539 *OptionString = NULL;\r
c60a0616 540 return EFI_NOT_FOUND;\r
541 }\r
542\r
82612023
ED
543 Character[0] = LEFT_ONEOF_DELIMITER;\r
544 NewStrCat (OptionString[0], Character);\r
545 StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
546 ASSERT (StringPtr != NULL);\r
547 NewStrCat (OptionString[0], StringPtr);\r
548 Character[0] = RIGHT_ONEOF_DELIMITER;\r
549 NewStrCat (OptionString[0], Character);\r
550 Character[0] = CHAR_CARRIAGE_RETURN;\r
551 NewStrCat (OptionString[0], Character);\r
552 FreePool (StringPtr);\r
553 }\r
554\r
555 //\r
556 // Search the other options, try to find the one not in the container.\r
557 //\r
558 Link = GetFirstNode (&Question->OptionListHead);\r
559 while (!IsNull (&Question->OptionListHead, Link)) {\r
560 OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
561 Link = GetNextNode (&Question->OptionListHead, Link);\r
c60a0616 562 if ((OneOfOption->SuppressExpression != NULL) &&\r
82612023
ED
563 ((EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
564 continue;\r
c60a0616 565 }\r
566\r
82612023
ED
567 if (FindArrayData (ValueArray, ValueType, OneOfOption->Value.Value.u64, NULL)) {\r
568 continue;\r
c60a0616 569 }\r
82612023
ED
570\r
571 SetArrayData (ValueArray, ValueType, Index++, OneOfOption->Value.Value.u64);\r
572\r
573 Character[0] = LEFT_ONEOF_DELIMITER;\r
574 NewStrCat (OptionString[0], Character);\r
575 StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
576 ASSERT (StringPtr != NULL);\r
577 NewStrCat (OptionString[0], StringPtr);\r
578 Character[0] = RIGHT_ONEOF_DELIMITER;\r
579 NewStrCat (OptionString[0], Character);\r
580 Character[0] = CHAR_CARRIAGE_RETURN;\r
581 NewStrCat (OptionString[0], Character);\r
582 FreePool (StringPtr);\r
c60a0616 583 }\r
584 }\r
585 break;\r
586\r
587 case EFI_IFR_ONE_OF_OP:\r
b86b413a
LG
588 //\r
589 // Check whether there are Options of this OneOf\r
590 //\r
591 if (IsListEmpty (&Question->OptionListHead)) {\r
592 break;\r
593 }\r
c60a0616 594 if (Selected) {\r
595 //\r
596 // Go ask for input\r
597 //\r
598 Status = GetSelectionInputPopUp (Selection, MenuOption);\r
599 } else {\r
600 *OptionString = AllocateZeroPool (BufferSize);\r
601 ASSERT (*OptionString);\r
602\r
603 OneOfOption = ValueToOption (Question, QuestionValue);\r
604 if (OneOfOption == NULL) {\r
8d00a0f1 605 //\r
606 // Show error message\r
607 //\r
608 do {\r
609 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString);\r
610 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
611\r
612 //\r
613 // Force the Question value to be valid\r
614 //\r
615 Link = GetFirstNode (&Question->OptionListHead);\r
616 while (!IsNull (&Question->OptionListHead, Link)) {\r
617 Option = QUESTION_OPTION_FROM_LINK (Link);\r
618\r
619 if ((Option->SuppressExpression == NULL) ||\r
31585af4 620 (EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)) {\r
8d00a0f1 621 CopyMem (QuestionValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
816a7110 622 SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
b18e7050 623 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
8d00a0f1 624 break;\r
625 }\r
626\r
627 Link = GetNextNode (&Question->OptionListHead, Link);\r
628 }\r
629\r
f4113e1f 630 FreePool (*OptionString);\r
8d00a0f1 631 *OptionString = NULL;\r
40a06b0c 632 return EFI_NOT_FOUND;\r
c60a0616 633 }\r
634\r
82612023
ED
635 Character[0] = LEFT_ONEOF_DELIMITER;\r
636 NewStrCat (OptionString[0], Character);\r
637 StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
638 ASSERT (StringPtr != NULL);\r
639 NewStrCat (OptionString[0], StringPtr);\r
640 Character[0] = RIGHT_ONEOF_DELIMITER;\r
641 NewStrCat (OptionString[0], Character);\r
c60a0616 642\r
82612023 643 FreePool (StringPtr);\r
c60a0616 644 }\r
645 break;\r
646\r
647 case EFI_IFR_CHECKBOX_OP:\r
648 *OptionString = AllocateZeroPool (BufferSize);\r
649 ASSERT (*OptionString);\r
650\r
651 *OptionString[0] = LEFT_CHECKBOX_DELIMITER;\r
652\r
653 if (Selected) {\r
654 //\r
655 // Since this is a BOOLEAN operation, flip it upon selection\r
656 //\r
657 QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);\r
658\r
659 //\r
660 // Perform inconsistent check\r
661 //\r
662 Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
663 if (EFI_ERROR (Status)) {\r
664 //\r
665 // Inconsistent check fail, restore Question Value\r
666 //\r
667 QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);\r
f4113e1f 668 FreePool (*OptionString);\r
8d00a0f1 669 *OptionString = NULL;\r
c60a0616 670 return Status;\r
671 }\r
672\r
673 //\r
674 // Save Question value\r
675 //\r
816a7110 676 Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
b18e7050 677 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
c60a0616 678 }\r
679\r
680 if (QuestionValue->Value.b) {\r
681 *(OptionString[0] + 1) = CHECK_ON;\r
682 } else {\r
683 *(OptionString[0] + 1) = CHECK_OFF;\r
684 }\r
685 *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;\r
686 break;\r
687\r
688 case EFI_IFR_NUMERIC_OP:\r
689 if (Selected) {\r
690 //\r
691 // Go ask for input\r
692 //\r
693 Status = GetNumericInput (Selection, MenuOption);\r
694 } else {\r
695 *OptionString = AllocateZeroPool (BufferSize);\r
696 ASSERT (*OptionString);\r
697\r
698 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
699\r
700 //\r
701 // Formatted print\r
702 //\r
703 PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
704 Number = (UINT16) GetStringWidth (FormattedNumber);\r
705 CopyMem (OptionString[0] + 1, FormattedNumber, Number);\r
706\r
707 *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;\r
708 }\r
709 break;\r
710\r
711 case EFI_IFR_DATE_OP:\r
712 if (Selected) {\r
713 //\r
714 // This is similar to numerics\r
715 //\r
716 Status = GetNumericInput (Selection, MenuOption);\r
717 } else {\r
718 *OptionString = AllocateZeroPool (BufferSize);\r
719 ASSERT (*OptionString);\r
720\r
721 switch (MenuOption->Sequence) {\r
722 case 0:\r
723 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
724 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);\r
725 *(OptionString[0] + 3) = DATE_SEPARATOR;\r
726 break;\r
727\r
728 case 1:\r
729 SetUnicodeMem (OptionString[0], 4, L' ');\r
730 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);\r
731 *(OptionString[0] + 6) = DATE_SEPARATOR;\r
732 break;\r
733\r
734 case 2:\r
735 SetUnicodeMem (OptionString[0], 7, L' ');\r
4a6876b7 736 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);\r
c60a0616 737 *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;\r
738 break;\r
739 }\r
740 }\r
741 break;\r
742\r
743 case EFI_IFR_TIME_OP:\r
744 if (Selected) {\r
745 //\r
746 // This is similar to numerics\r
747 //\r
748 Status = GetNumericInput (Selection, MenuOption);\r
749 } else {\r
750 *OptionString = AllocateZeroPool (BufferSize);\r
751 ASSERT (*OptionString);\r
752\r
753 switch (MenuOption->Sequence) {\r
754 case 0:\r
755 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
756 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);\r
757 *(OptionString[0] + 3) = TIME_SEPARATOR;\r
758 break;\r
759\r
760 case 1:\r
761 SetUnicodeMem (OptionString[0], 4, L' ');\r
762 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);\r
763 *(OptionString[0] + 6) = TIME_SEPARATOR;\r
764 break;\r
765\r
766 case 2:\r
767 SetUnicodeMem (OptionString[0], 7, L' ');\r
768 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);\r
769 *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;\r
770 break;\r
771 }\r
772 }\r
773 break;\r
774\r
775 case EFI_IFR_STRING_OP:\r
776 if (Selected) {\r
777 StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
778 ASSERT (StringPtr);\r
da588638 779 CopyMem(StringPtr, Question->BufferValue, Maximum * sizeof (CHAR16));\r
c60a0616 780\r
781 Status = ReadString (MenuOption, gPromptForData, StringPtr);\r
782 if (!EFI_ERROR (Status)) {\r
e2100bfa
ED
783 HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
784 Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
785 if (EFI_ERROR (Status)) {\r
786 HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
787 } else {\r
788 CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
816a7110 789 SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
c60a0616 790\r
b18e7050 791 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
e2100bfa 792 }\r
c60a0616 793 }\r
794\r
f4113e1f 795 FreePool (StringPtr);\r
c60a0616 796 } else {\r
797 *OptionString = AllocateZeroPool (BufferSize);\r
798 ASSERT (*OptionString);\r
799\r
800 if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) {\r
801 *(OptionString[0]) = '_';\r
802 } else {\r
803 if ((Maximum * sizeof (CHAR16)) < BufferSize) {\r
804 BufferSize = Maximum * sizeof (CHAR16);\r
805 }\r
806 CopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize);\r
807 }\r
808 }\r
809 break;\r
810\r
811 case EFI_IFR_PASSWORD_OP:\r
812 if (Selected) {\r
813 StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
814 ASSERT (StringPtr);\r
815\r
816 //\r
817 // For interactive passwords, old password is validated by callback\r
818 //\r
819 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
820 //\r
821 // Use a NULL password to test whether old password is required\r
822 //\r
823 *StringPtr = 0;\r
824 Status = PasswordCallback (Selection, MenuOption, StringPtr);\r
13ad1def 825 if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {\r
c60a0616 826 //\r
13ad1def 827 // Callback is not supported, or\r
c60a0616 828 // Callback request to terminate password input\r
829 //\r
f4113e1f 830 FreePool (StringPtr);\r
c60a0616 831 return EFI_SUCCESS;\r
832 }\r
833\r
834 if (EFI_ERROR (Status)) {\r
835 //\r
836 // Old password exist, ask user for the old password\r
837 //\r
838 Status = ReadString (MenuOption, gPromptForPassword, StringPtr);\r
839 if (EFI_ERROR (Status)) {\r
f4113e1f 840 FreePool (StringPtr);\r
c60a0616 841 return Status;\r
842 }\r
843\r
844 //\r
845 // Check user input old password\r
846 //\r
847 Status = PasswordCallback (Selection, MenuOption, StringPtr);\r
848 if (EFI_ERROR (Status)) {\r
849 if (Status == EFI_NOT_READY) {\r
850 //\r
851 // Typed in old password incorrect\r
852 //\r
853 PasswordInvalid ();\r
854 } else {\r
855 Status = EFI_SUCCESS;\r
856 }\r
857\r
f4113e1f 858 FreePool (StringPtr);\r
c60a0616 859 return Status;\r
860 }\r
861 }\r
862 } else {\r
863 //\r
864 // For non-interactive password, validate old password in local\r
865 //\r
866 if (*((CHAR16 *) Question->BufferValue) != 0) {\r
867 //\r
868 // There is something there! Prompt for password\r
869 //\r
870 Status = ReadString (MenuOption, gPromptForPassword, StringPtr);\r
871 if (EFI_ERROR (Status)) {\r
f4113e1f 872 FreePool (StringPtr);\r
c60a0616 873 return Status;\r
874 }\r
875\r
876 TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue);\r
40a06b0c 877 ASSERT (TempString != NULL);\r
8b0fc5c1 878\r
c60a0616 879 TempString[Maximum] = L'\0';\r
880\r
881 if (StrCmp (StringPtr, TempString) != 0) {\r
882 //\r
883 // Typed in old password incorrect\r
884 //\r
885 PasswordInvalid ();\r
886\r
f4113e1f 887 FreePool (StringPtr);\r
888 FreePool (TempString);\r
c60a0616 889 return Status;\r
890 }\r
891\r
f4113e1f 892 FreePool (TempString);\r
c60a0616 893 }\r
894 }\r
895\r
896 //\r
897 // Ask for new password\r
898 //\r
899 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));\r
900 Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);\r
901 if (EFI_ERROR (Status)) {\r
902 //\r
903 // Reset state machine for interactive password\r
904 //\r
905 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
906 PasswordCallback (Selection, MenuOption, NULL);\r
907 }\r
908\r
f4113e1f 909 FreePool (StringPtr);\r
c60a0616 910 return Status;\r
911 }\r
912\r
913 //\r
914 // Confirm new password\r
915 //\r
916 TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
917 ASSERT (TempString);\r
918 Status = ReadString (MenuOption, gConfirmPassword, TempString);\r
919 if (EFI_ERROR (Status)) {\r
920 //\r
921 // Reset state machine for interactive password\r
922 //\r
923 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
924 PasswordCallback (Selection, MenuOption, NULL);\r
925 }\r
926\r
f4113e1f 927 FreePool (StringPtr);\r
928 FreePool (TempString);\r
c60a0616 929 return Status;\r
930 }\r
931\r
932 //\r
933 // Compare two typed-in new passwords\r
934 //\r
935 if (StrCmp (StringPtr, TempString) == 0) {\r
936 //\r
e2100bfa 937 // Prepare the Question->HiiValue.Value.string for ValidateQuestion use.\r
c60a0616 938 //\r
e2100bfa
ED
939 if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
940 StringId = Question->HiiValue.Value.string;\r
941 Question->HiiValue.Value.string = NewString (StringPtr, Selection->FormSet->HiiHandle);\r
c60a0616 942 } else {\r
e2100bfa
ED
943 HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
944 }\r
945 \r
946 Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
947\r
948 //\r
949 // Researve the Question->HiiValue.Value.string.\r
950 //\r
951 if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
952 DeleteString(Question->HiiValue.Value.string, Selection->FormSet->HiiHandle);\r
953 Question->HiiValue.Value.string = StringId;\r
954 } \r
955 \r
956 if (EFI_ERROR (Status)) {\r
957 //\r
958 // Reset state machine for interactive password\r
959 //\r
960 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
961 PasswordCallback (Selection, MenuOption, NULL);\r
962 } else {\r
963 //\r
964 // Researve the Question->HiiValue.Value.string.\r
965 //\r
966 HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL); \r
967 }\r
968 } else {\r
969 //\r
970 // Two password match, send it to Configuration Driver\r
971 //\r
972 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
973 PasswordCallback (Selection, MenuOption, StringPtr);\r
974 } else {\r
975 CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
816a7110 976 SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);\r
e2100bfa 977 }\r
c60a0616 978 }\r
979 } else {\r
980 //\r
981 // Reset state machine for interactive password\r
982 //\r
983 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
984 PasswordCallback (Selection, MenuOption, NULL);\r
985 }\r
986\r
987 //\r
988 // Two password mismatch, prompt error message\r
989 //\r
990 do {\r
991 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString);\r
992 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
993 }\r
994\r
f4113e1f 995 FreePool (TempString);\r
996 FreePool (StringPtr);\r
c60a0616 997 }\r
998 break;\r
999\r
1000 default:\r
1001 break;\r
1002 }\r
1003\r
1004 return Status;\r
1005}\r
1006\r
1007\r
1008/**\r
1009 Process the help string: Split StringPtr to several lines of strings stored in\r
1010 FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
1011\r
1012 @param StringPtr The entire help string.\r
1013 @param FormattedString The oupput formatted string.\r
6c310dfb 1014 @param EachLineWidth The max string length of each line in the formatted string.\r
c60a0616 1015 @param RowCount TRUE: if Question is selected.\r
1016\r
1017**/\r
ba46ab94 1018UINTN\r
c60a0616 1019ProcessHelpString (\r
1020 IN CHAR16 *StringPtr,\r
1021 OUT CHAR16 **FormattedString,\r
6c310dfb 1022 OUT UINT16 *EachLineWidth,\r
c60a0616 1023 IN UINTN RowCount\r
1024 )\r
1025{\r
5ea466a5
ED
1026 UINTN Index;\r
1027 CHAR16 *OutputString;\r
1028 UINTN TotalRowNum;\r
1029 UINTN CheckedNum;\r
6c310dfb
ED
1030 UINT16 GlyphWidth;\r
1031 UINT16 LineWidth;\r
1032 UINT16 MaxStringLen;\r
1033 UINT16 StringLen;\r
1034\r
1035 TotalRowNum = 0;\r
1036 CheckedNum = 0;\r
1037 GlyphWidth = 1;\r
1038 Index = 0;\r
1039 MaxStringLen = 0;\r
1040 StringLen = 0;\r
c60a0616 1041\r
6c310dfb
ED
1042 //\r
1043 // Set default help string width.\r
1044 //\r
1045 LineWidth = (UINT16) (gHelpBlockWidth - 1);\r
8b0fc5c1 1046\r
c60a0616 1047 //\r
5ea466a5 1048 // Get row number of the String.\r
c60a0616 1049 //\r
6c310dfb
ED
1050 while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
1051 if (StringLen > MaxStringLen) {\r
1052 MaxStringLen = StringLen;\r
1053 }\r
1054\r
5ea466a5
ED
1055 TotalRowNum ++;\r
1056 FreePool (OutputString);\r
c60a0616 1057 }\r
6c310dfb
ED
1058 *EachLineWidth = MaxStringLen;\r
1059\r
1060 *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));\r
40a06b0c 1061 ASSERT (*FormattedString != NULL);\r
c60a0616 1062\r
6c310dfb
ED
1063 //\r
1064 // Generate formatted help string array.\r
1065 //\r
1066 GlyphWidth = 1;\r
1067 Index = 0;\r
1068 while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
1069 CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));\r
1070 CheckedNum ++;\r
5ea466a5 1071 FreePool (OutputString);\r
c60a0616 1072 }\r
1073\r
5ea466a5 1074 return TotalRowNum; \r
c60a0616 1075}\r