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