]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
BaseTools: Enhance the check for numeric opcode with EFI_IFR_DISPLAY_INT_DEC attribute.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
... / ...
CommitLineData
1/** @file\r
2Entry and initialization module for the browser.\r
3\r
4Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
16\r
17SETUP_DRIVER_PRIVATE_DATA mPrivateData = {\r
18 SETUP_DRIVER_SIGNATURE,\r
19 NULL,\r
20 {\r
21 SendForm,\r
22 BrowserCallback\r
23 },\r
24 {\r
25 SetScope,\r
26 RegisterHotKey,\r
27 RegiserExitHandler,\r
28 SaveReminder\r
29 },\r
30 {\r
31 BROWSER_EXTENSION2_VERSION_1_1,\r
32 SetScope,\r
33 RegisterHotKey,\r
34 RegiserExitHandler,\r
35 IsBrowserDataModified,\r
36 ExecuteAction,\r
37 {NULL,NULL},\r
38 {NULL,NULL},\r
39 IsResetRequired\r
40 }\r
41};\r
42\r
43EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
44EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
45EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;\r
46EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;\r
47\r
48UINTN gBrowserContextCount = 0;\r
49LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
50LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);\r
51LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);\r
52LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);\r
53LIST_ENTRY gBrowserSaveFailFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList);\r
54\r
55BOOLEAN mSystemSubmit = FALSE;\r
56BOOLEAN gResetRequired;\r
57BOOLEAN gExitRequired;\r
58BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;\r
59BOOLEAN mBrowserScopeFirstSet = TRUE;\r
60EXIT_HANDLER ExitHandlerFunction = NULL;\r
61FORM_BROWSER_FORMSET *mSystemLevelFormSet;\r
62\r
63//\r
64// Browser Global Strings\r
65//\r
66CHAR16 *gEmptyString;\r
67CHAR16 *mUnknownString = L"!";\r
68\r
69EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
70\r
71extern EFI_GUID mCurrentFormSetGuid;\r
72extern EFI_HII_HANDLE mCurrentHiiHandle;\r
73extern UINT16 mCurrentFormId;\r
74extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
75\r
76/**\r
77 Create a menu with specified formset GUID and form ID, and add it as a child\r
78 of the given parent menu.\r
79\r
80 @param HiiHandle Hii handle related to this formset.\r
81 @param FormSetGuid The Formset Guid of menu to be added.\r
82 @param FormId The Form ID of menu to be added.\r
83 @param QuestionId The question id of this menu to be added.\r
84\r
85 @return A pointer to the newly added menu or NULL if memory is insufficient.\r
86\r
87**/\r
88FORM_ENTRY_INFO *\r
89UiAddMenuList (\r
90 IN EFI_HII_HANDLE HiiHandle,\r
91 IN EFI_GUID *FormSetGuid,\r
92 IN UINT16 FormId,\r
93 IN UINT16 QuestionId\r
94 )\r
95{\r
96 FORM_ENTRY_INFO *MenuList;\r
97\r
98 MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
99 if (MenuList == NULL) {\r
100 return NULL;\r
101 }\r
102\r
103 MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
104\r
105 MenuList->HiiHandle = HiiHandle;\r
106 CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
107 MenuList->FormId = FormId;\r
108 MenuList->QuestionId = QuestionId;\r
109\r
110 //\r
111 // If parent is not specified, it is the root Form of a Formset\r
112 //\r
113 InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
114\r
115 return MenuList;\r
116}\r
117\r
118/**\r
119 Return the form id for the input hiihandle and formset.\r
120\r
121 @param HiiHandle HiiHandle for FormSet.\r
122 @param FormSetGuid The Formset GUID of the menu to search.\r
123\r
124 @return First form's id for this form set.\r
125\r
126**/\r
127EFI_FORM_ID\r
128GetFirstFormId (\r
129 IN EFI_HII_HANDLE HiiHandle,\r
130 IN EFI_GUID *FormSetGuid\r
131 )\r
132{\r
133 LIST_ENTRY *Link;\r
134 FORM_BROWSER_FORM *Form;\r
135\r
136 Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);\r
137 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
138\r
139 return Form->FormId;\r
140}\r
141\r
142/**\r
143 Search Menu with given FormSetGuid and FormId in all cached menu list.\r
144\r
145 @param HiiHandle HiiHandle for FormSet.\r
146 @param FormSetGuid The Formset GUID of the menu to search.\r
147 @param FormId The Form ID of menu to search.\r
148\r
149 @return A pointer to menu found or NULL if not found.\r
150\r
151**/\r
152FORM_ENTRY_INFO *\r
153UiFindMenuList (\r
154 IN EFI_HII_HANDLE HiiHandle, \r
155 IN EFI_GUID *FormSetGuid,\r
156 IN UINT16 FormId\r
157 )\r
158{\r
159 LIST_ENTRY *Link;\r
160 FORM_ENTRY_INFO *MenuList;\r
161 FORM_ENTRY_INFO *RetMenu;\r
162 EFI_FORM_ID FirstFormId;\r
163\r
164 RetMenu = NULL;\r
165\r
166 Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
167 while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) {\r
168 MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
169 Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link);\r
170 \r
171 //\r
172 // If already find the menu, free the menus behind it.\r
173 //\r
174 if (RetMenu != NULL) {\r
175 RemoveEntryList (&MenuList->Link);\r
176 FreePool (MenuList);\r
177 continue;\r
178 }\r
179\r
180 //\r
181 // Find the same FromSet.\r
182 //\r
183 if (MenuList->HiiHandle == HiiHandle) {\r
184 if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) {\r
185 //\r
186 // FormSetGuid is not specified.\r
187 //\r
188 RetMenu = MenuList;\r
189 } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) {\r
190 if (MenuList->FormId == FormId) {\r
191 RetMenu = MenuList;\r
192 } else if (FormId == 0 || MenuList->FormId == 0 ) {\r
193 FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid);\r
194 if ((FormId == 0 && FirstFormId == MenuList->FormId) || (MenuList->FormId ==0 && FirstFormId == FormId)) {\r
195 RetMenu = MenuList;\r
196 }\r
197 }\r
198 }\r
199 }\r
200 }\r
201\r
202 return RetMenu;\r
203}\r
204\r
205/**\r
206 Find parent menu for current menu.\r
207\r
208 @param CurrentMenu Current Menu\r
209 @param SettingLevel Whether find parent menu in Form Level or Formset level.\r
210 In form level, just find the parent menu; \r
211 In formset level, find the parent menu which has different\r
212 formset guid value.\r
213\r
214 @retval The parent menu for current menu.\r
215**/\r
216FORM_ENTRY_INFO *\r
217UiFindParentMenu (\r
218 IN FORM_ENTRY_INFO *CurrentMenu,\r
219 IN BROWSER_SETTING_SCOPE SettingLevel\r
220 )\r
221{\r
222 FORM_ENTRY_INFO *ParentMenu;\r
223 LIST_ENTRY *Link;\r
224\r
225 ASSERT (SettingLevel == FormLevel || SettingLevel == FormSetLevel);\r
226\r
227 if (CurrentMenu == NULL) {\r
228 return NULL;\r
229 }\r
230 \r
231 ParentMenu = NULL;\r
232 Link = &CurrentMenu->Link;\r
233\r
234 while (Link->BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
235 ParentMenu = FORM_ENTRY_INFO_FROM_LINK (Link->BackLink);\r
236\r
237 if (SettingLevel == FormLevel) {\r
238 //\r
239 // For FormLevel, just find the parent menu, return.\r
240 //\r
241 break;\r
242 }\r
243\r
244 if (!CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
245 //\r
246 // For SystemLevel, must find the menu which has different formset.\r
247 //\r
248 break;\r
249 }\r
250\r
251 Link = Link->BackLink;\r
252 }\r
253\r
254 //\r
255 // Not find the parent menu, just return NULL.\r
256 //\r
257 if (Link->BackLink == &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
258 return NULL;\r
259 }\r
260\r
261 return ParentMenu;\r
262}\r
263\r
264/**\r
265 Free Menu list linked list.\r
266\r
267 @param MenuListHead One Menu list point in the menu list.\r
268\r
269**/\r
270VOID\r
271UiFreeMenuList (\r
272 LIST_ENTRY *MenuListHead\r
273 )\r
274{\r
275 FORM_ENTRY_INFO *MenuList;\r
276\r
277 while (!IsListEmpty (MenuListHead)) {\r
278 MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink);\r
279 RemoveEntryList (&MenuList->Link);\r
280\r
281 FreePool (MenuList);\r
282 }\r
283}\r
284\r
285/**\r
286 Copy current Menu list to the new menu list.\r
287 \r
288 @param NewMenuListHead New create Menu list.\r
289 @param CurrentMenuListHead Current Menu list.\r
290\r
291**/\r
292VOID\r
293UiCopyMenuList (\r
294 OUT LIST_ENTRY *NewMenuListHead,\r
295 IN LIST_ENTRY *CurrentMenuListHead\r
296 )\r
297{\r
298 LIST_ENTRY *Link;\r
299 FORM_ENTRY_INFO *MenuList;\r
300 FORM_ENTRY_INFO *NewMenuEntry;\r
301\r
302 //\r
303 // If new menu list not empty, free it first.\r
304 //\r
305 UiFreeMenuList (NewMenuListHead);\r
306\r
307 Link = GetFirstNode (CurrentMenuListHead);\r
308 while (!IsNull (CurrentMenuListHead, Link)) {\r
309 MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
310 Link = GetNextNode (CurrentMenuListHead, Link);\r
311\r
312 NewMenuEntry = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
313 ASSERT (NewMenuEntry != NULL);\r
314 NewMenuEntry->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
315 NewMenuEntry->HiiHandle = MenuList->HiiHandle;\r
316 CopyMem (&NewMenuEntry->FormSetGuid, &MenuList->FormSetGuid, sizeof (EFI_GUID));\r
317 NewMenuEntry->FormId = MenuList->FormId;\r
318 NewMenuEntry->QuestionId = MenuList->QuestionId;\r
319\r
320 InsertTailList (NewMenuListHead, &NewMenuEntry->Link);\r
321 }\r
322}\r
323\r
324/**\r
325 Load all hii formset to the browser.\r
326\r
327**/\r
328VOID\r
329LoadAllHiiFormset (\r
330 VOID\r
331 )\r
332{\r
333 FORM_BROWSER_FORMSET *LocalFormSet;\r
334 EFI_HII_HANDLE *HiiHandles;\r
335 UINTN Index;\r
336 EFI_GUID ZeroGuid;\r
337 EFI_STATUS Status;\r
338 FORM_BROWSER_FORMSET *OldFormset;\r
339\r
340 OldFormset = mSystemLevelFormSet;\r
341\r
342 //\r
343 // Get all the Hii handles\r
344 //\r
345 HiiHandles = HiiGetHiiHandles (NULL);\r
346 ASSERT (HiiHandles != NULL);\r
347\r
348 //\r
349 // Search for formset of each class type\r
350 //\r
351 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
352 //\r
353 // Check HiiHandles[Index] does exist in global maintain list.\r
354 //\r
355 if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
356 continue;\r
357 }\r
358\r
359 //\r
360 // Initilize FormSet Setting\r
361 //\r
362 LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
363 ASSERT (LocalFormSet != NULL);\r
364 mSystemLevelFormSet = LocalFormSet;\r
365\r
366 ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
367 Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);\r
368 if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
369 DestroyFormSet (LocalFormSet);\r
370 continue;\r
371 }\r
372 InitializeCurrentSetting (LocalFormSet);\r
373\r
374 //\r
375 // Initilize Questions' Value\r
376 //\r
377 Status = LoadFormSetConfig (NULL, LocalFormSet);\r
378 if (EFI_ERROR (Status)) {\r
379 DestroyFormSet (LocalFormSet);\r
380 continue;\r
381 }\r
382 }\r
383\r
384 //\r
385 // Free resources, and restore gOldFormSet and gClassOfVfr\r
386 //\r
387 FreePool (HiiHandles);\r
388\r
389 mSystemLevelFormSet = OldFormset;\r
390}\r
391\r
392/**\r
393 Pop up the error info.\r
394\r
395 @param BrowserStatus The input browser status.\r
396 @param HiiHandle The Hiihandle for this opcode.\r
397 @param OpCode The opcode use to get the erro info and timeout value.\r
398 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.\r
399\r
400**/\r
401UINT32\r
402PopupErrorMessage (\r
403 IN UINT32 BrowserStatus,\r
404 IN EFI_HII_HANDLE HiiHandle,\r
405 IN EFI_IFR_OP_HEADER *OpCode, OPTIONAL\r
406 IN CHAR16 *ErrorString\r
407 )\r
408{\r
409 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
410 USER_INPUT UserInputData;\r
411\r
412 Statement = NULL;\r
413\r
414 if (OpCode != NULL) {\r
415 Statement = AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT));\r
416 ASSERT (Statement != NULL);\r
417 Statement->OpCode = OpCode;\r
418 gDisplayFormData.HighLightedStatement = Statement;\r
419 }\r
420\r
421 //\r
422 // Used to compatible with old display engine.\r
423 // New display engine not use this field.\r
424 //\r
425 gDisplayFormData.ErrorString = ErrorString;\r
426 gDisplayFormData.BrowserStatus = BrowserStatus;\r
427\r
428 if (HiiHandle != NULL) {\r
429 gDisplayFormData.HiiHandle = HiiHandle;\r
430 }\r
431\r
432 mFormDisplay->FormDisplay (&gDisplayFormData, &UserInputData);\r
433\r
434 gDisplayFormData.BrowserStatus = BROWSER_SUCCESS;\r
435 gDisplayFormData.ErrorString = NULL;\r
436\r
437 if (OpCode != NULL) {\r
438 FreePool (Statement);\r
439 }\r
440\r
441 return UserInputData.Action;\r
442}\r
443\r
444/**\r
445 This is the routine which an external caller uses to direct the browser\r
446 where to obtain it's information.\r
447\r
448\r
449 @param This The Form Browser protocol instanse.\r
450 @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
451 display a list of the formsets for the handles specified.\r
452 @param HandleCount The number of Handles specified in Handle.\r
453 @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
454 field in the EFI_IFR_FORM_SET op-code for the specified\r
455 forms-based package. If FormSetGuid is NULL, then this\r
456 function will display the first found forms package.\r
457 @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
458 displayable page. If this field has a value of 0x0000, then\r
459 the forms browser will render the specified forms in their encoded order.\r
460 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
461 characters.\r
462 @param ActionRequest Points to the action recommended by the form.\r
463\r
464 @retval EFI_SUCCESS The function completed successfully.\r
465 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
466 @retval EFI_NOT_FOUND No valid forms could be found to display.\r
467\r
468**/\r
469EFI_STATUS\r
470EFIAPI\r
471SendForm (\r
472 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
473 IN EFI_HII_HANDLE *Handles,\r
474 IN UINTN HandleCount,\r
475 IN EFI_GUID *FormSetGuid, OPTIONAL\r
476 IN UINT16 FormId, OPTIONAL\r
477 IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
478 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
479 )\r
480{\r
481 EFI_STATUS Status;\r
482 UI_MENU_SELECTION *Selection;\r
483 UINTN Index;\r
484 FORM_BROWSER_FORMSET *FormSet;\r
485 FORM_ENTRY_INFO *MenuList;\r
486\r
487 //\r
488 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.\r
489 //\r
490 if (mFormDisplay == NULL) {\r
491 return EFI_UNSUPPORTED;\r
492 }\r
493\r
494 //\r
495 // Save globals used by SendForm()\r
496 //\r
497 SaveBrowserContext ();\r
498\r
499 gResetRequired = FALSE;\r
500 gExitRequired = FALSE;\r
501 Status = EFI_SUCCESS;\r
502 gEmptyString = L"";\r
503 gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions;\r
504\r
505 for (Index = 0; Index < HandleCount; Index++) {\r
506 Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
507 ASSERT (Selection != NULL);\r
508\r
509 Selection->Handle = Handles[Index];\r
510 if (FormSetGuid != NULL) {\r
511 CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
512 Selection->FormId = FormId;\r
513 } else {\r
514 CopyMem (&Selection->FormSetGuid, &gEfiHiiPlatformSetupFormsetGuid, sizeof (EFI_GUID));\r
515 }\r
516\r
517 do {\r
518 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
519 ASSERT (FormSet != NULL);\r
520\r
521 //\r
522 // Validate the HiiHandle\r
523 // if validate failed, find the first validate parent HiiHandle.\r
524 //\r
525 if (!ValidateHiiHandle(Selection->Handle)) {\r
526 FindNextMenu (Selection, FormSetLevel);\r
527 }\r
528\r
529 //\r
530 // Initialize internal data structures of FormSet\r
531 //\r
532 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
533 if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
534 DestroyFormSet (FormSet);\r
535 break;\r
536 }\r
537 Selection->FormSet = FormSet;\r
538 mSystemLevelFormSet = FormSet;\r
539\r
540 //\r
541 // Display this formset\r
542 //\r
543 gCurrentSelection = Selection;\r
544\r
545 Status = SetupBrowser (Selection);\r
546\r
547 gCurrentSelection = NULL;\r
548 mSystemLevelFormSet = NULL;\r
549\r
550 //\r
551 // If no data is changed, don't need to save current FormSet into the maintain list.\r
552 //\r
553 if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
554 CleanBrowserStorage(FormSet);\r
555 RemoveEntryList (&FormSet->Link);\r
556 DestroyFormSet (FormSet);\r
557 }\r
558\r
559 if (EFI_ERROR (Status)) {\r
560 break;\r
561 }\r
562 } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
563\r
564 FreePool (Selection);\r
565 }\r
566\r
567 if (ActionRequest != NULL) {\r
568 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
569 if (gResetRequired) {\r
570 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
571 }\r
572 }\r
573\r
574 mFormDisplay->ExitDisplay();\r
575\r
576 //\r
577 // Clear the menu history data.\r
578 //\r
579 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
580 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
581 RemoveEntryList (&MenuList->Link);\r
582 FreePool (MenuList);\r
583 }\r
584\r
585 //\r
586 // Restore globals used by SendForm()\r
587 //\r
588 RestoreBrowserContext ();\r
589\r
590 return Status;\r
591}\r
592\r
593/**\r
594 Get or set data to the storage.\r
595\r
596 @param ResultsDataSize The size of the buffer associatedwith ResultsData.\r
597 @param ResultsData A string returned from an IFR browser or\r
598 equivalent. The results string will have no\r
599 routing information in them.\r
600 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
601 (if RetrieveData = TRUE) data from the uncommitted\r
602 browser state information or set (if RetrieveData\r
603 = FALSE) data in the uncommitted browser state\r
604 information.\r
605 @param Storage The pointer to the storage.\r
606\r
607 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
608 distribution.\r
609\r
610**/\r
611EFI_STATUS \r
612ProcessStorage (\r
613 IN OUT UINTN *ResultsDataSize,\r
614 IN OUT EFI_STRING *ResultsData,\r
615 IN BOOLEAN RetrieveData,\r
616 IN BROWSER_STORAGE *Storage\r
617 )\r
618{\r
619 CHAR16 *ConfigResp;\r
620 EFI_STATUS Status;\r
621 CHAR16 *StrPtr;\r
622 UINTN BufferSize;\r
623 UINTN TmpSize;\r
624 FORMSET_STORAGE *BrowserStorage;\r
625\r
626 if (RetrieveData) {\r
627 //\r
628 // Generate <ConfigResp>\r
629 //\r
630 Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);\r
631 if (EFI_ERROR (Status)) {\r
632 return Status;\r
633 }\r
634\r
635 //\r
636 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.\r
637 // Also need to consider add "\0" at first time.\r
638 //\r
639 StrPtr = StrStr (ConfigResp, L"PATH");\r
640 ASSERT (StrPtr != NULL);\r
641 StrPtr = StrStr (StrPtr, L"&");\r
642 StrPtr += 1;\r
643 BufferSize = StrSize (StrPtr);\r
644\r
645 //\r
646 // Copy the data if the input buffer is bigger enough.\r
647 //\r
648 if (*ResultsDataSize >= BufferSize) {\r
649 StrCpy (*ResultsData, StrPtr);\r
650 }\r
651\r
652 *ResultsDataSize = BufferSize;\r
653 FreePool (ConfigResp);\r
654 } else {\r
655 //\r
656 // Prepare <ConfigResp>\r
657 //\r
658 BrowserStorage = GetFstStgFromBrsStg (Storage);\r
659 ASSERT (BrowserStorage != NULL);\r
660 TmpSize = StrLen (*ResultsData);\r
661 BufferSize = (TmpSize + StrLen (BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);\r
662 ConfigResp = AllocateZeroPool (BufferSize);\r
663 ASSERT (ConfigResp != NULL);\r
664\r
665 StrCpy (ConfigResp, BrowserStorage->ConfigHdr);\r
666 StrCat (ConfigResp, L"&");\r
667 StrCat (ConfigResp, *ResultsData);\r
668\r
669 //\r
670 // Update Browser uncommited data\r
671 //\r
672 Status = ConfigRespToStorage (Storage, ConfigResp);\r
673 FreePool (ConfigResp);\r
674 if (EFI_ERROR (Status)) {\r
675 return Status;\r
676 }\r
677 }\r
678\r
679 return EFI_SUCCESS;\r
680}\r
681\r
682/**\r
683 This routine called this service in the browser to retrieve or set certain uncommitted \r
684 state information that resides in the open formsets. \r
685\r
686 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
687 instance.\r
688 @param ResultsDataSize A pointer to the size of the buffer associated\r
689 with ResultsData.\r
690 @param ResultsData A string returned from an IFR browser or\r
691 equivalent. The results string will have no\r
692 routing information in them.\r
693 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
694 (if RetrieveData = TRUE) data from the uncommitted\r
695 browser state information or set (if RetrieveData\r
696 = FALSE) data in the uncommitted browser state\r
697 information.\r
698 @param VariableGuid An optional field to indicate the target variable\r
699 GUID name to use.\r
700 @param VariableName An optional field to indicate the target\r
701 human-readable variable name.\r
702\r
703 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
704 distribution.\r
705 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
706 contain the results data.\r
707\r
708**/\r
709EFI_STATUS\r
710EFIAPI\r
711BrowserCallback (\r
712 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
713 IN OUT UINTN *ResultsDataSize,\r
714 IN OUT EFI_STRING ResultsData,\r
715 IN BOOLEAN RetrieveData,\r
716 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
717 IN CONST CHAR16 *VariableName OPTIONAL\r
718 )\r
719{\r
720 EFI_STATUS Status;\r
721 LIST_ENTRY *Link;\r
722 BROWSER_STORAGE *Storage;\r
723 FORMSET_STORAGE *FormsetStorage;\r
724 UINTN TotalSize;\r
725 BOOLEAN Found;\r
726\r
727 if (ResultsDataSize == NULL || ResultsData == NULL) {\r
728 return EFI_INVALID_PARAMETER;\r
729 }\r
730\r
731 TotalSize = *ResultsDataSize;\r
732 Storage = NULL;\r
733 Found = FALSE;\r
734 Status = EFI_SUCCESS;\r
735\r
736 if (VariableGuid != NULL) {\r
737 //\r
738 // Try to find target storage in the current formset.\r
739 //\r
740 Link = GetFirstNode (&gBrowserStorageList);\r
741 while (!IsNull (&gBrowserStorageList, Link)) {\r
742 Storage = BROWSER_STORAGE_FROM_LINK (Link);\r
743 Link = GetNextNode (&gBrowserStorageList, Link);\r
744 //\r
745 // Check the current storage.\r
746 //\r
747 if (!CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
748 continue;\r
749 }\r
750\r
751 if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||\r
752 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
753 //\r
754 // Buffer storage require both GUID and Name\r
755 //\r
756 if (VariableName == NULL) {\r
757 return EFI_NOT_FOUND;\r
758 }\r
759\r
760 if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
761 continue;\r
762 }\r
763 }\r
764\r
765 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE ||\r
766 Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
767 if (mSystemLevelFormSet == NULL || mSystemLevelFormSet->HiiHandle == NULL) {\r
768 return EFI_NOT_FOUND;\r
769 }\r
770\r
771 if (Storage->HiiHandle != mSystemLevelFormSet->HiiHandle) {\r
772 continue;\r
773 }\r
774 }\r
775\r
776 Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);\r
777 if (EFI_ERROR (Status)) {\r
778 return Status;\r
779 }\r
780\r
781 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
782 ConfigRequestAdjust (Storage, ResultsData, TRUE);\r
783 }\r
784\r
785 //\r
786 // Different formsets may have same varstore, so here just set the flag\r
787 // not exit the circle.\r
788 // \r
789 Found = TRUE;\r
790 break;\r
791 }\r
792\r
793 if (!Found) {\r
794 return EFI_NOT_FOUND;\r
795 }\r
796 } else {\r
797 //\r
798 // GUID/Name is not specified, take the first storage in FormSet\r
799 //\r
800 if (mSystemLevelFormSet == NULL) {\r
801 return EFI_NOT_READY;\r
802 }\r
803\r
804 //\r
805 // Generate <ConfigResp>\r
806 //\r
807 Link = GetFirstNode (&mSystemLevelFormSet->StorageListHead);\r
808 if (IsNull (&mSystemLevelFormSet->StorageListHead, Link)) {\r
809 return EFI_UNSUPPORTED;\r
810 }\r
811\r
812 FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
813 \r
814 Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);\r
815 if (EFI_ERROR (Status)) {\r
816 return Status;\r
817 }\r
818 }\r
819\r
820 if (RetrieveData) {\r
821 Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
822 *ResultsDataSize = TotalSize;\r
823 }\r
824 \r
825 return Status;\r
826\r
827}\r
828\r
829\r
830/**\r
831 Callback function for SimpleTextInEx protocol install events\r
832\r
833 @param Event the event that is signaled.\r
834 @param Context not used here.\r
835\r
836**/\r
837VOID\r
838EFIAPI\r
839FormDisplayCallback (\r
840 IN EFI_EVENT Event,\r
841 IN VOID *Context\r
842 )\r
843{\r
844 if (mFormDisplay != NULL) {\r
845 return;\r
846 }\r
847\r
848 gBS->LocateProtocol (\r
849 &gEdkiiFormDisplayEngineProtocolGuid,\r
850 NULL,\r
851 (VOID **) &mFormDisplay\r
852 );\r
853}\r
854\r
855/**\r
856 Initialize Setup Browser driver.\r
857\r
858 @param ImageHandle The image handle.\r
859 @param SystemTable The system table.\r
860\r
861 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
862 @return Other value if failed to initialize the Setup Browser module.\r
863\r
864**/\r
865EFI_STATUS\r
866EFIAPI\r
867InitializeSetup (\r
868 IN EFI_HANDLE ImageHandle,\r
869 IN EFI_SYSTEM_TABLE *SystemTable\r
870 )\r
871{\r
872 EFI_STATUS Status;\r
873 VOID *Registration;\r
874\r
875 //\r
876 // Locate required Hii relative protocols\r
877 //\r
878 Status = gBS->LocateProtocol (\r
879 &gEfiHiiDatabaseProtocolGuid,\r
880 NULL,\r
881 (VOID **) &mHiiDatabase\r
882 );\r
883 ASSERT_EFI_ERROR (Status);\r
884\r
885 Status = gBS->LocateProtocol (\r
886 &gEfiHiiConfigRoutingProtocolGuid,\r
887 NULL,\r
888 (VOID **) &mHiiConfigRouting\r
889 );\r
890 ASSERT_EFI_ERROR (Status);\r
891\r
892 Status = gBS->LocateProtocol (\r
893 &gEfiDevicePathFromTextProtocolGuid,\r
894 NULL,\r
895 (VOID **) &mPathFromText\r
896 );\r
897\r
898 //\r
899 // Install FormBrowser2 protocol\r
900 //\r
901 mPrivateData.Handle = NULL;\r
902 Status = gBS->InstallProtocolInterface (\r
903 &mPrivateData.Handle,\r
904 &gEfiFormBrowser2ProtocolGuid,\r
905 EFI_NATIVE_INTERFACE,\r
906 &mPrivateData.FormBrowser2\r
907 );\r
908 ASSERT_EFI_ERROR (Status);\r
909\r
910 //\r
911 // Install FormBrowserEx2 protocol\r
912 //\r
913 InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
914 InitializeListHead (&mPrivateData.FormBrowserEx2.OverrideQestListHead);\r
915 mPrivateData.Handle = NULL;\r
916 Status = gBS->InstallProtocolInterface (\r
917 &mPrivateData.Handle,\r
918 &gEdkiiFormBrowserEx2ProtocolGuid,\r
919 EFI_NATIVE_INTERFACE,\r
920 &mPrivateData.FormBrowserEx2\r
921 );\r
922 ASSERT_EFI_ERROR (Status);\r
923 \r
924 Status = gBS->InstallProtocolInterface (\r
925 &mPrivateData.Handle,\r
926 &gEfiFormBrowserExProtocolGuid,\r
927 EFI_NATIVE_INTERFACE,\r
928 &mPrivateData.FormBrowserEx\r
929 );\r
930 ASSERT_EFI_ERROR (Status);\r
931\r
932 InitializeDisplayFormData ();\r
933\r
934 Status = gBS->LocateProtocol (\r
935 &gEdkiiFormDisplayEngineProtocolGuid,\r
936 NULL,\r
937 (VOID **) &mFormDisplay\r
938 );\r
939\r
940 if (EFI_ERROR (Status)) {\r
941 EfiCreateProtocolNotifyEvent (\r
942 &gEdkiiFormDisplayEngineProtocolGuid,\r
943 TPL_CALLBACK,\r
944 FormDisplayCallback,\r
945 NULL,\r
946 &Registration\r
947 );\r
948 }\r
949 \r
950 return EFI_SUCCESS;\r
951}\r
952\r
953\r
954/**\r
955 Create a new string in HII Package List.\r
956\r
957 @param String The String to be added\r
958 @param HiiHandle The package list in the HII database to insert the\r
959 specified string.\r
960\r
961 @return The output string.\r
962\r
963**/\r
964EFI_STRING_ID\r
965NewString (\r
966 IN CHAR16 *String,\r
967 IN EFI_HII_HANDLE HiiHandle\r
968 )\r
969{\r
970 EFI_STRING_ID StringId;\r
971\r
972 StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
973 ASSERT (StringId != 0);\r
974\r
975 return StringId;\r
976}\r
977\r
978\r
979/**\r
980 Delete a string from HII Package List.\r
981\r
982 @param StringId Id of the string in HII database.\r
983 @param HiiHandle The HII package list handle.\r
984\r
985 @retval EFI_SUCCESS The string was deleted successfully.\r
986\r
987**/\r
988EFI_STATUS\r
989DeleteString (\r
990 IN EFI_STRING_ID StringId,\r
991 IN EFI_HII_HANDLE HiiHandle\r
992 )\r
993{\r
994 CHAR16 NullChar;\r
995\r
996 NullChar = CHAR_NULL;\r
997 HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
998 return EFI_SUCCESS;\r
999}\r
1000\r
1001\r
1002/**\r
1003 Get the string based on the StringId and HII Package List Handle.\r
1004\r
1005 @param Token The String's ID.\r
1006 @param HiiHandle The package list in the HII database to search for\r
1007 the specified string.\r
1008\r
1009 @return The output string.\r
1010\r
1011**/\r
1012CHAR16 *\r
1013GetToken (\r
1014 IN EFI_STRING_ID Token,\r
1015 IN EFI_HII_HANDLE HiiHandle\r
1016 )\r
1017{\r
1018 EFI_STRING String;\r
1019\r
1020 if (HiiHandle == NULL) {\r
1021 return NULL;\r
1022 }\r
1023\r
1024 String = HiiGetString (HiiHandle, Token, NULL);\r
1025 if (String == NULL) {\r
1026 String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
1027 ASSERT (String != NULL);\r
1028 }\r
1029 return (CHAR16 *) String;\r
1030}\r
1031\r
1032\r
1033/**\r
1034 Allocate new memory and then copy the Unicode string Source to Destination.\r
1035\r
1036 @param Dest Location to copy string\r
1037 @param Src String to copy\r
1038\r
1039**/\r
1040VOID\r
1041NewStringCpy (\r
1042 IN OUT CHAR16 **Dest,\r
1043 IN CHAR16 *Src\r
1044 )\r
1045{\r
1046 if (*Dest != NULL) {\r
1047 FreePool (*Dest);\r
1048 }\r
1049 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
1050 ASSERT (*Dest != NULL);\r
1051}\r
1052\r
1053\r
1054/**\r
1055 Allocate new memory and concatinate Source on the end of Destination.\r
1056\r
1057 @param Dest String to added to the end of.\r
1058 @param Src String to concatinate.\r
1059\r
1060**/\r
1061VOID\r
1062NewStringCat (\r
1063 IN OUT CHAR16 **Dest,\r
1064 IN CHAR16 *Src\r
1065 )\r
1066{\r
1067 CHAR16 *NewString;\r
1068 UINTN TmpSize;\r
1069\r
1070 if (*Dest == NULL) {\r
1071 NewStringCpy (Dest, Src);\r
1072 return;\r
1073 }\r
1074\r
1075 TmpSize = StrSize (*Dest);\r
1076 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
1077 ASSERT (NewString != NULL);\r
1078\r
1079 StrCpy (NewString, *Dest);\r
1080 StrCat (NewString, Src);\r
1081\r
1082 FreePool (*Dest);\r
1083 *Dest = NewString;\r
1084}\r
1085\r
1086/**\r
1087 Get Value for given Name from a NameValue Storage.\r
1088\r
1089 @param Storage The NameValue Storage.\r
1090 @param Name The Name.\r
1091 @param Value The retured Value.\r
1092 @param GetValueFrom Where to get source value, from EditValue or Value.\r
1093\r
1094 @retval EFI_SUCCESS Value found for given Name.\r
1095 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
1096\r
1097**/\r
1098EFI_STATUS\r
1099GetValueByName (\r
1100 IN BROWSER_STORAGE *Storage,\r
1101 IN CHAR16 *Name,\r
1102 IN OUT CHAR16 **Value,\r
1103 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
1104 )\r
1105{\r
1106 LIST_ENTRY *Link;\r
1107 NAME_VALUE_NODE *Node;\r
1108\r
1109 if (GetValueFrom != GetSetValueWithEditBuffer && GetValueFrom != GetSetValueWithBuffer) {\r
1110 return EFI_INVALID_PARAMETER;\r
1111 }\r
1112\r
1113 *Value = NULL;\r
1114\r
1115 Link = GetFirstNode (&Storage->NameValueListHead);\r
1116 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1117 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1118\r
1119 if (StrCmp (Name, Node->Name) == 0) {\r
1120 if (GetValueFrom == GetSetValueWithEditBuffer) {\r
1121 NewStringCpy (Value, Node->EditValue);\r
1122 } else {\r
1123 NewStringCpy (Value, Node->Value);\r
1124 }\r
1125 return EFI_SUCCESS;\r
1126 }\r
1127\r
1128 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1129 }\r
1130\r
1131 return EFI_NOT_FOUND;\r
1132}\r
1133\r
1134\r
1135/**\r
1136 Set Value of given Name in a NameValue Storage.\r
1137\r
1138 @param Storage The NameValue Storage.\r
1139 @param Name The Name.\r
1140 @param Value The Value to set.\r
1141 @param SetValueTo Whether update editValue or Value.\r
1142 @param ReturnNode The node use the input name.\r
1143\r
1144 @retval EFI_SUCCESS Value found for given Name.\r
1145 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
1146\r
1147**/\r
1148EFI_STATUS\r
1149SetValueByName (\r
1150 IN BROWSER_STORAGE *Storage,\r
1151 IN CHAR16 *Name,\r
1152 IN CHAR16 *Value,\r
1153 IN GET_SET_QUESTION_VALUE_WITH SetValueTo,\r
1154 OUT NAME_VALUE_NODE **ReturnNode\r
1155 )\r
1156{\r
1157 LIST_ENTRY *Link;\r
1158 NAME_VALUE_NODE *Node;\r
1159 CHAR16 *Buffer;\r
1160\r
1161 if (SetValueTo != GetSetValueWithEditBuffer && SetValueTo != GetSetValueWithBuffer) {\r
1162 return EFI_INVALID_PARAMETER;\r
1163 }\r
1164\r
1165 Link = GetFirstNode (&Storage->NameValueListHead);\r
1166 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1167 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1168\r
1169 if (StrCmp (Name, Node->Name) == 0) {\r
1170 if (SetValueTo == GetSetValueWithEditBuffer) {\r
1171 Buffer = Node->EditValue;\r
1172 } else {\r
1173 Buffer = Node->Value;\r
1174 }\r
1175 if (Buffer != NULL) {\r
1176 FreePool (Buffer);\r
1177 }\r
1178 Buffer = AllocateCopyPool (StrSize (Value), Value);\r
1179 ASSERT (Buffer != NULL);\r
1180 if (SetValueTo == GetSetValueWithEditBuffer) {\r
1181 Node->EditValue = Buffer;\r
1182 } else {\r
1183 Node->Value = Buffer;\r
1184 }\r
1185\r
1186 if (ReturnNode != NULL) {\r
1187 *ReturnNode = Node;\r
1188 }\r
1189\r
1190 return EFI_SUCCESS;\r
1191 }\r
1192\r
1193 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1194 }\r
1195\r
1196 return EFI_NOT_FOUND;\r
1197}\r
1198\r
1199\r
1200/**\r
1201 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
1202\r
1203 @param Storage The Storage to be conveted.\r
1204 @param ConfigResp The returned <ConfigResp>.\r
1205 @param ConfigRequest The ConfigRequest string.\r
1206 @param GetEditBuf Get the data from editbuffer or buffer.\r
1207\r
1208 @retval EFI_SUCCESS Convert success.\r
1209 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
1210\r
1211**/\r
1212EFI_STATUS\r
1213StorageToConfigResp (\r
1214 IN BROWSER_STORAGE *Storage,\r
1215 IN CHAR16 **ConfigResp,\r
1216 IN CHAR16 *ConfigRequest,\r
1217 IN BOOLEAN GetEditBuf\r
1218 )\r
1219{\r
1220 EFI_STATUS Status;\r
1221 EFI_STRING Progress;\r
1222 LIST_ENTRY *Link;\r
1223 NAME_VALUE_NODE *Node;\r
1224 UINT8 *SourceBuf;\r
1225 FORMSET_STORAGE *FormsetStorage;\r
1226\r
1227 Status = EFI_SUCCESS;\r
1228\r
1229 switch (Storage->Type) {\r
1230 case EFI_HII_VARSTORE_BUFFER:\r
1231 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
1232 SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer;\r
1233 Status = mHiiConfigRouting->BlockToConfig (\r
1234 mHiiConfigRouting,\r
1235 ConfigRequest,\r
1236 SourceBuf,\r
1237 Storage->Size,\r
1238 ConfigResp,\r
1239 &Progress\r
1240 );\r
1241 break;\r
1242\r
1243 case EFI_HII_VARSTORE_NAME_VALUE:\r
1244 *ConfigResp = NULL;\r
1245 FormsetStorage = GetFstStgFromBrsStg(Storage);\r
1246 ASSERT (FormsetStorage != NULL);\r
1247 NewStringCat (ConfigResp, FormsetStorage->ConfigHdr);\r
1248\r
1249 Link = GetFirstNode (&Storage->NameValueListHead);\r
1250 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1251 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1252\r
1253 if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
1254 NewStringCat (ConfigResp, L"&");\r
1255 NewStringCat (ConfigResp, Node->Name);\r
1256 NewStringCat (ConfigResp, L"=");\r
1257 if (GetEditBuf) {\r
1258 NewStringCat (ConfigResp, Node->EditValue);\r
1259 } else {\r
1260 NewStringCat (ConfigResp, Node->Value);\r
1261 }\r
1262 }\r
1263 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1264 }\r
1265 break;\r
1266\r
1267 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1268 default:\r
1269 Status = EFI_INVALID_PARAMETER;\r
1270 break;\r
1271 }\r
1272\r
1273 return Status;\r
1274}\r
1275\r
1276\r
1277/**\r
1278 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
1279\r
1280 @param Storage The Storage to receive the settings.\r
1281 @param ConfigResp The <ConfigResp> to be converted.\r
1282\r
1283 @retval EFI_SUCCESS Convert success.\r
1284 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
1285\r
1286**/\r
1287EFI_STATUS\r
1288ConfigRespToStorage (\r
1289 IN BROWSER_STORAGE *Storage,\r
1290 IN CHAR16 *ConfigResp\r
1291 )\r
1292{\r
1293 EFI_STATUS Status;\r
1294 EFI_STRING Progress;\r
1295 UINTN BufferSize;\r
1296 CHAR16 *StrPtr;\r
1297 CHAR16 *Name;\r
1298 CHAR16 *Value;\r
1299\r
1300 Status = EFI_SUCCESS;\r
1301\r
1302 switch (Storage->Type) {\r
1303 case EFI_HII_VARSTORE_BUFFER:\r
1304 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
1305 BufferSize = Storage->Size;\r
1306 Status = mHiiConfigRouting->ConfigToBlock (\r
1307 mHiiConfigRouting,\r
1308 ConfigResp,\r
1309 Storage->EditBuffer,\r
1310 &BufferSize,\r
1311 &Progress\r
1312 );\r
1313 break;\r
1314\r
1315 case EFI_HII_VARSTORE_NAME_VALUE:\r
1316 StrPtr = StrStr (ConfigResp, L"PATH");\r
1317 if (StrPtr == NULL) {\r
1318 break;\r
1319 }\r
1320 StrPtr = StrStr (ConfigResp, L"&");\r
1321 while (StrPtr != NULL) {\r
1322 //\r
1323 // Skip '&'\r
1324 //\r
1325 StrPtr = StrPtr + 1;\r
1326 Name = StrPtr;\r
1327 StrPtr = StrStr (StrPtr, L"=");\r
1328 if (StrPtr == NULL) {\r
1329 break;\r
1330 }\r
1331 *StrPtr = 0;\r
1332\r
1333 //\r
1334 // Skip '='\r
1335 //\r
1336 StrPtr = StrPtr + 1;\r
1337 Value = StrPtr;\r
1338 StrPtr = StrStr (StrPtr, L"&");\r
1339 if (StrPtr != NULL) {\r
1340 *StrPtr = 0;\r
1341 }\r
1342 SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);\r
1343 }\r
1344 break;\r
1345\r
1346 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1347 default:\r
1348 Status = EFI_INVALID_PARAMETER;\r
1349 break;\r
1350 }\r
1351\r
1352 return Status;\r
1353}\r
1354\r
1355/**\r
1356 Convert the buffer value to HiiValue.\r
1357\r
1358 @param Question The question.\r
1359 @param Value Unicode buffer save the question value.\r
1360\r
1361 @retval Status whether convert the value success.\r
1362\r
1363**/\r
1364EFI_STATUS\r
1365BufferToValue (\r
1366 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1367 IN CHAR16 *Value\r
1368 )\r
1369{\r
1370 CHAR16 *StringPtr;\r
1371 BOOLEAN IsBufferStorage;\r
1372 CHAR16 *DstBuf;\r
1373 CHAR16 TempChar;\r
1374 UINTN LengthStr;\r
1375 UINT8 *Dst;\r
1376 CHAR16 TemStr[5];\r
1377 UINTN Index;\r
1378 UINT8 DigitUint8;\r
1379 BOOLEAN IsString;\r
1380 UINTN Length;\r
1381 EFI_STATUS Status;\r
1382\r
1383 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1384 if (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1385 Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1386 IsBufferStorage = TRUE;\r
1387 } else {\r
1388 IsBufferStorage = FALSE;\r
1389 }\r
1390\r
1391 //\r
1392 // Question Value is provided by Buffer Storage or NameValue Storage\r
1393 //\r
1394 if (Question->BufferValue != NULL) {\r
1395 //\r
1396 // This Question is password or orderedlist\r
1397 //\r
1398 Dst = Question->BufferValue;\r
1399 } else {\r
1400 //\r
1401 // Other type of Questions\r
1402 //\r
1403 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1404 }\r
1405\r
1406 //\r
1407 // Temp cut at the end of this section, end with '\0' or '&'.\r
1408 //\r
1409 StringPtr = Value;\r
1410 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1411 StringPtr++;\r
1412 }\r
1413 TempChar = *StringPtr;\r
1414 *StringPtr = L'\0';\r
1415\r
1416 LengthStr = StrLen (Value);\r
1417 Status = EFI_SUCCESS;\r
1418 if (!IsBufferStorage && IsString) {\r
1419 //\r
1420 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1421 // Add string tail char L'\0' into Length\r
1422 //\r
1423 Length = Question->StorageWidth + sizeof (CHAR16);\r
1424 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1425 Status = EFI_BUFFER_TOO_SMALL;\r
1426 } else {\r
1427 DstBuf = (CHAR16 *) Dst;\r
1428 ZeroMem (TemStr, sizeof (TemStr));\r
1429 for (Index = 0; Index < LengthStr; Index += 4) {\r
1430 StrnCpy (TemStr, Value + Index, 4);\r
1431 DstBuf[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1432 }\r
1433 //\r
1434 // Add tailing L'\0' character\r
1435 //\r
1436 DstBuf[Index/4] = L'\0';\r
1437 }\r
1438 } else {\r
1439 if (Question->StorageWidth < ((LengthStr + 1) / 2)) {\r
1440 Status = EFI_BUFFER_TOO_SMALL;\r
1441 } else {\r
1442 ZeroMem (TemStr, sizeof (TemStr));\r
1443 for (Index = 0; Index < LengthStr; Index ++) {\r
1444 TemStr[0] = Value[LengthStr - Index - 1];\r
1445 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1446 if ((Index & 1) == 0) {\r
1447 Dst [Index/2] = DigitUint8;\r
1448 } else {\r
1449 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
1450 }\r
1451 }\r
1452 }\r
1453 }\r
1454\r
1455 *StringPtr = TempChar;\r
1456\r
1457 return Status;\r
1458}\r
1459\r
1460/**\r
1461 Get Question's current Value.\r
1462\r
1463 @param FormSet FormSet data structure.\r
1464 @param Form Form data structure.\r
1465 @param Question Question to be initialized.\r
1466 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
1467\r
1468 @retval EFI_SUCCESS The function completed successfully.\r
1469\r
1470**/\r
1471EFI_STATUS\r
1472GetQuestionValue (\r
1473 IN FORM_BROWSER_FORMSET *FormSet,\r
1474 IN FORM_BROWSER_FORM *Form,\r
1475 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1476 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
1477 )\r
1478{\r
1479 EFI_STATUS Status;\r
1480 BOOLEAN Enabled;\r
1481 BOOLEAN Pending;\r
1482 UINT8 *Dst;\r
1483 UINTN StorageWidth;\r
1484 EFI_TIME EfiTime;\r
1485 BROWSER_STORAGE *Storage;\r
1486 FORMSET_STORAGE *FormsetStorage;\r
1487 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1488 CHAR16 *ConfigRequest;\r
1489 CHAR16 *Progress;\r
1490 CHAR16 *Result;\r
1491 CHAR16 *Value;\r
1492 UINTN Length;\r
1493 BOOLEAN IsBufferStorage;\r
1494\r
1495 Status = EFI_SUCCESS;\r
1496 Value = NULL;\r
1497 Result = NULL;\r
1498\r
1499 if (GetValueFrom >= GetSetValueWithMax) {\r
1500 return EFI_INVALID_PARAMETER;\r
1501 }\r
1502\r
1503 //\r
1504 // Question value is provided by an Expression, evaluate it\r
1505 //\r
1506 if (Question->ValueExpression != NULL) {\r
1507 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1508 if (!EFI_ERROR (Status)) {\r
1509 if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1510 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1511 if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
1512 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
1513 Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;\r
1514 } else {\r
1515 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
1516 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1517 }\r
1518 FreePool (Question->ValueExpression->Result.Buffer);\r
1519 }\r
1520 Question->HiiValue.Type = Question->ValueExpression->Result.Type;\r
1521 CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
1522 }\r
1523 return Status;\r
1524 }\r
1525 \r
1526 //\r
1527 // Get question value by read expression.\r
1528 //\r
1529 if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1530 Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
1531 if (!EFI_ERROR (Status) && \r
1532 ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER))) {\r
1533 //\r
1534 // Only update question value to the valid result.\r
1535 //\r
1536 if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1537 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1538 if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
1539 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
1540 Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;\r
1541 } else {\r
1542 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
1543 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1544 }\r
1545 FreePool (Question->ReadExpression->Result.Buffer);\r
1546 }\r
1547 Question->HiiValue.Type = Question->ReadExpression->Result.Type;\r
1548 CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
1549 return EFI_SUCCESS;\r
1550 }\r
1551 }\r
1552\r
1553 //\r
1554 // Question value is provided by RTC\r
1555 //\r
1556 Storage = Question->Storage;\r
1557 QuestionValue = &Question->HiiValue.Value;\r
1558 if (Storage == NULL) {\r
1559 //\r
1560 // It's a Question without storage, or RTC date/time\r
1561 //\r
1562 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1563 //\r
1564 // Date and time define the same Flags bit\r
1565 //\r
1566 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1567 case QF_DATE_STORAGE_TIME:\r
1568 Status = gRT->GetTime (&EfiTime, NULL);\r
1569 break;\r
1570\r
1571 case QF_DATE_STORAGE_WAKEUP:\r
1572 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1573 break;\r
1574\r
1575 case QF_DATE_STORAGE_NORMAL:\r
1576 default:\r
1577 //\r
1578 // For date/time without storage\r
1579 //\r
1580 return EFI_SUCCESS;\r
1581 }\r
1582\r
1583 if (EFI_ERROR (Status)) {\r
1584 return Status;\r
1585 }\r
1586\r
1587 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1588 QuestionValue->date.Year = EfiTime.Year;\r
1589 QuestionValue->date.Month = EfiTime.Month;\r
1590 QuestionValue->date.Day = EfiTime.Day;\r
1591 } else {\r
1592 QuestionValue->time.Hour = EfiTime.Hour;\r
1593 QuestionValue->time.Minute = EfiTime.Minute;\r
1594 QuestionValue->time.Second = EfiTime.Second;\r
1595 }\r
1596 }\r
1597\r
1598 return EFI_SUCCESS;\r
1599 }\r
1600\r
1601 //\r
1602 // Question value is provided by EFI variable\r
1603 //\r
1604 StorageWidth = Question->StorageWidth;\r
1605 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1606 if (Question->BufferValue != NULL) {\r
1607 Dst = Question->BufferValue;\r
1608 } else {\r
1609 Dst = (UINT8 *) QuestionValue;\r
1610 }\r
1611\r
1612 Status = gRT->GetVariable (\r
1613 Question->VariableName,\r
1614 &Storage->Guid,\r
1615 NULL,\r
1616 &StorageWidth,\r
1617 Dst\r
1618 );\r
1619 //\r
1620 // Always return success, even this EFI variable doesn't exist\r
1621 //\r
1622 return EFI_SUCCESS;\r
1623 }\r
1624\r
1625 //\r
1626 // Question Value is provided by Buffer Storage or NameValue Storage\r
1627 //\r
1628 if (Question->BufferValue != NULL) {\r
1629 //\r
1630 // This Question is password or orderedlist\r
1631 //\r
1632 Dst = Question->BufferValue;\r
1633 } else {\r
1634 //\r
1635 // Other type of Questions\r
1636 //\r
1637 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1638 }\r
1639\r
1640 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1641 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1642 IsBufferStorage = TRUE;\r
1643 } else {\r
1644 IsBufferStorage = FALSE;\r
1645 }\r
1646 if (GetValueFrom == GetSetValueWithEditBuffer || GetValueFrom == GetSetValueWithBuffer ) {\r
1647 if (IsBufferStorage) {\r
1648 if (GetValueFrom == GetSetValueWithEditBuffer) {\r
1649 //\r
1650 // Copy from storage Edit buffer\r
1651 //\r
1652 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1653 } else {\r
1654 //\r
1655 // Copy from storage Edit buffer\r
1656 //\r
1657 CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1658 }\r
1659 } else {\r
1660 Value = NULL;\r
1661 Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);\r
1662 if (EFI_ERROR (Status)) {\r
1663 return Status;\r
1664 }\r
1665\r
1666 ASSERT (Value != NULL);\r
1667 Status = BufferToValue (Question, Value);\r
1668 FreePool (Value);\r
1669 }\r
1670 } else {\r
1671 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
1672 ASSERT (FormsetStorage != NULL);\r
1673 //\r
1674 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1675 // <ConfigHdr> + "&" + <VariableName>\r
1676 //\r
1677 if (IsBufferStorage) {\r
1678 Length = StrLen (FormsetStorage->ConfigHdr);\r
1679 Length += StrLen (Question->BlockName);\r
1680 } else {\r
1681 Length = StrLen (FormsetStorage->ConfigHdr);\r
1682 Length += StrLen (Question->VariableName) + 1;\r
1683 }\r
1684 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1685 ASSERT (ConfigRequest != NULL);\r
1686\r
1687 StrCpy (ConfigRequest, FormsetStorage->ConfigHdr);\r
1688 if (IsBufferStorage) {\r
1689 StrCat (ConfigRequest, Question->BlockName);\r
1690 } else {\r
1691 StrCat (ConfigRequest, L"&");\r
1692 StrCat (ConfigRequest, Question->VariableName);\r
1693 }\r
1694\r
1695 //\r
1696 // Request current settings from Configuration Driver\r
1697 //\r
1698 Status = mHiiConfigRouting->ExtractConfig (\r
1699 mHiiConfigRouting,\r
1700 ConfigRequest,\r
1701 &Progress,\r
1702 &Result\r
1703 );\r
1704 FreePool (ConfigRequest);\r
1705 if (EFI_ERROR (Status)) {\r
1706 return Status;\r
1707 }\r
1708\r
1709 //\r
1710 // Skip <ConfigRequest>\r
1711 //\r
1712 if (IsBufferStorage) {\r
1713 Value = StrStr (Result, L"&VALUE");\r
1714 if (Value == NULL) {\r
1715 FreePool (Result);\r
1716 return EFI_NOT_FOUND;\r
1717 }\r
1718 //\r
1719 // Skip "&VALUE"\r
1720 //\r
1721 Value = Value + 6;\r
1722 } else {\r
1723 Value = Result + Length;\r
1724 }\r
1725 if (*Value != '=') {\r
1726 FreePool (Result);\r
1727 return EFI_NOT_FOUND;\r
1728 }\r
1729 //\r
1730 // Skip '=', point to value\r
1731 //\r
1732 Value = Value + 1;\r
1733\r
1734 Status = BufferToValue (Question, Value);\r
1735 if (EFI_ERROR (Status)) {\r
1736 FreePool (Result);\r
1737 return Status;\r
1738 }\r
1739\r
1740 //\r
1741 // Synchronize Edit Buffer\r
1742 //\r
1743 if (IsBufferStorage) {\r
1744 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1745 } else {\r
1746 SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);\r
1747 }\r
1748\r
1749 if (Result != NULL) {\r
1750 FreePool (Result);\r
1751 }\r
1752 }\r
1753\r
1754 return Status;\r
1755}\r
1756\r
1757\r
1758/**\r
1759 Save Question Value to edit copy(cached) or Storage(uncached).\r
1760\r
1761 @param FormSet FormSet data structure.\r
1762 @param Form Form data structure.\r
1763 @param Question Pointer to the Question.\r
1764 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.\r
1765\r
1766 @retval EFI_SUCCESS The function completed successfully.\r
1767\r
1768**/\r
1769EFI_STATUS\r
1770SetQuestionValue (\r
1771 IN FORM_BROWSER_FORMSET *FormSet,\r
1772 IN FORM_BROWSER_FORM *Form,\r
1773 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1774 IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
1775 )\r
1776{\r
1777 EFI_STATUS Status;\r
1778 BOOLEAN Enabled;\r
1779 BOOLEAN Pending;\r
1780 UINT8 *Src;\r
1781 EFI_TIME EfiTime;\r
1782 UINTN BufferLen;\r
1783 UINTN StorageWidth;\r
1784 BROWSER_STORAGE *Storage;\r
1785 FORMSET_STORAGE *FormsetStorage;\r
1786 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1787 CHAR16 *ConfigResp;\r
1788 CHAR16 *Progress;\r
1789 CHAR16 *Value;\r
1790 UINTN Length;\r
1791 BOOLEAN IsBufferStorage;\r
1792 BOOLEAN IsString;\r
1793 UINT8 *TemBuffer;\r
1794 CHAR16 *TemName;\r
1795 CHAR16 *TemString;\r
1796 UINTN Index;\r
1797 NAME_VALUE_NODE *Node;\r
1798\r
1799 Status = EFI_SUCCESS;\r
1800 Node = NULL;\r
1801\r
1802 if (SetValueTo >= GetSetValueWithMax) {\r
1803 return EFI_INVALID_PARAMETER;\r
1804 }\r
1805\r
1806 //\r
1807 // If Question value is provided by an Expression, then it is read only\r
1808 //\r
1809 if (Question->ValueExpression != NULL) {\r
1810 return Status;\r
1811 }\r
1812 \r
1813 //\r
1814 // Before set question value, evaluate its write expression.\r
1815 //\r
1816 if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1817 Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
1818 if (EFI_ERROR (Status)) {\r
1819 return Status;\r
1820 }\r
1821 }\r
1822\r
1823 //\r
1824 // Question value is provided by RTC\r
1825 //\r
1826 Storage = Question->Storage;\r
1827 QuestionValue = &Question->HiiValue.Value;\r
1828 if (Storage == NULL) {\r
1829 //\r
1830 // It's a Question without storage, or RTC date/time\r
1831 //\r
1832 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1833 //\r
1834 // Date and time define the same Flags bit\r
1835 //\r
1836 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1837 case QF_DATE_STORAGE_TIME:\r
1838 Status = gRT->GetTime (&EfiTime, NULL);\r
1839 break;\r
1840\r
1841 case QF_DATE_STORAGE_WAKEUP:\r
1842 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1843 break;\r
1844\r
1845 case QF_DATE_STORAGE_NORMAL:\r
1846 default:\r
1847 //\r
1848 // For date/time without storage\r
1849 //\r
1850 return EFI_SUCCESS;\r
1851 }\r
1852\r
1853 if (EFI_ERROR (Status)) {\r
1854 return Status;\r
1855 }\r
1856\r
1857 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1858 EfiTime.Year = QuestionValue->date.Year;\r
1859 EfiTime.Month = QuestionValue->date.Month;\r
1860 EfiTime.Day = QuestionValue->date.Day;\r
1861 } else {\r
1862 EfiTime.Hour = QuestionValue->time.Hour;\r
1863 EfiTime.Minute = QuestionValue->time.Minute;\r
1864 EfiTime.Second = QuestionValue->time.Second;\r
1865 }\r
1866\r
1867 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1868 Status = gRT->SetTime (&EfiTime);\r
1869 } else {\r
1870 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1871 }\r
1872 }\r
1873\r
1874 return Status;\r
1875 }\r
1876\r
1877 //\r
1878 // Question value is provided by EFI variable\r
1879 //\r
1880 StorageWidth = Question->StorageWidth;\r
1881 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1882 if (Question->BufferValue != NULL) {\r
1883 Src = Question->BufferValue;\r
1884 } else {\r
1885 Src = (UINT8 *) QuestionValue;\r
1886 }\r
1887\r
1888 Status = gRT->SetVariable (\r
1889 Question->VariableName,\r
1890 &Storage->Guid,\r
1891 Storage->Attributes,\r
1892 StorageWidth,\r
1893 Src\r
1894 );\r
1895 return Status;\r
1896 }\r
1897\r
1898 //\r
1899 // Question Value is provided by Buffer Storage or NameValue Storage\r
1900 //\r
1901 if (Question->BufferValue != NULL) {\r
1902 Src = Question->BufferValue;\r
1903 } else {\r
1904 Src = (UINT8 *) &Question->HiiValue.Value;\r
1905 }\r
1906\r
1907 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1908 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1909 IsBufferStorage = TRUE;\r
1910 } else {\r
1911 IsBufferStorage = FALSE;\r
1912 }\r
1913 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1914\r
1915 if (SetValueTo == GetSetValueWithEditBuffer || SetValueTo == GetSetValueWithBuffer) {\r
1916 if (IsBufferStorage) {\r
1917 if (SetValueTo == GetSetValueWithEditBuffer) {\r
1918 //\r
1919 // Copy to storage edit buffer\r
1920 // \r
1921 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1922 } else if (SetValueTo == GetSetValueWithBuffer) {\r
1923 //\r
1924 // Copy to storage edit buffer\r
1925 // \r
1926 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1927 }\r
1928 } else {\r
1929 if (IsString) {\r
1930 //\r
1931 // Allocate enough string buffer.\r
1932 //\r
1933 Value = NULL;\r
1934 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1935 Value = AllocateZeroPool (BufferLen);\r
1936 ASSERT (Value != NULL);\r
1937 //\r
1938 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1939 //\r
1940 TemName = (CHAR16 *) Src;\r
1941 TemString = Value;\r
1942 for (; *TemName != L'\0'; TemName++) {\r
1943 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1944 }\r
1945 } else {\r
1946 BufferLen = StorageWidth * 2 + 1;\r
1947 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1948 ASSERT (Value != NULL);\r
1949 //\r
1950 // Convert Buffer to Hex String\r
1951 //\r
1952 TemBuffer = Src + StorageWidth - 1;\r
1953 TemString = Value;\r
1954 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1955 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1956 }\r
1957 }\r
1958\r
1959 Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
1960 FreePool (Value);\r
1961 if (EFI_ERROR (Status)) {\r
1962 return Status;\r
1963 }\r
1964 }\r
1965 } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
1966 //\r
1967 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1968 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1969 //\r
1970 if (IsBufferStorage) {\r
1971 Length = StrLen (Question->BlockName) + 7;\r
1972 } else {\r
1973 Length = StrLen (Question->VariableName) + 2;\r
1974 }\r
1975 if (!IsBufferStorage && IsString) {\r
1976 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1977 } else {\r
1978 Length += (StorageWidth * 2);\r
1979 }\r
1980 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
1981 ASSERT (FormsetStorage != NULL);\r
1982 ConfigResp = AllocateZeroPool ((StrLen (FormsetStorage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1983 ASSERT (ConfigResp != NULL);\r
1984\r
1985 StrCpy (ConfigResp, FormsetStorage->ConfigHdr);\r
1986 if (IsBufferStorage) {\r
1987 StrCat (ConfigResp, Question->BlockName);\r
1988 StrCat (ConfigResp, L"&VALUE=");\r
1989 } else {\r
1990 StrCat (ConfigResp, L"&");\r
1991 StrCat (ConfigResp, Question->VariableName);\r
1992 StrCat (ConfigResp, L"=");\r
1993 }\r
1994\r
1995 Value = ConfigResp + StrLen (ConfigResp);\r
1996\r
1997 if (!IsBufferStorage && IsString) {\r
1998 //\r
1999 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
2000 //\r
2001 TemName = (CHAR16 *) Src;\r
2002 TemString = Value;\r
2003 for (; *TemName != L'\0'; TemName++) {\r
2004 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
2005 }\r
2006 } else {\r
2007 //\r
2008 // Convert Buffer to Hex String\r
2009 //\r
2010 TemBuffer = Src + StorageWidth - 1;\r
2011 TemString = Value;\r
2012 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
2013 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
2014 }\r
2015 }\r
2016\r
2017 //\r
2018 // Convert to lower char.\r
2019 //\r
2020 for (TemString = Value; *Value != L'\0'; Value++) {\r
2021 if (*Value >= L'A' && *Value <= L'Z') {\r
2022 *Value = (CHAR16) (*Value - L'A' + L'a');\r
2023 }\r
2024 }\r
2025\r
2026 //\r
2027 // Submit Question Value to Configuration Driver\r
2028 //\r
2029 Status = mHiiConfigRouting->RouteConfig (\r
2030 mHiiConfigRouting,\r
2031 ConfigResp,\r
2032 &Progress\r
2033 );\r
2034 if (EFI_ERROR (Status)) {\r
2035 FreePool (ConfigResp);\r
2036 return Status;\r
2037 }\r
2038 FreePool (ConfigResp);\r
2039 \r
2040 //\r
2041 // Sync storage, from editbuffer to buffer.\r
2042 //\r
2043 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
2044 }\r
2045\r
2046 return Status;\r
2047}\r
2048\r
2049\r
2050/**\r
2051 Perform nosubmitif check for a Form.\r
2052\r
2053 @param FormSet FormSet data structure.\r
2054 @param Form Form data structure.\r
2055 @param Question The Question to be validated.\r
2056 @param Type Validation type: NoSubmit\r
2057\r
2058 @retval EFI_SUCCESS Form validation pass.\r
2059 @retval other Form validation failed.\r
2060\r
2061**/\r
2062EFI_STATUS\r
2063ValidateQuestion (\r
2064 IN FORM_BROWSER_FORMSET *FormSet,\r
2065 IN FORM_BROWSER_FORM *Form,\r
2066 IN FORM_BROWSER_STATEMENT *Question,\r
2067 IN UINTN Type\r
2068 )\r
2069{\r
2070 EFI_STATUS Status;\r
2071 LIST_ENTRY *Link;\r
2072 LIST_ENTRY *ListHead;\r
2073 FORM_EXPRESSION *Expression;\r
2074 UINT32 BrowserStatus;\r
2075 CHAR16 *ErrorStr;\r
2076\r
2077 BrowserStatus = BROWSER_SUCCESS;\r
2078 ErrorStr = NULL;\r
2079\r
2080 switch (Type) {\r
2081 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2082 ListHead = &Question->InconsistentListHead;\r
2083 break;\r
2084\r
2085 case EFI_HII_EXPRESSION_WARNING_IF:\r
2086 ListHead = &Question->WarningListHead;\r
2087 break;\r
2088\r
2089 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
2090 ListHead = &Question->NoSubmitListHead;\r
2091 break;\r
2092\r
2093 default:\r
2094 ASSERT (FALSE);\r
2095 return EFI_UNSUPPORTED;\r
2096 }\r
2097\r
2098 Link = GetFirstNode (ListHead);\r
2099 while (!IsNull (ListHead, Link)) {\r
2100 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
2101\r
2102 //\r
2103 // Evaluate the expression\r
2104 //\r
2105 Status = EvaluateExpression (FormSet, Form, Expression);\r
2106 if (EFI_ERROR (Status)) {\r
2107 return Status;\r
2108 }\r
2109\r
2110 if (IsTrue (&Expression->Result)) {\r
2111 switch (Type) {\r
2112 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2113 BrowserStatus = BROWSER_INCONSISTENT_IF;\r
2114 break;\r
2115\r
2116 case EFI_HII_EXPRESSION_WARNING_IF:\r
2117 BrowserStatus = BROWSER_WARNING_IF;\r
2118 break;\r
2119\r
2120 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
2121 BrowserStatus = BROWSER_NO_SUBMIT_IF;\r
2122 //\r
2123 // This code only used to compatible with old display engine,\r
2124 // New display engine will not use this field.\r
2125 //\r
2126 if (Expression->Error != 0) {\r
2127 ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle);\r
2128 }\r
2129 break;\r
2130\r
2131 default:\r
2132 ASSERT (FALSE);\r
2133 break;\r
2134 }\r
2135\r
2136 if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {\r
2137 //\r
2138 // If in system submit process and for no_submit_if check, not popup this error message.\r
2139 // Will process this fail again later in not system submit process.\r
2140 //\r
2141 PopupErrorMessage(BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);\r
2142 }\r
2143\r
2144 if (ErrorStr != NULL) {\r
2145 FreePool (ErrorStr);\r
2146 }\r
2147\r
2148 if (Type == EFI_HII_EXPRESSION_WARNING_IF) {\r
2149 return EFI_SUCCESS;\r
2150 } else {\r
2151 return EFI_NOT_READY;\r
2152 }\r
2153 }\r
2154\r
2155 Link = GetNextNode (ListHead, Link);\r
2156 }\r
2157\r
2158 return EFI_SUCCESS;\r
2159}\r
2160\r
2161/**\r
2162 Perform question check. \r
2163 \r
2164 If one question has more than one check, process form high priority to low. \r
2165 Only one error info will be popup.\r
2166\r
2167 @param FormSet FormSet data structure.\r
2168 @param Form Form data structure.\r
2169 @param Question The Question to be validated.\r
2170\r
2171 @retval EFI_SUCCESS Form validation pass.\r
2172 @retval other Form validation failed.\r
2173\r
2174**/\r
2175EFI_STATUS\r
2176ValueChangedValidation (\r
2177 IN FORM_BROWSER_FORMSET *FormSet,\r
2178 IN FORM_BROWSER_FORM *Form,\r
2179 IN FORM_BROWSER_STATEMENT *Question\r
2180 )\r
2181{\r
2182 EFI_STATUS Status;\r
2183\r
2184 Status = EFI_SUCCESS;\r
2185\r
2186 //\r
2187 // Do the inconsistentif check.\r
2188 //\r
2189 if (!IsListEmpty (&Question->InconsistentListHead)) {\r
2190 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
2191 if (EFI_ERROR (Status)) {\r
2192 return Status;\r
2193 }\r
2194 }\r
2195\r
2196 //\r
2197 // Do the warningif check.\r
2198 //\r
2199 if (!IsListEmpty (&Question->WarningListHead)) {\r
2200 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF);\r
2201 }\r
2202\r
2203 return Status;\r
2204}\r
2205\r
2206/**\r
2207 Perform NoSubmit check for each Form in FormSet.\r
2208\r
2209 @param FormSet FormSet data structure.\r
2210 @param CurrentForm Current input form data structure.\r
2211 @param Statement The statement for this check.\r
2212\r
2213 @retval EFI_SUCCESS Form validation pass.\r
2214 @retval other Form validation failed.\r
2215\r
2216**/\r
2217EFI_STATUS\r
2218NoSubmitCheck (\r
2219 IN FORM_BROWSER_FORMSET *FormSet,\r
2220 IN OUT FORM_BROWSER_FORM **CurrentForm,\r
2221 OUT FORM_BROWSER_STATEMENT **Statement\r
2222 )\r
2223{\r
2224 EFI_STATUS Status;\r
2225 LIST_ENTRY *Link;\r
2226 FORM_BROWSER_STATEMENT *Question;\r
2227 FORM_BROWSER_FORM *Form;\r
2228 LIST_ENTRY *LinkForm;\r
2229\r
2230 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
2231 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
2232 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
2233 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
2234\r
2235 if (*CurrentForm != NULL && *CurrentForm != Form) {\r
2236 continue;\r
2237 }\r
2238\r
2239 Link = GetFirstNode (&Form->StatementListHead);\r
2240 while (!IsNull (&Form->StatementListHead, Link)) {\r
2241 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2242 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
2243 if (EFI_ERROR (Status)) {\r
2244 if (*CurrentForm == NULL) {\r
2245 *CurrentForm = Form;\r
2246 }\r
2247 if (Statement != NULL) {\r
2248 *Statement = Question;\r
2249 }\r
2250 return Status;\r
2251 }\r
2252\r
2253 Link = GetNextNode (&Form->StatementListHead, Link);\r
2254 }\r
2255 }\r
2256\r
2257 return EFI_SUCCESS;\r
2258}\r
2259\r
2260/**\r
2261 Fill storage's edit copy with settings requested from Configuration Driver.\r
2262\r
2263 @param Storage The storage which need to sync.\r
2264 @param ConfigRequest The config request string which used to sync storage.\r
2265 @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
2266 editbuffer to buffer\r
2267 if TRUE, copy the editbuffer to the buffer.\r
2268 if FALSE, copy the buffer to the editbuffer.\r
2269\r
2270 @retval EFI_SUCCESS The function completed successfully.\r
2271\r
2272**/\r
2273EFI_STATUS\r
2274SynchronizeStorage (\r
2275 OUT BROWSER_STORAGE *Storage,\r
2276 IN CHAR16 *ConfigRequest,\r
2277 IN BOOLEAN SyncOrRestore\r
2278 )\r
2279{\r
2280 EFI_STATUS Status;\r
2281 EFI_STRING Progress;\r
2282 EFI_STRING Result;\r
2283 UINTN BufferSize;\r
2284 LIST_ENTRY *Link;\r
2285 NAME_VALUE_NODE *Node;\r
2286 UINT8 *Src;\r
2287 UINT8 *Dst;\r
2288\r
2289 Status = EFI_SUCCESS;\r
2290 Result = NULL;\r
2291\r
2292 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2293 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
2294 BufferSize = Storage->Size;\r
2295\r
2296 if (SyncOrRestore) {\r
2297 Src = Storage->EditBuffer;\r
2298 Dst = Storage->Buffer;\r
2299 } else {\r
2300 Src = Storage->Buffer;\r
2301 Dst = Storage->EditBuffer;\r
2302 }\r
2303\r
2304 if (ConfigRequest != NULL) {\r
2305 Status = mHiiConfigRouting->BlockToConfig(\r
2306 mHiiConfigRouting,\r
2307 ConfigRequest,\r
2308 Src,\r
2309 BufferSize,\r
2310 &Result,\r
2311 &Progress\r
2312 );\r
2313 if (EFI_ERROR (Status)) {\r
2314 return Status;\r
2315 }\r
2316\r
2317 Status = mHiiConfigRouting->ConfigToBlock (\r
2318 mHiiConfigRouting,\r
2319 Result,\r
2320 Dst,\r
2321 &BufferSize,\r
2322 &Progress\r
2323 );\r
2324 if (Result != NULL) {\r
2325 FreePool (Result);\r
2326 }\r
2327 } else {\r
2328 CopyMem (Dst, Src, BufferSize);\r
2329 }\r
2330 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2331 Link = GetFirstNode (&Storage->NameValueListHead);\r
2332 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
2333 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2334\r
2335 if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||\r
2336 (ConfigRequest == NULL)) {\r
2337 if (SyncOrRestore) {\r
2338 NewStringCpy (&Node->Value, Node->EditValue);\r
2339 } else {\r
2340 NewStringCpy (&Node->EditValue, Node->Value);\r
2341 }\r
2342 }\r
2343\r
2344 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
2345 }\r
2346 }\r
2347\r
2348 return Status;\r
2349}\r
2350\r
2351/**\r
2352 When discard the question value, call the callback function with Changed type\r
2353 to inform the hii driver.\r
2354\r
2355 @param FormSet FormSet data structure.\r
2356 @param Form Form data structure.\r
2357\r
2358**/\r
2359VOID\r
2360SendDiscardInfoToDriver (\r
2361 IN FORM_BROWSER_FORMSET *FormSet,\r
2362 IN FORM_BROWSER_FORM *Form\r
2363 )\r
2364{\r
2365 LIST_ENTRY *Link;\r
2366 FORM_BROWSER_STATEMENT *Question;\r
2367 EFI_IFR_TYPE_VALUE *TypeValue;\r
2368 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2369\r
2370 if (FormSet->ConfigAccess == NULL) {\r
2371 return;\r
2372 }\r
2373\r
2374 Link = GetFirstNode (&Form->StatementListHead);\r
2375 while (!IsNull (&Form->StatementListHead, Link)) {\r
2376 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2377 Link = GetNextNode (&Form->StatementListHead, Link);\r
2378\r
2379 if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2380 continue;\r
2381 }\r
2382\r
2383 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2384 continue;\r
2385 }\r
2386\r
2387 if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
2388 continue;\r
2389 }\r
2390\r
2391 if (!Question->ValueChanged) {\r
2392 continue;\r
2393 }\r
2394\r
2395 //\r
2396 // Restore the question value before call the CHANGED callback type.\r
2397 //\r
2398 GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
2399\r
2400 if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
2401 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
2402 } else {\r
2403 TypeValue = &Question->HiiValue.Value;\r
2404 }\r
2405\r
2406 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2407 FormSet->ConfigAccess->Callback (\r
2408 FormSet->ConfigAccess,\r
2409 EFI_BROWSER_ACTION_CHANGED,\r
2410 Question->QuestionId,\r
2411 Question->HiiValue.Type,\r
2412 TypeValue,\r
2413 &ActionRequest\r
2414 );\r
2415 }\r
2416}\r
2417\r
2418/**\r
2419 Validate the HiiHandle.\r
2420\r
2421 @param HiiHandle The input HiiHandle which need to validate.\r
2422\r
2423 @retval TRUE The handle is validate.\r
2424 @retval FALSE The handle is invalidate.\r
2425\r
2426**/\r
2427BOOLEAN\r
2428ValidateHiiHandle (\r
2429 EFI_HII_HANDLE HiiHandle\r
2430 )\r
2431{\r
2432 EFI_HII_HANDLE *HiiHandles;\r
2433 UINTN Index;\r
2434 BOOLEAN Find;\r
2435\r
2436 if (HiiHandle == NULL) {\r
2437 return FALSE;\r
2438 }\r
2439\r
2440 Find = FALSE;\r
2441\r
2442 HiiHandles = HiiGetHiiHandles (NULL);\r
2443 ASSERT (HiiHandles != NULL);\r
2444\r
2445 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
2446 if (HiiHandles[Index] == HiiHandle) {\r
2447 Find = TRUE;\r
2448 break;\r
2449 }\r
2450 }\r
2451\r
2452 FreePool (HiiHandles);\r
2453\r
2454 return Find;\r
2455}\r
2456\r
2457/**\r
2458 Validate the FormSet. If the formset is not validate, remove it from the list.\r
2459\r
2460 @param FormSet The input FormSet which need to validate.\r
2461\r
2462 @retval TRUE The handle is validate.\r
2463 @retval FALSE The handle is invalidate.\r
2464\r
2465**/\r
2466BOOLEAN\r
2467ValidateFormSet (\r
2468 FORM_BROWSER_FORMSET *FormSet\r
2469 )\r
2470{\r
2471 BOOLEAN Find;\r
2472\r
2473 ASSERT (FormSet != NULL);\r
2474\r
2475 Find = ValidateHiiHandle(FormSet->HiiHandle);\r
2476 //\r
2477 // Should not remove the formset which is being used.\r
2478 //\r
2479 if (!Find && (FormSet != gCurrentSelection->FormSet)) {\r
2480 CleanBrowserStorage(FormSet);\r
2481 RemoveEntryList (&FormSet->Link);\r
2482 DestroyFormSet (FormSet);\r
2483 }\r
2484\r
2485 return Find;\r
2486}\r
2487/**\r
2488 Check whether need to enable the reset flag in form level.\r
2489 Also clean all ValueChanged flag in question.\r
2490\r
2491 @param SetFlag Whether need to set the Reset Flag.\r
2492 @param FormSet FormSet data structure.\r
2493 @param Form Form data structure.\r
2494\r
2495**/\r
2496VOID\r
2497UpdateFlagForForm (\r
2498 IN BOOLEAN SetFlag,\r
2499 IN FORM_BROWSER_FORMSET *FormSet,\r
2500 IN FORM_BROWSER_FORM *Form\r
2501 )\r
2502{\r
2503 LIST_ENTRY *Link;\r
2504 FORM_BROWSER_STATEMENT *Question;\r
2505 BOOLEAN OldValue;\r
2506\r
2507 Link = GetFirstNode (&Form->StatementListHead);\r
2508 while (!IsNull (&Form->StatementListHead, Link)) {\r
2509 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2510 Link = GetNextNode (&Form->StatementListHead, Link);\r
2511\r
2512 if (!Question->ValueChanged) {\r
2513 continue;\r
2514 }\r
2515\r
2516 OldValue = Question->ValueChanged;\r
2517\r
2518 //\r
2519 // Compare the buffer and editbuffer data to see whether the data has been saved.\r
2520 //\r
2521 Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);\r
2522\r
2523 //\r
2524 // Only the changed data has been saved, then need to set the reset flag.\r
2525 //\r
2526 if (SetFlag && OldValue && !Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
2527 gResetRequired = TRUE;\r
2528 } \r
2529 }\r
2530}\r
2531\r
2532/**\r
2533 Check whether need to enable the reset flag.\r
2534 Also clean ValueChanged flag for all statements.\r
2535\r
2536 Form level or formset level, only one.\r
2537 \r
2538 @param SetFlag Whether need to set the Reset Flag.\r
2539 @param FormSet FormSet data structure.\r
2540 @param Form Form data structure.\r
2541\r
2542**/\r
2543VOID\r
2544ValueChangeResetFlagUpdate (\r
2545 IN BOOLEAN SetFlag,\r
2546 IN FORM_BROWSER_FORMSET *FormSet,\r
2547 IN FORM_BROWSER_FORM *Form \r
2548 )\r
2549{\r
2550 FORM_BROWSER_FORM *CurrentForm;\r
2551 LIST_ENTRY *Link;\r
2552\r
2553 if (Form != NULL) {\r
2554 UpdateFlagForForm(SetFlag, FormSet, Form);\r
2555 return;\r
2556 }\r
2557\r
2558 Link = GetFirstNode (&FormSet->FormListHead);\r
2559 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2560 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2561 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2562\r
2563 UpdateFlagForForm(SetFlag, FormSet, CurrentForm);\r
2564 }\r
2565}\r
2566\r
2567/**\r
2568 Base on the return Progress string to find the form. \r
2569 \r
2570 Base on the first return Offset/Width (Name) string to find the form\r
2571 which keep this string.\r
2572\r
2573 @param FormSet FormSet data structure.\r
2574 @param Storage Storage which has this Progress string.\r
2575 @param Progress The Progress string which has the first fail string.\r
2576 @param RetForm The return form for this progress string.\r
2577 @param RetQuestion The return question for the error progress string.\r
2578\r
2579 @retval TRUE Find the error form and statement for this error progress string.\r
2580 @retval FALSE Not find the error form.\r
2581\r
2582**/\r
2583BOOLEAN\r
2584FindQuestionFromProgress (\r
2585 IN FORM_BROWSER_FORMSET *FormSet,\r
2586 IN BROWSER_STORAGE *Storage,\r
2587 IN EFI_STRING Progress,\r
2588 OUT FORM_BROWSER_FORM **RetForm,\r
2589 OUT FORM_BROWSER_STATEMENT **RetQuestion\r
2590 )\r
2591{\r
2592 LIST_ENTRY *Link;\r
2593 LIST_ENTRY *LinkStorage;\r
2594 LIST_ENTRY *LinkStatement;\r
2595 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
2596 FORM_BROWSER_FORM *Form;\r
2597 EFI_STRING EndStr;\r
2598 FORM_BROWSER_STATEMENT *Statement;\r
2599\r
2600 ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
2601\r
2602 ConfigInfo = NULL;\r
2603 *RetForm = NULL;\r
2604 *RetQuestion = NULL;\r
2605\r
2606 //\r
2607 // Skip the first "&" or the ConfigHdr part.\r
2608 //\r
2609 if (*Progress == '&') {\r
2610 Progress++;\r
2611 } else {\r
2612 //\r
2613 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2614 //\r
2615 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2616 //\r
2617 // For Name/Value type, Skip the ConfigHdr part.\r
2618 //\r
2619 EndStr = StrStr (Progress, L"PATH=");\r
2620 ASSERT (EndStr != NULL);\r
2621 while (*EndStr != '&') {\r
2622 EndStr++;\r
2623 }\r
2624\r
2625 *EndStr = '\0';\r
2626 } else {\r
2627 //\r
2628 // For Buffer type, Skip the ConfigHdr part.\r
2629 //\r
2630 EndStr = StrStr (Progress, L"&OFFSET=");\r
2631 ASSERT (EndStr != NULL);\r
2632 *EndStr = '\0';\r
2633 }\r
2634\r
2635 Progress = EndStr + 1;\r
2636 }\r
2637\r
2638 //\r
2639 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2640 //\r
2641 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2642 //\r
2643 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
2644 // here, just keep the "Fred" string.\r
2645 //\r
2646 EndStr = StrStr (Progress, L"=");\r
2647 ASSERT (EndStr != NULL);\r
2648 *EndStr = '\0';\r
2649 } else {\r
2650 //\r
2651 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
2652 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
2653 //\r
2654 EndStr = StrStr (Progress, L"&VALUE=");\r
2655 ASSERT (EndStr != NULL);\r
2656 *EndStr = '\0';\r
2657 }\r
2658\r
2659 //\r
2660 // Search in the form list.\r
2661 //\r
2662 Link = GetFirstNode (&FormSet->FormListHead);\r
2663 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2664 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2665 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2666\r
2667 //\r
2668 // Search in the ConfigReqeust list in this form.\r
2669 //\r
2670 LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
2671 while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
2672 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
2673 LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
2674\r
2675 if (Storage != ConfigInfo->Storage) {\r
2676 continue;\r
2677 }\r
2678\r
2679 if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
2680 //\r
2681 // Find the OffsetWidth string in this form.\r
2682 //\r
2683 *RetForm = Form;\r
2684 break;\r
2685 }\r
2686 }\r
2687\r
2688 if (*RetForm != NULL) {\r
2689 LinkStatement = GetFirstNode (&Form->StatementListHead);\r
2690 while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
2691 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
2692 LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
2693\r
2694 if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {\r
2695 *RetQuestion = Statement;\r
2696 break;\r
2697 }\r
2698\r
2699 if (Statement->VariableName != NULL && StrStr (Statement->VariableName, Progress) != NULL) {\r
2700 *RetQuestion = Statement;\r
2701 break;\r
2702 }\r
2703 }\r
2704 }\r
2705\r
2706 if (*RetForm != NULL) {\r
2707 break;\r
2708 }\r
2709 }\r
2710\r
2711 //\r
2712 // restore the OffsetWidth string to the original format.\r
2713 //\r
2714 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2715 *EndStr = '=';\r
2716 } else {\r
2717 *EndStr = '&';\r
2718 }\r
2719\r
2720 return (BOOLEAN) (*RetForm != NULL);\r
2721}\r
2722\r
2723/**\r
2724 Popup an save error info and get user input.\r
2725\r
2726 @param TitleId The form title id.\r
2727 @param HiiHandle The hii handle for this package.\r
2728\r
2729 @retval UINT32 The user select option for the save fail.\r
2730 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2731**/\r
2732UINT32\r
2733ConfirmSaveFail (\r
2734 IN EFI_STRING_ID TitleId,\r
2735 IN EFI_HII_HANDLE HiiHandle\r
2736 )\r
2737{\r
2738 CHAR16 *FormTitle;\r
2739 CHAR16 *StringBuffer;\r
2740 UINT32 RetVal;\r
2741\r
2742 FormTitle = GetToken (TitleId, HiiHandle);\r
2743\r
2744 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
2745 ASSERT (StringBuffer != NULL);\r
2746\r
2747 UnicodeSPrint (\r
2748 StringBuffer, \r
2749 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
2750 L"Submit Fail For Form: %s.", \r
2751 FormTitle\r
2752 );\r
2753\r
2754 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
2755\r
2756 FreePool (StringBuffer);\r
2757 FreePool (FormTitle);\r
2758\r
2759 return RetVal;\r
2760}\r
2761\r
2762/**\r
2763 Popup an NO_SUBMIT_IF error info and get user input.\r
2764\r
2765 @param TitleId The form title id.\r
2766 @param HiiHandle The hii handle for this package.\r
2767\r
2768 @retval UINT32 The user select option for the save fail.\r
2769 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2770**/\r
2771UINT32\r
2772ConfirmNoSubmitFail (\r
2773 IN EFI_STRING_ID TitleId,\r
2774 IN EFI_HII_HANDLE HiiHandle\r
2775 )\r
2776{\r
2777 CHAR16 *FormTitle;\r
2778 CHAR16 *StringBuffer;\r
2779 UINT32 RetVal;\r
2780\r
2781 FormTitle = GetToken (TitleId, HiiHandle);\r
2782\r
2783 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
2784 ASSERT (StringBuffer != NULL);\r
2785\r
2786 UnicodeSPrint (\r
2787 StringBuffer, \r
2788 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
2789 L"NO_SUBMIT_IF error For Form: %s.", \r
2790 FormTitle\r
2791 );\r
2792\r
2793 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
2794\r
2795 FreePool (StringBuffer);\r
2796 FreePool (FormTitle);\r
2797\r
2798 return RetVal;\r
2799}\r
2800\r
2801/**\r
2802 Discard data based on the input setting scope (Form, FormSet or System).\r
2803\r
2804 @param FormSet FormSet data structure.\r
2805 @param Form Form data structure.\r
2806 @param SettingScope Setting Scope for Discard action.\r
2807\r
2808 @retval EFI_SUCCESS The function completed successfully.\r
2809 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
2810\r
2811**/\r
2812EFI_STATUS\r
2813DiscardForm (\r
2814 IN FORM_BROWSER_FORMSET *FormSet,\r
2815 IN FORM_BROWSER_FORM *Form,\r
2816 IN BROWSER_SETTING_SCOPE SettingScope\r
2817 )\r
2818{\r
2819 LIST_ENTRY *Link;\r
2820 FORMSET_STORAGE *Storage;\r
2821 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
2822 FORM_BROWSER_FORMSET *LocalFormSet;\r
2823 FORM_BROWSER_FORMSET *OldFormSet;\r
2824\r
2825 //\r
2826 // Check the supported setting level.\r
2827 //\r
2828 if (SettingScope >= MaxLevel) {\r
2829 return EFI_UNSUPPORTED;\r
2830 }\r
2831\r
2832 if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
2833 ConfigInfo = NULL;\r
2834 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2835 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2836 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2837 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
2838\r
2839 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2840 continue;\r
2841 }\r
2842\r
2843 //\r
2844 // Skip if there is no RequestElement\r
2845 //\r
2846 if (ConfigInfo->ElementCount == 0) {\r
2847 continue;\r
2848 }\r
2849\r
2850 //\r
2851 // Prepare <ConfigResp>\r
2852 //\r
2853 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
2854\r
2855 //\r
2856 // Call callback with Changed type to inform the driver.\r
2857 //\r
2858 SendDiscardInfoToDriver (FormSet, Form);\r
2859 }\r
2860\r
2861 ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
2862 } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
2863\r
2864 //\r
2865 // Discard Buffer storage or Name/Value storage\r
2866 //\r
2867 Link = GetFirstNode (&FormSet->StorageListHead);\r
2868 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2869 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2870 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2871\r
2872 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2873 continue;\r
2874 }\r
2875\r
2876 //\r
2877 // Skip if there is no RequestElement\r
2878 //\r
2879 if (Storage->ElementCount == 0) {\r
2880 continue;\r
2881 }\r
2882\r
2883 SynchronizeStorage(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
2884 }\r
2885\r
2886 Link = GetFirstNode (&FormSet->FormListHead);\r
2887 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2888 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2889 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2890 \r
2891 //\r
2892 // Call callback with Changed type to inform the driver.\r
2893 //\r
2894 SendDiscardInfoToDriver (FormSet, Form);\r
2895 }\r
2896\r
2897 ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
2898 } else if (SettingScope == SystemLevel) {\r
2899 //\r
2900 // System Level Discard.\r
2901 //\r
2902 OldFormSet = mSystemLevelFormSet;\r
2903\r
2904 //\r
2905 // Discard changed value for each FormSet in the maintain list.\r
2906 //\r
2907 Link = GetFirstNode (&gBrowserFormSetList);\r
2908 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2909 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
2910 Link = GetNextNode (&gBrowserFormSetList, Link);\r
2911 if (!ValidateFormSet(LocalFormSet)) {\r
2912 continue;\r
2913 }\r
2914\r
2915 mSystemLevelFormSet = LocalFormSet;\r
2916\r
2917 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
2918 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
2919 //\r
2920 // Remove maintain backup list after discard except for the current using FormSet.\r
2921 //\r
2922 CleanBrowserStorage(LocalFormSet);\r
2923 RemoveEntryList (&LocalFormSet->Link);\r
2924 DestroyFormSet (LocalFormSet);\r
2925 }\r
2926 }\r
2927\r
2928 mSystemLevelFormSet = OldFormSet;\r
2929 }\r
2930\r
2931 return EFI_SUCCESS; \r
2932}\r
2933\r
2934/**\r
2935 Submit data for a form.\r
2936\r
2937 @param FormSet FormSet data structure.\r
2938 @param Form Form data structure.\r
2939\r
2940 @retval EFI_SUCCESS The function completed successfully.\r
2941 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
2942\r
2943**/\r
2944EFI_STATUS\r
2945SubmitForForm (\r
2946 IN FORM_BROWSER_FORMSET *FormSet,\r
2947 IN FORM_BROWSER_FORM *Form\r
2948 )\r
2949{\r
2950 EFI_STATUS Status;\r
2951 LIST_ENTRY *Link;\r
2952 EFI_STRING ConfigResp;\r
2953 EFI_STRING Progress;\r
2954 BROWSER_STORAGE *Storage;\r
2955 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
2956\r
2957 if (!IsNvUpdateRequiredForForm (Form)) {\r
2958 return EFI_SUCCESS;\r
2959 }\r
2960\r
2961 Status = NoSubmitCheck (FormSet, &Form, NULL);\r
2962 if (EFI_ERROR (Status)) {\r
2963 return Status;\r
2964 }\r
2965\r
2966 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2967 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2968 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2969 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
2970\r
2971 Storage = ConfigInfo->Storage;\r
2972 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2973 continue;\r
2974 }\r
2975\r
2976 //\r
2977 // Skip if there is no RequestElement\r
2978 //\r
2979 if (ConfigInfo->ElementCount == 0) {\r
2980 continue;\r
2981 }\r
2982\r
2983 //\r
2984 // 1. Prepare <ConfigResp>\r
2985 //\r
2986 Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
2987 if (EFI_ERROR (Status)) {\r
2988 return Status;\r
2989 }\r
2990\r
2991 //\r
2992 // 2. Set value to hii config routine protocol.\r
2993 //\r
2994 Status = mHiiConfigRouting->RouteConfig (\r
2995 mHiiConfigRouting,\r
2996 ConfigResp,\r
2997 &Progress\r
2998 );\r
2999 FreePool (ConfigResp);\r
3000\r
3001 if (EFI_ERROR (Status)) {\r
3002 InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
3003 continue;\r
3004 }\r
3005\r
3006 //\r
3007 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
3008 //\r
3009 SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
3010 }\r
3011\r
3012 //\r
3013 // 4. Process the save failed storage.\r
3014 //\r
3015 if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3016 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3017 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3018 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3019 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3020 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
3021\r
3022 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
3023\r
3024 Status = EFI_SUCCESS;\r
3025 }\r
3026 } else {\r
3027 Status = EFI_UNSUPPORTED;\r
3028 }\r
3029\r
3030 //\r
3031 // Free Form save fail list.\r
3032 //\r
3033 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3034 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3035 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3036 RemoveEntryList (&ConfigInfo->SaveFailLink);\r
3037 }\r
3038 }\r
3039\r
3040 //\r
3041 // 5. Update the NV flag.\r
3042 //\r
3043 ValueChangeResetFlagUpdate(TRUE, FormSet, Form);\r
3044\r
3045 return Status;\r
3046}\r
3047\r
3048/**\r
3049 Submit data for a formset.\r
3050\r
3051 @param FormSet FormSet data structure.\r
3052 @param SkipProcessFail Whether skip to process the save failed storage.\r
3053 If submit formset is called when do system level save, \r
3054 set this value to true and process the failed formset \r
3055 together. \r
3056 if submit formset is called when do formset level save,\r
3057 set the value to false and process the failed storage\r
3058 right after process all storages for this formset.\r
3059\r
3060 @retval EFI_SUCCESS The function completed successfully.\r
3061 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3062\r
3063**/\r
3064EFI_STATUS\r
3065SubmitForFormSet (\r
3066 IN FORM_BROWSER_FORMSET *FormSet,\r
3067 IN BOOLEAN SkipProcessFail\r
3068 )\r
3069{\r
3070 EFI_STATUS Status;\r
3071 LIST_ENTRY *Link;\r
3072 EFI_STRING ConfigResp;\r
3073 EFI_STRING Progress;\r
3074 BROWSER_STORAGE *Storage;\r
3075 FORMSET_STORAGE *FormSetStorage;\r
3076 FORM_BROWSER_FORM *Form;\r
3077 BOOLEAN HasInserted;\r
3078 FORM_BROWSER_STATEMENT *Question;\r
3079\r
3080 HasInserted = FALSE;\r
3081\r
3082 if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
3083 return EFI_SUCCESS;\r
3084 }\r
3085\r
3086 Form = NULL; \r
3087 Status = NoSubmitCheck (FormSet, &Form, &Question);\r
3088 if (EFI_ERROR (Status)) {\r
3089 if (SkipProcessFail) {\r
3090 //\r
3091 // Process NO_SUBMIT check first, so insert it at head.\r
3092 //\r
3093 FormSet->SaveFailForm = Form;\r
3094 FormSet->SaveFailStatement = Question;\r
3095 InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3096 }\r
3097\r
3098 return Status;\r
3099 }\r
3100\r
3101 Form = NULL;\r
3102 Question = NULL;\r
3103 //\r
3104 // Submit Buffer storage or Name/Value storage\r
3105 //\r
3106 Link = GetFirstNode (&FormSet->StorageListHead);\r
3107 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3108 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3109 Storage = FormSetStorage->BrowserStorage;\r
3110 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3111\r
3112 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3113 continue;\r
3114 }\r
3115\r
3116 //\r
3117 // Skip if there is no RequestElement\r
3118 //\r
3119 if (FormSetStorage->ElementCount == 0) {\r
3120 continue;\r
3121 }\r
3122\r
3123 //\r
3124 // 1. Prepare <ConfigResp>\r
3125 //\r
3126 Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
3127 if (EFI_ERROR (Status)) {\r
3128 return Status;\r
3129 }\r
3130\r
3131 //\r
3132 // 2. Send <ConfigResp> to Routine config Protocol.\r
3133 //\r
3134 Status = mHiiConfigRouting->RouteConfig (\r
3135 mHiiConfigRouting,\r
3136 ConfigResp,\r
3137 &Progress\r
3138 );\r
3139 if (EFI_ERROR (Status)) {\r
3140 InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
3141 if (!HasInserted) {\r
3142 //\r
3143 // Call submit formset for system level, save the formset info\r
3144 // and process later.\r
3145 //\r
3146 FindQuestionFromProgress(FormSet, Storage, Progress, &Form, &Question);\r
3147 ASSERT (Form != NULL && Question != NULL);\r
3148 FormSet->SaveFailForm = Form;\r
3149 FormSet->SaveFailStatement = Question;\r
3150 if (SkipProcessFail) {\r
3151 InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3152 }\r
3153 HasInserted = TRUE;\r
3154 }\r
3155\r
3156 FreePool (ConfigResp);\r
3157 continue;\r
3158 }\r
3159\r
3160 FreePool (ConfigResp);\r
3161 //\r
3162 // 3. Config success, update storage shadow Buffer\r
3163 //\r
3164 SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
3165 }\r
3166\r
3167 //\r
3168 // 4. Has save fail storage need to handle.\r
3169 //\r
3170 if (Form != NULL) {\r
3171 if (!SkipProcessFail) {\r
3172 //\r
3173 // If not in system level, just handl the save failed storage here.\r
3174 //\r
3175 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3176 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3177 while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
3178 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3179 Storage = FormSetStorage->BrowserStorage;\r
3180 Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
3181\r
3182 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3183\r
3184 Status = EFI_SUCCESS;\r
3185 }\r
3186 } else {\r
3187 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3188\r
3189 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3190 gCurrentSelection->Handle = FormSet->HiiHandle;\r
3191 CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
3192 gCurrentSelection->FormId = Form->FormId;\r
3193 gCurrentSelection->QuestionId = Question->QuestionId;\r
3194\r
3195 Status = EFI_UNSUPPORTED;\r
3196 }\r
3197\r
3198 //\r
3199 // Free FormSet save fail list.\r
3200 //\r
3201 while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
3202 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3203 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3204 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
3205 }\r
3206 } else {\r
3207 //\r
3208 // If in system level, just return error and handle the failed formset later.\r
3209 //\r
3210 Status = EFI_UNSUPPORTED;\r
3211 }\r
3212 }\r
3213\r
3214 //\r
3215 // 5. Update the NV flag.\r
3216 // \r
3217 ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
3218\r
3219 return Status;\r
3220}\r
3221\r
3222/**\r
3223 Submit data for all formsets.\r
3224\r
3225 @retval EFI_SUCCESS The function completed successfully.\r
3226 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3227\r
3228**/\r
3229EFI_STATUS\r
3230SubmitForSystem (\r
3231 VOID\r
3232 )\r
3233{\r
3234 EFI_STATUS Status;\r
3235 LIST_ENTRY *Link;\r
3236 LIST_ENTRY *StorageLink;\r
3237 FORMSET_STORAGE *FormSetStorage;\r
3238 FORM_BROWSER_FORM *Form;\r
3239 FORM_BROWSER_FORMSET *LocalFormSet;\r
3240 UINT32 UserSelection;\r
3241 FORM_BROWSER_STATEMENT *Question;\r
3242\r
3243 mSystemSubmit = TRUE;\r
3244 Link = GetFirstNode (&gBrowserFormSetList);\r
3245 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3246 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3247 Link = GetNextNode (&gBrowserFormSetList, Link);\r
3248 if (!ValidateFormSet(LocalFormSet)) {\r
3249 continue;\r
3250 }\r
3251\r
3252 Status = SubmitForFormSet (LocalFormSet, TRUE);\r
3253 if (EFI_ERROR (Status)) {\r
3254 continue;\r
3255 }\r
3256\r
3257 //\r
3258 // Remove maintain backup list after save except for the current using FormSet.\r
3259 // \r
3260 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
3261 CleanBrowserStorage(LocalFormSet);\r
3262 RemoveEntryList (&LocalFormSet->Link);\r
3263 DestroyFormSet (LocalFormSet);\r
3264 }\r
3265 }\r
3266 mSystemSubmit = FALSE;\r
3267\r
3268 Status = EFI_SUCCESS;\r
3269\r
3270 //\r
3271 // Process the save failed formsets.\r
3272 //\r
3273 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3274 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3275 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3276 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
3277\r
3278 if (!ValidateFormSet(LocalFormSet)) {\r
3279 continue;\r
3280 }\r
3281\r
3282 Form = LocalFormSet->SaveFailForm;\r
3283 Question= LocalFormSet->SaveFailStatement;\r
3284\r
3285 //\r
3286 // Confirm with user, get user input.\r
3287 //\r
3288 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3289 //\r
3290 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
3291 //\r
3292 UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3293 } else {\r
3294 UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3295 }\r
3296\r
3297 if (UserSelection == BROWSER_ACTION_DISCARD) {\r
3298 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3299 StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
3300 while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
3301 FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
3302 StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
3303\r
3304 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3305 }\r
3306 } else {\r
3307 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3308 while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
3309 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
3310 StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
3311\r
3312 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3313 }\r
3314 }\r
3315\r
3316 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
3317 CleanBrowserStorage(LocalFormSet);\r
3318 RemoveEntryList (&LocalFormSet->Link);\r
3319 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
3320 DestroyFormSet (LocalFormSet);\r
3321 } else {\r
3322 ValueChangeResetFlagUpdate(FALSE, LocalFormSet, NULL);\r
3323 }\r
3324 } else {\r
3325 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3326 NoSubmitCheck (LocalFormSet, &Form, &Question);\r
3327 }\r
3328\r
3329 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3330\r
3331 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3332 gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
3333 CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
3334 gCurrentSelection->FormId = Form->FormId;\r
3335 gCurrentSelection->QuestionId = Question->QuestionId;\r
3336\r
3337 Status = EFI_UNSUPPORTED;\r
3338 break;\r
3339 }\r
3340 }\r
3341\r
3342 //\r
3343 // Clean the list which will not process.\r
3344 //\r
3345 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3346 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3347 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3348 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
3349\r
3350 while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3351 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3352 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
3353 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
3354 }\r
3355 }\r
3356\r
3357 return Status;\r
3358}\r
3359\r
3360/**\r
3361 Submit data based on the input Setting level (Form, FormSet or System).\r
3362\r
3363 @param FormSet FormSet data structure.\r
3364 @param Form Form data structure.\r
3365 @param SettingScope Setting Scope for Submit action.\r
3366\r
3367 @retval EFI_SUCCESS The function completed successfully.\r
3368 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3369\r
3370**/\r
3371EFI_STATUS\r
3372SubmitForm (\r
3373 IN FORM_BROWSER_FORMSET *FormSet,\r
3374 IN FORM_BROWSER_FORM *Form,\r
3375 IN BROWSER_SETTING_SCOPE SettingScope\r
3376 )\r
3377{\r
3378 EFI_STATUS Status;\r
3379\r
3380 switch (SettingScope) {\r
3381 case FormLevel:\r
3382 Status = SubmitForForm(FormSet, Form);\r
3383 break;\r
3384\r
3385 case FormSetLevel:\r
3386 Status = SubmitForFormSet (FormSet, FALSE);\r
3387 break;\r
3388\r
3389 case SystemLevel:\r
3390 Status = SubmitForSystem ();\r
3391 break;\r
3392\r
3393 default:\r
3394 Status = EFI_UNSUPPORTED;\r
3395 break;\r
3396 }\r
3397\r
3398 return Status;\r
3399}\r
3400\r
3401/**\r
3402 Converts the unicode character of the string from uppercase to lowercase.\r
3403 This is a internal function.\r
3404\r
3405 @param ConfigString String to be converted\r
3406\r
3407**/\r
3408VOID\r
3409EFIAPI\r
3410HiiToLower (\r
3411 IN EFI_STRING ConfigString\r
3412 )\r
3413{\r
3414 EFI_STRING String;\r
3415 BOOLEAN Lower;\r
3416\r
3417 ASSERT (ConfigString != NULL);\r
3418\r
3419 //\r
3420 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
3421 //\r
3422 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
3423 if (*String == L'=') {\r
3424 Lower = TRUE;\r
3425 } else if (*String == L'&') {\r
3426 Lower = FALSE;\r
3427 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
3428 *String = (CHAR16) (*String - L'A' + L'a');\r
3429 }\r
3430 }\r
3431}\r
3432\r
3433/**\r
3434 Find the point in the ConfigResp string for this question.\r
3435\r
3436 @param Question The question.\r
3437 @param ConfigResp Get ConfigResp string.\r
3438\r
3439 @retval point to the offset where is for this question.\r
3440\r
3441**/\r
3442CHAR16 *\r
3443GetOffsetFromConfigResp (\r
3444 IN FORM_BROWSER_STATEMENT *Question,\r
3445 IN CHAR16 *ConfigResp\r
3446 )\r
3447{\r
3448 CHAR16 *RequestElement;\r
3449 CHAR16 *BlockData;\r
3450\r
3451 //\r
3452 // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
3453 //\r
3454 if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3455 RequestElement = StrStr (ConfigResp, Question->VariableName);\r
3456 if (RequestElement != NULL) {\r
3457 //\r
3458 // Skip the "VariableName=" field.\r
3459 //\r
3460 RequestElement += StrLen (Question->VariableName) + 1;\r
3461 }\r
3462\r
3463 return RequestElement;\r
3464 }\r
3465\r
3466 //\r
3467 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
3468 //\r
3469\r
3470 //\r
3471 // 1. Directly use Question->BlockName to find.\r
3472 //\r
3473 RequestElement = StrStr (ConfigResp, Question->BlockName);\r
3474 if (RequestElement != NULL) {\r
3475 //\r
3476 // Skip the "Question->BlockName&VALUE=" field.\r
3477 //\r
3478 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
3479 return RequestElement;\r
3480 }\r
3481 \r
3482 //\r
3483 // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
3484 //\r
3485 BlockData = AllocateCopyPool (StrSize(Question->BlockName), Question->BlockName);\r
3486 ASSERT (BlockData != NULL);\r
3487 HiiToLower (BlockData);\r
3488 RequestElement = StrStr (ConfigResp, BlockData);\r
3489 FreePool (BlockData);\r
3490\r
3491 if (RequestElement != NULL) {\r
3492 //\r
3493 // Skip the "Question->BlockName&VALUE=" field.\r
3494 //\r
3495 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
3496 }\r
3497\r
3498 return RequestElement;\r
3499}\r
3500\r
3501/**\r
3502 Get Question default value from AltCfg string.\r
3503\r
3504 @param FormSet The form set.\r
3505 @param Form The form\r
3506 @param Question The question.\r
3507\r
3508 @retval EFI_SUCCESS Question is reset to default value.\r
3509\r
3510**/\r
3511EFI_STATUS\r
3512GetDefaultValueFromAltCfg (\r
3513 IN FORM_BROWSER_FORMSET *FormSet,\r
3514 IN FORM_BROWSER_FORM *Form,\r
3515 IN OUT FORM_BROWSER_STATEMENT *Question\r
3516 )\r
3517{ \r
3518 BROWSER_STORAGE *Storage;\r
3519 FORMSET_STORAGE *FormSetStorage;\r
3520 CHAR16 *ConfigResp;\r
3521 CHAR16 *Value;\r
3522 LIST_ENTRY *Link;\r
3523 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
3524\r
3525 Storage = Question->Storage;\r
3526 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
3527 return EFI_NOT_FOUND;\r
3528 }\r
3529\r
3530 //\r
3531 // Try to get AltCfg string from form. If not found it, then\r
3532 // try to get it from formset.\r
3533 //\r
3534 ConfigResp = NULL;\r
3535 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3536 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3537 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3538 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
3539\r
3540 if (Storage == ConfigInfo->Storage) {\r
3541 ConfigResp = ConfigInfo->ConfigAltResp;\r
3542 break;\r
3543 }\r
3544 }\r
3545\r
3546 if (ConfigResp == NULL) {\r
3547 Link = GetFirstNode (&FormSet->StorageListHead);\r
3548 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3549 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3550 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3551\r
3552 if (Storage == FormSetStorage->BrowserStorage) {\r
3553 ConfigResp = FormSetStorage->ConfigAltResp;\r
3554 break;\r
3555 }\r
3556 }\r
3557 }\r
3558\r
3559 if (ConfigResp == NULL) {\r
3560 return EFI_NOT_FOUND;\r
3561 }\r
3562\r
3563 Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
3564 if (Value == NULL) {\r
3565 return EFI_NOT_FOUND;\r
3566 }\r
3567\r
3568 return BufferToValue (Question, Value);\r
3569}\r
3570\r
3571/**\r
3572 Get default Id value used for browser.\r
3573\r
3574 @param DefaultId The default id value used by hii.\r
3575\r
3576 @retval Browser used default value.\r
3577\r
3578**/\r
3579INTN\r
3580GetDefaultIdForCallBack (\r
3581 UINTN DefaultId\r
3582 )\r
3583{ \r
3584 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
3585 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
3586 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3587 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
3588 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
3589 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
3590 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
3591 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
3592 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
3593 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
3594 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
3595 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
3596 } else {\r
3597 return -1;\r
3598 }\r
3599}\r
3600\r
3601\r
3602\r
3603/**\r
3604 Return data element in an Array by its Index.\r
3605\r
3606 @param Array The data array.\r
3607 @param Type Type of the data in this array.\r
3608 @param Index Zero based index for data in this array.\r
3609\r
3610 @retval Value The data to be returned\r
3611\r
3612**/\r
3613UINT64\r
3614GetArrayData (\r
3615 IN VOID *Array,\r
3616 IN UINT8 Type,\r
3617 IN UINTN Index\r
3618 )\r
3619{\r
3620 UINT64 Data;\r
3621\r
3622 ASSERT (Array != NULL);\r
3623\r
3624 Data = 0;\r
3625 switch (Type) {\r
3626 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3627 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
3628 break;\r
3629\r
3630 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3631 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
3632 break;\r
3633\r
3634 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3635 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
3636 break;\r
3637\r
3638 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3639 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
3640 break;\r
3641\r
3642 default:\r
3643 break;\r
3644 }\r
3645\r
3646 return Data;\r
3647}\r
3648\r
3649\r
3650/**\r
3651 Set value of a data element in an Array by its Index.\r
3652\r
3653 @param Array The data array.\r
3654 @param Type Type of the data in this array.\r
3655 @param Index Zero based index for data in this array.\r
3656 @param Value The value to be set.\r
3657\r
3658**/\r
3659VOID\r
3660SetArrayData (\r
3661 IN VOID *Array,\r
3662 IN UINT8 Type,\r
3663 IN UINTN Index,\r
3664 IN UINT64 Value\r
3665 )\r
3666{\r
3667\r
3668 ASSERT (Array != NULL);\r
3669\r
3670 switch (Type) {\r
3671 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3672 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
3673 break;\r
3674\r
3675 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3676 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
3677 break;\r
3678\r
3679 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3680 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
3681 break;\r
3682\r
3683 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3684 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
3685 break;\r
3686\r
3687 default:\r
3688 break;\r
3689 }\r
3690}\r
3691\r
3692/**\r
3693 Search an Option of a Question by its value.\r
3694\r
3695 @param Question The Question\r
3696 @param OptionValue Value for Option to be searched.\r
3697\r
3698 @retval Pointer Pointer to the found Option.\r
3699 @retval NULL Option not found.\r
3700\r
3701**/\r
3702QUESTION_OPTION *\r
3703ValueToOption (\r
3704 IN FORM_BROWSER_STATEMENT *Question,\r
3705 IN EFI_HII_VALUE *OptionValue\r
3706 )\r
3707{\r
3708 LIST_ENTRY *Link;\r
3709 QUESTION_OPTION *Option;\r
3710 INTN Result;\r
3711\r
3712 Link = GetFirstNode (&Question->OptionListHead);\r
3713 while (!IsNull (&Question->OptionListHead, Link)) {\r
3714 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3715\r
3716 if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
3717 //\r
3718 // Check the suppressif condition, only a valid option can be return.\r
3719 //\r
3720 if ((Option->SuppressExpression == NULL) ||\r
3721 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
3722 return Option;\r
3723 }\r
3724 }\r
3725\r
3726 Link = GetNextNode (&Question->OptionListHead, Link);\r
3727 }\r
3728\r
3729 return NULL;\r
3730}\r
3731\r
3732\r
3733/**\r
3734 Reset Question to its default value.\r
3735\r
3736 @param FormSet The form set.\r
3737 @param Form The form.\r
3738 @param Question The question.\r
3739 @param DefaultId The Class of the default.\r
3740\r
3741 @retval EFI_SUCCESS Question is reset to default value.\r
3742\r
3743**/\r
3744EFI_STATUS\r
3745GetQuestionDefault (\r
3746 IN FORM_BROWSER_FORMSET *FormSet,\r
3747 IN FORM_BROWSER_FORM *Form,\r
3748 IN FORM_BROWSER_STATEMENT *Question,\r
3749 IN UINT16 DefaultId\r
3750 )\r
3751{\r
3752 EFI_STATUS Status;\r
3753 LIST_ENTRY *Link;\r
3754 QUESTION_DEFAULT *Default;\r
3755 QUESTION_OPTION *Option;\r
3756 EFI_HII_VALUE *HiiValue;\r
3757 UINT8 Index;\r
3758 EFI_STRING StrValue;\r
3759 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3760 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
3761 INTN Action;\r
3762 CHAR16 *NewString;\r
3763\r
3764 Status = EFI_NOT_FOUND;\r
3765 StrValue = NULL;\r
3766\r
3767 //\r
3768 // Statement don't have storage, skip them\r
3769 //\r
3770 if (Question->QuestionId == 0) {\r
3771 return Status;\r
3772 }\r
3773\r
3774 //\r
3775 // There are Five ways to specify default value for a Question:\r
3776 // 1, use call back function (highest priority)\r
3777 // 2, use ExtractConfig function\r
3778 // 3, use nested EFI_IFR_DEFAULT \r
3779 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
3780 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
3781 //\r
3782 HiiValue = &Question->HiiValue;\r
3783\r
3784 //\r
3785 // Get Question defaut value from call back function.\r
3786 //\r
3787 ConfigAccess = FormSet->ConfigAccess;\r
3788 Action = GetDefaultIdForCallBack (DefaultId);\r
3789 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
3790 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
3791 Status = ConfigAccess->Callback (\r
3792 ConfigAccess,\r
3793 Action,\r
3794 Question->QuestionId,\r
3795 HiiValue->Type,\r
3796 &HiiValue->Value,\r
3797 &ActionRequest\r
3798 );\r
3799 if (!EFI_ERROR (Status)) {\r
3800 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3801 NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
3802 ASSERT (NewString != NULL);\r
3803\r
3804 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
3805 if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
3806 CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
3807 } else {\r
3808 CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
3809 }\r
3810\r
3811 FreePool (NewString);\r
3812 }\r
3813 return Status;\r
3814 }\r
3815 }\r
3816\r
3817 //\r
3818 // Get default value from altcfg string.\r
3819 //\r
3820 if (ConfigAccess != NULL) { \r
3821 Status = GetDefaultValueFromAltCfg(FormSet, Form, Question);\r
3822 if (!EFI_ERROR (Status)) {\r
3823 return Status;\r
3824 }\r
3825 }\r
3826\r
3827 //\r
3828 // EFI_IFR_DEFAULT has highest priority\r
3829 //\r
3830 if (!IsListEmpty (&Question->DefaultListHead)) {\r
3831 Link = GetFirstNode (&Question->DefaultListHead);\r
3832 while (!IsNull (&Question->DefaultListHead, Link)) {\r
3833 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
3834\r
3835 if (Default->DefaultId == DefaultId) {\r
3836 if (Default->ValueExpression != NULL) {\r
3837 //\r
3838 // Default is provided by an Expression, evaluate it\r
3839 //\r
3840 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
3841 if (EFI_ERROR (Status)) {\r
3842 return Status;\r
3843 }\r
3844\r
3845 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
3846 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
3847 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
3848 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
3849 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
3850 } else {\r
3851 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
3852 Question->HiiValue.BufferLen = Question->StorageWidth;\r
3853 }\r
3854 FreePool (Default->ValueExpression->Result.Buffer);\r
3855 }\r
3856 HiiValue->Type = Default->ValueExpression->Result.Type;\r
3857 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
3858 } else {\r
3859 //\r
3860 // Default value is embedded in EFI_IFR_DEFAULT\r
3861 //\r
3862 if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
3863 ASSERT (HiiValue->Buffer != NULL);\r
3864 CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
3865 } else {\r
3866 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
3867 }\r
3868 }\r
3869\r
3870 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3871 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
3872 if (StrValue == NULL) {\r
3873 return EFI_NOT_FOUND;\r
3874 }\r
3875 if (Question->StorageWidth > StrSize (StrValue)) {\r
3876 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
3877 } else {\r
3878 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
3879 }\r
3880 }\r
3881\r
3882 return EFI_SUCCESS;\r
3883 }\r
3884\r
3885 Link = GetNextNode (&Question->DefaultListHead, Link);\r
3886 }\r
3887 }\r
3888\r
3889 //\r
3890 // EFI_ONE_OF_OPTION\r
3891 //\r
3892 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
3893 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3894 //\r
3895 // OneOfOption could only provide Standard and Manufacturing default\r
3896 //\r
3897 Link = GetFirstNode (&Question->OptionListHead);\r
3898 while (!IsNull (&Question->OptionListHead, Link)) {\r
3899 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3900 Link = GetNextNode (&Question->OptionListHead, Link);\r
3901\r
3902 if ((Option->SuppressExpression != NULL) &&\r
3903 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3904 continue;\r
3905 }\r
3906\r
3907 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
3908 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
3909 ) {\r
3910 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
3911\r
3912 return EFI_SUCCESS;\r
3913 }\r
3914 }\r
3915 }\r
3916 }\r
3917\r
3918 //\r
3919 // EFI_IFR_CHECKBOX - lowest priority\r
3920 //\r
3921 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
3922 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3923 //\r
3924 // Checkbox could only provide Standard and Manufacturing default\r
3925 //\r
3926 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
3927 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
3928 ) {\r
3929 HiiValue->Value.b = TRUE;\r
3930 } else {\r
3931 HiiValue->Value.b = FALSE;\r
3932 }\r
3933\r
3934 return EFI_SUCCESS;\r
3935 }\r
3936 }\r
3937\r
3938 //\r
3939 // For Questions without default\r
3940 //\r
3941 Status = EFI_NOT_FOUND;\r
3942 switch (Question->Operand) {\r
3943 case EFI_IFR_NUMERIC_OP:\r
3944 //\r
3945 // Take minimum value as numeric default value\r
3946 //\r
3947 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
3948 HiiValue->Value.u64 = Question->Minimum;\r
3949 Status = EFI_SUCCESS;\r
3950 }\r
3951 break;\r
3952\r
3953 case EFI_IFR_ONE_OF_OP:\r
3954 //\r
3955 // Take first oneof option as oneof's default value\r
3956 //\r
3957 if (ValueToOption (Question, HiiValue) == NULL) {\r
3958 Link = GetFirstNode (&Question->OptionListHead);\r
3959 while (!IsNull (&Question->OptionListHead, Link)) {\r
3960 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3961 Link = GetNextNode (&Question->OptionListHead, Link);\r
3962\r
3963 if ((Option->SuppressExpression != NULL) &&\r
3964 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3965 continue;\r
3966 }\r
3967\r
3968 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
3969 Status = EFI_SUCCESS;\r
3970 break;\r
3971 }\r
3972 }\r
3973 break;\r
3974\r
3975 case EFI_IFR_ORDERED_LIST_OP:\r
3976 //\r
3977 // Take option sequence in IFR as ordered list's default value\r
3978 //\r
3979 Index = 0;\r
3980 Link = GetFirstNode (&Question->OptionListHead);\r
3981 while (!IsNull (&Question->OptionListHead, Link)) {\r
3982 Status = EFI_SUCCESS;\r
3983 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3984 Link = GetNextNode (&Question->OptionListHead, Link);\r
3985\r
3986 if ((Option->SuppressExpression != NULL) &&\r
3987 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3988 continue;\r
3989 }\r
3990\r
3991 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
3992\r
3993 Index++;\r
3994 if (Index >= Question->MaxContainers) {\r
3995 break;\r
3996 }\r
3997 }\r
3998 break;\r
3999\r
4000 default:\r
4001 break;\r
4002 }\r
4003\r
4004 return Status;\r
4005}\r
4006\r
4007/**\r
4008 Get AltCfg string for current form.\r
4009\r
4010 @param FormSet Form data structure.\r
4011 @param Form Form data structure.\r
4012 @param DefaultId The Class of the default.\r
4013 @param BrowserStorage The input request storage for the questions.\r
4014\r
4015**/\r
4016VOID\r
4017ExtractAltCfgForForm (\r
4018 IN FORM_BROWSER_FORMSET *FormSet,\r
4019 IN FORM_BROWSER_FORM *Form,\r
4020 IN UINT16 DefaultId,\r
4021 IN BROWSER_STORAGE *BrowserStorage\r
4022 )\r
4023{\r
4024 EFI_STATUS Status;\r
4025 LIST_ENTRY *Link;\r
4026 CHAR16 *ConfigResp;\r
4027 CHAR16 *Progress;\r
4028 CHAR16 *Result;\r
4029 BROWSER_STORAGE *Storage;\r
4030 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4031 FORMSET_STORAGE *FormSetStorage;\r
4032\r
4033 //\r
4034 // Check whether has get AltCfg string for this formset.\r
4035 // If yes, no need to get AltCfg for form.\r
4036 //\r
4037 Link = GetFirstNode (&FormSet->StorageListHead);\r
4038 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4039 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4040 Storage = FormSetStorage->BrowserStorage;\r
4041 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4042 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4043 continue;\r
4044 }\r
4045\r
4046 if (Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE &&\r
4047 FormSetStorage->ElementCount != 0 &&\r
4048 FormSetStorage->HasCallAltCfg) {\r
4049 return;\r
4050 }\r
4051 }\r
4052\r
4053 //\r
4054 // Get AltCfg string for each form.\r
4055 //\r
4056 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4057 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4058 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4059 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4060\r
4061 Storage = ConfigInfo->Storage;\r
4062 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4063 continue;\r
4064 }\r
4065\r
4066 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4067 continue;\r
4068 }\r
4069\r
4070 //\r
4071 // 1. Skip if there is no RequestElement\r
4072 //\r
4073 if (ConfigInfo->ElementCount == 0) {\r
4074 continue;\r
4075 }\r
4076\r
4077 //\r
4078 // 2. Get value through hii config routine protocol.\r
4079 //\r
4080 Status = mHiiConfigRouting->ExtractConfig (\r
4081 mHiiConfigRouting,\r
4082 ConfigInfo->ConfigRequest,\r
4083 &Progress,\r
4084 &Result\r
4085 );\r
4086 if (EFI_ERROR (Status)) {\r
4087 continue;\r
4088 }\r
4089\r
4090 //\r
4091 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4092 // Get the default configuration string according to the default ID.\r
4093 //\r
4094 Status = mHiiConfigRouting->GetAltConfig (\r
4095 mHiiConfigRouting,\r
4096 Result,\r
4097 &Storage->Guid,\r
4098 Storage->Name,\r
4099 NULL,\r
4100 &DefaultId, // it can be NULL to get the current setting.\r
4101 &ConfigResp\r
4102 );\r
4103 FreePool (Result);\r
4104 if (EFI_ERROR (Status)) {\r
4105 continue;\r
4106 }\r
4107\r
4108 ConfigInfo->ConfigAltResp = ConfigResp;\r
4109 }\r
4110}\r
4111\r
4112/**\r
4113 Clean AltCfg string for current form.\r
4114\r
4115 @param Form Form data structure.\r
4116\r
4117**/\r
4118VOID\r
4119CleanAltCfgForForm (\r
4120 IN FORM_BROWSER_FORM *Form\r
4121 )\r
4122{\r
4123 LIST_ENTRY *Link;\r
4124 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4125\r
4126 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4127 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4128 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4129 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4130\r
4131 if (ConfigInfo->ConfigAltResp != NULL) {\r
4132 FreePool (ConfigInfo->ConfigAltResp);\r
4133 ConfigInfo->ConfigAltResp = NULL;\r
4134 }\r
4135 }\r
4136}\r
4137\r
4138/**\r
4139 Get AltCfg string for current formset.\r
4140\r
4141 @param FormSet Form data structure.\r
4142 @param DefaultId The Class of the default.\r
4143 @param BrowserStorage The input request storage for the questions.\r
4144\r
4145**/\r
4146VOID\r
4147ExtractAltCfgForFormSet (\r
4148 IN FORM_BROWSER_FORMSET *FormSet,\r
4149 IN UINT16 DefaultId,\r
4150 IN BROWSER_STORAGE *BrowserStorage\r
4151 )\r
4152{\r
4153 EFI_STATUS Status;\r
4154 LIST_ENTRY *Link;\r
4155 CHAR16 *ConfigResp;\r
4156 CHAR16 *Progress;\r
4157 CHAR16 *Result;\r
4158 BROWSER_STORAGE *Storage;\r
4159 FORMSET_STORAGE *FormSetStorage;\r
4160\r
4161 Link = GetFirstNode (&FormSet->StorageListHead);\r
4162 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4163 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4164 Storage = FormSetStorage->BrowserStorage;\r
4165 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4166\r
4167 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4168 continue;\r
4169 }\r
4170\r
4171 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4172 continue;\r
4173 }\r
4174\r
4175 //\r
4176 // 1. Skip if there is no RequestElement\r
4177 //\r
4178 if (FormSetStorage->ElementCount == 0) {\r
4179 continue;\r
4180 }\r
4181\r
4182 FormSetStorage->HasCallAltCfg = TRUE;\r
4183\r
4184 //\r
4185 // 2. Get value through hii config routine protocol.\r
4186 //\r
4187 Status = mHiiConfigRouting->ExtractConfig (\r
4188 mHiiConfigRouting,\r
4189 FormSetStorage->ConfigRequest,\r
4190 &Progress,\r
4191 &Result\r
4192 );\r
4193 if (EFI_ERROR (Status)) {\r
4194 continue;\r
4195 }\r
4196\r
4197 //\r
4198 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4199 // Get the default configuration string according to the default ID.\r
4200 //\r
4201 Status = mHiiConfigRouting->GetAltConfig (\r
4202 mHiiConfigRouting,\r
4203 Result,\r
4204 &Storage->Guid,\r
4205 Storage->Name,\r
4206 NULL,\r
4207 &DefaultId, // it can be NULL to get the current setting.\r
4208 &ConfigResp\r
4209 );\r
4210\r
4211 FreePool (Result);\r
4212 if (EFI_ERROR (Status)) {\r
4213 continue;\r
4214 }\r
4215\r
4216 FormSetStorage->ConfigAltResp = ConfigResp;\r
4217 }\r
4218\r
4219}\r
4220\r
4221/**\r
4222 Clean AltCfg string for current formset.\r
4223\r
4224 @param FormSet Form data structure.\r
4225\r
4226**/\r
4227VOID\r
4228CleanAltCfgForFormSet (\r
4229 IN FORM_BROWSER_FORMSET *FormSet\r
4230 )\r
4231{\r
4232 LIST_ENTRY *Link;\r
4233 FORMSET_STORAGE *FormSetStorage;\r
4234\r
4235 Link = GetFirstNode (&FormSet->StorageListHead);\r
4236 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4237 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4238 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4239\r
4240 if (FormSetStorage->ConfigAltResp != NULL) {\r
4241 FreePool (FormSetStorage->ConfigAltResp);\r
4242 FormSetStorage->ConfigAltResp = NULL;\r
4243 }\r
4244\r
4245 FormSetStorage->HasCallAltCfg = FALSE;\r
4246 }\r
4247}\r
4248\r
4249/**\r
4250 Reset Questions to their initial value or default value in a Form, Formset or System.\r
4251\r
4252 GetDefaultValueScope parameter decides which questions will reset \r
4253 to its default value.\r
4254\r
4255 @param FormSet FormSet data structure.\r
4256 @param Form Form data structure.\r
4257 @param DefaultId The Class of the default.\r
4258 @param SettingScope Setting Scope for Default action.\r
4259 @param GetDefaultValueScope Get default value scope.\r
4260 @param Storage Get default value only for this storage.\r
4261 @param RetrieveValueFirst Whether call the retrieve call back to\r
4262 get the initial value before get default\r
4263 value.\r
4264 @param SkipGetAltCfg Whether skip the get altcfg string process.\r
4265\r
4266 @retval EFI_SUCCESS The function completed successfully.\r
4267 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
4268\r
4269**/\r
4270EFI_STATUS\r
4271ExtractDefault (\r
4272 IN FORM_BROWSER_FORMSET *FormSet,\r
4273 IN FORM_BROWSER_FORM *Form,\r
4274 IN UINT16 DefaultId,\r
4275 IN BROWSER_SETTING_SCOPE SettingScope,\r
4276 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
4277 IN BROWSER_STORAGE *Storage OPTIONAL,\r
4278 IN BOOLEAN RetrieveValueFirst,\r
4279 IN BOOLEAN SkipGetAltCfg\r
4280 )\r
4281{\r
4282 EFI_STATUS Status;\r
4283 LIST_ENTRY *FormLink;\r
4284 LIST_ENTRY *Link;\r
4285 FORM_BROWSER_STATEMENT *Question;\r
4286 FORM_BROWSER_FORMSET *LocalFormSet;\r
4287 FORM_BROWSER_FORMSET *OldFormSet;\r
4288\r
4289 Status = EFI_SUCCESS;\r
4290\r
4291 //\r
4292 // Check the supported setting level.\r
4293 //\r
4294 if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
4295 return EFI_UNSUPPORTED;\r
4296 }\r
4297\r
4298 if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
4299 return EFI_UNSUPPORTED;\r
4300 }\r
4301\r
4302 if (SettingScope == FormLevel) {\r
4303 //\r
4304 // Prepare the AltCfg String for form.\r
4305 //\r
4306 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4307 ExtractAltCfgForForm (FormSet, Form, DefaultId, Storage);\r
4308 }\r
4309\r
4310 //\r
4311 // Extract Form default\r
4312 //\r
4313 Link = GetFirstNode (&Form->StatementListHead);\r
4314 while (!IsNull (&Form->StatementListHead, Link)) {\r
4315 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4316 Link = GetNextNode (&Form->StatementListHead, Link);\r
4317\r
4318 //\r
4319 // If get default value only for this storage, check the storage first.\r
4320 //\r
4321 if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
4322 continue;\r
4323 }\r
4324\r
4325 //\r
4326 // If get default value only for no storage question, just skip the question which has storage.\r
4327 //\r
4328 if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
4329 continue;\r
4330 }\r
4331\r
4332 //\r
4333 // If Question is disabled, don't reset it to default\r
4334 //\r
4335 if (Question->Expression != NULL) {\r
4336 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4337 continue;\r
4338 }\r
4339 }\r
4340\r
4341 if (RetrieveValueFirst) {\r
4342 //\r
4343 // Call the Retrieve call back to get the initial question value.\r
4344 //\r
4345 Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question, FormSet);\r
4346 }\r
4347\r
4348 //\r
4349 // If not request to get the initial value or get initial value fail, then get default value.\r
4350 //\r
4351 if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
4352 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
4353 if (EFI_ERROR (Status)) {\r
4354 continue;\r
4355 }\r
4356 }\r
4357\r
4358 //\r
4359 // Synchronize Buffer storage's Edit buffer\r
4360 //\r
4361 if ((Question->Storage != NULL) &&\r
4362 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
4363 SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4364 }\r
4365 }\r
4366\r
4367 //\r
4368 // Clean the AltCfg String.\r
4369 //\r
4370 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4371 CleanAltCfgForForm(Form);\r
4372 }\r
4373 } else if (SettingScope == FormSetLevel) {\r
4374 //\r
4375 // Prepare the AltCfg String for formset.\r
4376 //\r
4377 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4378 ExtractAltCfgForFormSet (FormSet, DefaultId, Storage);\r
4379 }\r
4380\r
4381 FormLink = GetFirstNode (&FormSet->FormListHead);\r
4382 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
4383 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
4384 ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
4385 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
4386 }\r
4387\r
4388 //\r
4389 // Clean the AltCfg String.\r
4390 //\r
4391 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4392 CleanAltCfgForFormSet (FormSet);\r
4393 }\r
4394 } else if (SettingScope == SystemLevel) {\r
4395 //\r
4396 // Preload all Hii formset.\r
4397 //\r
4398 LoadAllHiiFormset();\r
4399\r
4400 OldFormSet = mSystemLevelFormSet;\r
4401\r
4402 //\r
4403 // Set Default Value for each FormSet in the maintain list.\r
4404 //\r
4405 Link = GetFirstNode (&gBrowserFormSetList);\r
4406 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4407 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
4408 Link = GetNextNode (&gBrowserFormSetList, Link);\r
4409 if (!ValidateFormSet(LocalFormSet)) {\r
4410 continue;\r
4411 }\r
4412\r
4413 mSystemLevelFormSet = LocalFormSet;\r
4414\r
4415 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
4416 }\r
4417\r
4418 mSystemLevelFormSet = OldFormSet;\r
4419 }\r
4420\r
4421 return EFI_SUCCESS;\r
4422}\r
4423\r
4424\r
4425/**\r
4426 Validate whether this question's value has changed.\r
4427\r
4428 @param FormSet FormSet data structure.\r
4429 @param Form Form data structure.\r
4430 @param Question Question to be initialized.\r
4431 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
4432\r
4433 @retval TRUE Question's value has changed.\r
4434 @retval FALSE Question's value has not changed\r
4435\r
4436**/\r
4437BOOLEAN\r
4438IsQuestionValueChanged (\r
4439 IN FORM_BROWSER_FORMSET *FormSet,\r
4440 IN FORM_BROWSER_FORM *Form,\r
4441 IN OUT FORM_BROWSER_STATEMENT *Question,\r
4442 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
4443 )\r
4444{\r
4445 EFI_HII_VALUE BackUpValue;\r
4446 CHAR8 *BackUpBuffer;\r
4447 EFI_HII_VALUE BackUpValue2;\r
4448 CHAR8 *BackUpBuffer2;\r
4449 EFI_STATUS Status;\r
4450 BOOLEAN ValueChanged;\r
4451 UINTN BufferWidth;\r
4452\r
4453 //\r
4454 // For quetion without storage, always mark it as data not changed.\r
4455 //\r
4456 if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
4457 return FALSE;\r
4458 }\r
4459\r
4460 BackUpBuffer = NULL;\r
4461 BackUpBuffer2 = NULL;\r
4462 ValueChanged = FALSE;\r
4463\r
4464 switch (Question->Operand) {\r
4465 case EFI_IFR_ORDERED_LIST_OP:\r
4466 BufferWidth = Question->StorageWidth;\r
4467 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4468 ASSERT (BackUpBuffer != NULL);\r
4469 break;\r
4470\r
4471 case EFI_IFR_STRING_OP:\r
4472 case EFI_IFR_PASSWORD_OP:\r
4473 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4474 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4475 ASSERT (BackUpBuffer != NULL);\r
4476 break;\r
4477\r
4478 default:\r
4479 BufferWidth = 0;\r
4480 break;\r
4481 }\r
4482 CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4483\r
4484 if (GetValueFrom == GetSetValueWithBothBuffer) {\r
4485 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4486 ASSERT_EFI_ERROR(Status);\r
4487\r
4488 switch (Question->Operand) {\r
4489 case EFI_IFR_ORDERED_LIST_OP:\r
4490 BufferWidth = Question->StorageWidth;\r
4491 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4492 ASSERT (BackUpBuffer2 != NULL);\r
4493 break;\r
4494\r
4495 case EFI_IFR_STRING_OP:\r
4496 case EFI_IFR_PASSWORD_OP:\r
4497 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4498 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4499 ASSERT (BackUpBuffer2 != NULL);\r
4500 break;\r
4501\r
4502 default:\r
4503 BufferWidth = 0;\r
4504 break;\r
4505 }\r
4506 CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4507\r
4508 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
4509 ASSERT_EFI_ERROR(Status);\r
4510\r
4511 if (CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4512 CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0) {\r
4513 ValueChanged = TRUE;\r
4514 }\r
4515 } else {\r
4516 Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
4517 ASSERT_EFI_ERROR(Status);\r
4518\r
4519 if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4520 CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
4521 ValueChanged = TRUE;\r
4522 }\r
4523 }\r
4524\r
4525 CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
4526 if (BackUpBuffer != NULL) {\r
4527 CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
4528 FreePool (BackUpBuffer);\r
4529 }\r
4530\r
4531 if (BackUpBuffer2 != NULL) {\r
4532 FreePool (BackUpBuffer2);\r
4533 }\r
4534\r
4535 Question->ValueChanged = ValueChanged;\r
4536\r
4537 return ValueChanged;\r
4538}\r
4539\r
4540/**\r
4541 Initialize Question's Edit copy from Storage.\r
4542\r
4543 @param Selection Selection contains the information about \r
4544 the Selection, form and formset to be displayed.\r
4545 Selection action may be updated in retrieve callback.\r
4546 If Selection is NULL, only initialize Question value.\r
4547 @param FormSet FormSet data structure.\r
4548 @param Form Form data structure.\r
4549\r
4550 @retval EFI_SUCCESS The function completed successfully.\r
4551\r
4552**/\r
4553EFI_STATUS\r
4554LoadFormConfig (\r
4555 IN OUT UI_MENU_SELECTION *Selection,\r
4556 IN FORM_BROWSER_FORMSET *FormSet,\r
4557 IN FORM_BROWSER_FORM *Form\r
4558 )\r
4559{\r
4560 EFI_STATUS Status;\r
4561 LIST_ENTRY *Link;\r
4562 FORM_BROWSER_STATEMENT *Question;\r
4563 \r
4564 Link = GetFirstNode (&Form->StatementListHead);\r
4565 while (!IsNull (&Form->StatementListHead, Link)) {\r
4566 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4567\r
4568 //\r
4569 // Initialize local copy of Value for each Question\r
4570 //\r
4571 if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
4572 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
4573 } else {\r
4574 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4575 }\r
4576 if (EFI_ERROR (Status)) {\r
4577 return Status;\r
4578 }\r
4579\r
4580 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
4581 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
4582 }\r
4583\r
4584 Link = GetNextNode (&Form->StatementListHead, Link);\r
4585 }\r
4586\r
4587 return EFI_SUCCESS;\r
4588}\r
4589\r
4590/**\r
4591 Initialize Question's Edit copy from Storage for the whole Formset.\r
4592\r
4593 @param Selection Selection contains the information about \r
4594 the Selection, form and formset to be displayed.\r
4595 Selection action may be updated in retrieve callback.\r
4596 If Selection is NULL, only initialize Question value.\r
4597 @param FormSet FormSet data structure.\r
4598\r
4599 @retval EFI_SUCCESS The function completed successfully.\r
4600\r
4601**/\r
4602EFI_STATUS\r
4603LoadFormSetConfig (\r
4604 IN OUT UI_MENU_SELECTION *Selection,\r
4605 IN FORM_BROWSER_FORMSET *FormSet\r
4606 )\r
4607{\r
4608 EFI_STATUS Status;\r
4609 LIST_ENTRY *Link;\r
4610 FORM_BROWSER_FORM *Form;\r
4611\r
4612 Link = GetFirstNode (&FormSet->FormListHead);\r
4613 while (!IsNull (&FormSet->FormListHead, Link)) {\r
4614 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
4615\r
4616 //\r
4617 // Initialize local copy of Value for each Form\r
4618 //\r
4619 Status = LoadFormConfig (Selection, FormSet, Form);\r
4620 if (EFI_ERROR (Status)) {\r
4621 return Status;\r
4622 }\r
4623\r
4624 Link = GetNextNode (&FormSet->FormListHead, Link);\r
4625 }\r
4626\r
4627 //\r
4628 // Finished question initialization.\r
4629 // \r
4630 FormSet->QuestionInited = TRUE;\r
4631\r
4632 return EFI_SUCCESS;\r
4633}\r
4634\r
4635/**\r
4636 Remove the Request element from the Config Request.\r
4637\r
4638 @param Storage Pointer to the browser storage.\r
4639 @param RequestElement The pointer to the Request element.\r
4640\r
4641**/\r
4642VOID\r
4643RemoveElement (\r
4644 IN OUT BROWSER_STORAGE *Storage,\r
4645 IN CHAR16 *RequestElement\r
4646 )\r
4647{\r
4648 CHAR16 *NewStr;\r
4649 CHAR16 *DestStr;\r
4650\r
4651 ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
4652\r
4653 NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
4654\r
4655 if (NewStr == NULL) {\r
4656 return;\r
4657 }\r
4658\r
4659 //\r
4660 // Remove this element from this ConfigRequest.\r
4661 //\r
4662 DestStr = NewStr;\r
4663 NewStr += StrLen (RequestElement);\r
4664 CopyMem (DestStr, NewStr, StrSize (NewStr));\r
4665 \r
4666 Storage->SpareStrLen += StrLen (RequestElement); \r
4667}\r
4668\r
4669/**\r
4670 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
4671\r
4672 @param Storage Pointer to the formset storage.\r
4673 @param ConfigRequest The pointer to the Request element.\r
4674\r
4675**/\r
4676VOID\r
4677RemoveConfigRequest (\r
4678 FORMSET_STORAGE *Storage,\r
4679 CHAR16 *ConfigRequest\r
4680 )\r
4681{\r
4682 CHAR16 *RequestElement;\r
4683 CHAR16 *NextRequestElement;\r
4684 CHAR16 *SearchKey;\r
4685\r
4686 //\r
4687 // No request element in it, just return.\r
4688 //\r
4689 if (ConfigRequest == NULL) {\r
4690 return;\r
4691 }\r
4692\r
4693 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4694 //\r
4695 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
4696 //\r
4697 SearchKey = L"&";\r
4698 } else {\r
4699 //\r
4700 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
4701 //\r
4702 SearchKey = L"&OFFSET";\r
4703 }\r
4704\r
4705 //\r
4706 // Find SearchKey storage\r
4707 //\r
4708 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4709 RequestElement = StrStr (ConfigRequest, L"PATH");\r
4710 ASSERT (RequestElement != NULL);\r
4711 RequestElement = StrStr (RequestElement, SearchKey); \r
4712 } else {\r
4713 RequestElement = StrStr (ConfigRequest, SearchKey);\r
4714 }\r
4715\r
4716 while (RequestElement != NULL) {\r
4717 //\r
4718 // +1 to avoid find header itself.\r
4719 //\r
4720 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
4721\r
4722 //\r
4723 // The last Request element in configRequest string.\r
4724 //\r
4725 if (NextRequestElement != NULL) {\r
4726 //\r
4727 // Replace "&" with '\0'.\r
4728 //\r
4729 *NextRequestElement = L'\0';\r
4730 }\r
4731\r
4732 RemoveElement (Storage->BrowserStorage, RequestElement);\r
4733\r
4734 if (NextRequestElement != NULL) {\r
4735 //\r
4736 // Restore '&' with '\0' for later used.\r
4737 //\r
4738 *NextRequestElement = L'&';\r
4739 }\r
4740\r
4741 RequestElement = NextRequestElement;\r
4742 }\r
4743\r
4744 //\r
4745 // If no request element remain, just remove the ConfigRequest string.\r
4746 //\r
4747 if (StrCmp (Storage->BrowserStorage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
4748 FreePool (Storage->BrowserStorage->ConfigRequest);\r
4749 Storage->BrowserStorage->ConfigRequest = NULL;\r
4750 Storage->BrowserStorage->SpareStrLen = 0;\r
4751 }\r
4752}\r
4753\r
4754/**\r
4755 Base on the current formset info, clean the ConfigRequest string in browser storage.\r
4756\r
4757 @param FormSet Pointer of the FormSet\r
4758\r
4759**/\r
4760VOID\r
4761CleanBrowserStorage (\r
4762 IN OUT FORM_BROWSER_FORMSET *FormSet\r
4763 )\r
4764{\r
4765 LIST_ENTRY *Link;\r
4766 FORMSET_STORAGE *Storage;\r
4767\r
4768 Link = GetFirstNode (&FormSet->StorageListHead);\r
4769 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4770 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
4771 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4772\r
4773 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
4774 if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
4775 continue;\r
4776 }\r
4777\r
4778 RemoveConfigRequest (Storage, Storage->ConfigRequest);\r
4779 } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
4780 Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4781 if (Storage->BrowserStorage->ConfigRequest != NULL) { \r
4782 FreePool (Storage->BrowserStorage->ConfigRequest);\r
4783 Storage->BrowserStorage->ConfigRequest = NULL;\r
4784 }\r
4785 Storage->BrowserStorage->Initialized = FALSE;\r
4786 }\r
4787 }\r
4788}\r
4789\r
4790/**\r
4791 Check whether current element in the ConfigReqeust string.\r
4792\r
4793 @param BrowserStorage Storage which includes ConfigReqeust.\r
4794 @param RequestElement New element need to check.\r
4795\r
4796 @retval TRUE The Element is in the ConfigReqeust string.\r
4797 @retval FALSE The Element not in the configReqeust String.\r
4798\r
4799**/\r
4800BOOLEAN \r
4801ElementValidation (\r
4802 BROWSER_STORAGE *BrowserStorage,\r
4803 CHAR16 *RequestElement\r
4804 )\r
4805{\r
4806 return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
4807}\r
4808\r
4809/**\r
4810 Append the Request element to the Config Request.\r
4811\r
4812 @param ConfigRequest Current ConfigRequest info.\r
4813 @param SpareStrLen Current remain free buffer for config reqeust.\r
4814 @param RequestElement New Request element.\r
4815\r
4816**/\r
4817VOID\r
4818AppendConfigRequest (\r
4819 IN OUT CHAR16 **ConfigRequest,\r
4820 IN OUT UINTN *SpareStrLen,\r
4821 IN CHAR16 *RequestElement\r
4822 )\r
4823{\r
4824 CHAR16 *NewStr;\r
4825 UINTN StringSize;\r
4826 UINTN StrLength;\r
4827\r
4828 StrLength = StrLen (RequestElement);\r
4829\r
4830 //\r
4831 // Append <RequestElement> to <ConfigRequest>\r
4832 //\r
4833 if (StrLength > *SpareStrLen) {\r
4834 //\r
4835 // Old String buffer is not sufficient for RequestElement, allocate a new one\r
4836 //\r
4837 StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
4838 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
4839 ASSERT (NewStr != NULL);\r
4840\r
4841 if (*ConfigRequest != NULL) {\r
4842 CopyMem (NewStr, *ConfigRequest, StringSize);\r
4843 FreePool (*ConfigRequest);\r
4844 }\r
4845 *ConfigRequest = NewStr;\r
4846 *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
4847 }\r
4848\r
4849 StrCat (*ConfigRequest, RequestElement);\r
4850 *SpareStrLen -= StrLength;\r
4851}\r
4852\r
4853/**\r
4854 Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
4855\r
4856 @param Storage Form set Storage.\r
4857 @param Request The input request string.\r
4858 @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
4859\r
4860 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
4861 @retval FALSE All elements covered by current used elements.\r
4862\r
4863**/\r
4864BOOLEAN \r
4865ConfigRequestAdjust (\r
4866 IN BROWSER_STORAGE *Storage,\r
4867 IN CHAR16 *Request,\r
4868 IN BOOLEAN RespString\r
4869 )\r
4870{\r
4871 CHAR16 *RequestElement;\r
4872 CHAR16 *NextRequestElement;\r
4873 CHAR16 *NextElementBakup;\r
4874 CHAR16 *SearchKey;\r
4875 CHAR16 *ValueKey;\r
4876 BOOLEAN RetVal;\r
4877 CHAR16 *ConfigRequest;\r
4878\r
4879 RetVal = FALSE;\r
4880 NextElementBakup = NULL;\r
4881 ValueKey = NULL;\r
4882\r
4883 if (Request != NULL) {\r
4884 ConfigRequest = Request;\r
4885 } else {\r
4886 ConfigRequest = Storage->ConfigRequest;\r
4887 }\r
4888\r
4889 if (Storage->ConfigRequest == NULL) {\r
4890 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
4891 return TRUE;\r
4892 }\r
4893\r
4894 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4895 //\r
4896 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
4897 //\r
4898 SearchKey = L"&";\r
4899 } else {\r
4900 //\r
4901 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
4902 //\r
4903 SearchKey = L"&OFFSET";\r
4904 ValueKey = L"&VALUE";\r
4905 }\r
4906\r
4907 //\r
4908 // Find SearchKey storage\r
4909 //\r
4910 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4911 RequestElement = StrStr (ConfigRequest, L"PATH");\r
4912 ASSERT (RequestElement != NULL);\r
4913 RequestElement = StrStr (RequestElement, SearchKey); \r
4914 } else {\r
4915 RequestElement = StrStr (ConfigRequest, SearchKey);\r
4916 }\r
4917\r
4918 while (RequestElement != NULL) {\r
4919\r
4920 //\r
4921 // +1 to avoid find header itself.\r
4922 //\r
4923 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
4924\r
4925 //\r
4926 // The last Request element in configRequest string.\r
4927 //\r
4928 if (NextRequestElement != NULL) {\r
4929 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4930 NextElementBakup = NextRequestElement;\r
4931 NextRequestElement = StrStr (RequestElement, ValueKey);\r
4932 ASSERT (NextRequestElement != NULL);\r
4933 }\r
4934 //\r
4935 // Replace "&" with '\0'.\r
4936 //\r
4937 *NextRequestElement = L'\0';\r
4938 } else {\r
4939 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4940 NextElementBakup = NextRequestElement;\r
4941 NextRequestElement = StrStr (RequestElement, ValueKey);\r
4942 ASSERT (NextRequestElement != NULL);\r
4943 //\r
4944 // Replace "&" with '\0'.\r
4945 //\r
4946 *NextRequestElement = L'\0';\r
4947 }\r
4948 }\r
4949 \r
4950 if (!ElementValidation (Storage, RequestElement)) {\r
4951 //\r
4952 // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
4953 //\r
4954 AppendConfigRequest(&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
4955 RetVal = TRUE;\r
4956 }\r
4957\r
4958 if (NextRequestElement != NULL) {\r
4959 //\r
4960 // Restore '&' with '\0' for later used.\r
4961 //\r
4962 *NextRequestElement = L'&';\r
4963 }\r
4964\r
4965 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4966 RequestElement = NextElementBakup;\r
4967 } else {\r
4968 RequestElement = NextRequestElement;\r
4969 }\r
4970 }\r
4971\r
4972 return RetVal;\r
4973}\r
4974\r
4975/**\r
4976 Fill storage's edit copy with settings requested from Configuration Driver.\r
4977\r
4978 @param FormSet FormSet data structure.\r
4979 @param Storage Buffer Storage.\r
4980\r
4981**/\r
4982VOID\r
4983LoadStorage (\r
4984 IN FORM_BROWSER_FORMSET *FormSet,\r
4985 IN FORMSET_STORAGE *Storage\r
4986 )\r
4987{\r
4988 EFI_STATUS Status;\r
4989 EFI_STRING Progress;\r
4990 EFI_STRING Result;\r
4991 CHAR16 *StrPtr;\r
4992 EFI_STRING ConfigRequest;\r
4993 UINTN StrLen;\r
4994\r
4995 ConfigRequest = NULL;\r
4996\r
4997 switch (Storage->BrowserStorage->Type) {\r
4998 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
4999 return;\r
5000\r
5001 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
5002 if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
5003 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
5004 return;\r
5005 }\r
5006 break;\r
5007\r
5008 case EFI_HII_VARSTORE_BUFFER:\r
5009 case EFI_HII_VARSTORE_NAME_VALUE:\r
5010 //\r
5011 // Skip if there is no RequestElement.\r
5012 //\r
5013 if (Storage->ElementCount == 0) {\r
5014 return;\r
5015 }\r
5016\r
5017 //\r
5018 // Just update the ConfigRequest, if storage already initialized. \r
5019 //\r
5020 if (Storage->BrowserStorage->Initialized) {\r
5021 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
5022 return;\r
5023 }\r
5024\r
5025 Storage->BrowserStorage->Initialized = TRUE;\r
5026 break;\r
5027\r
5028 default:\r
5029 return;\r
5030 }\r
5031\r
5032 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
5033 //\r
5034 // Create the config request string to get all fields for this storage.\r
5035 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
5036 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
5037 //\r
5038 StrLen = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
5039 ConfigRequest = AllocateZeroPool (StrLen);\r
5040 ASSERT (ConfigRequest != NULL);\r
5041 UnicodeSPrint (\r
5042 ConfigRequest, \r
5043 StrLen, \r
5044 L"%s&OFFSET=0&WIDTH=%04x", \r
5045 Storage->ConfigHdr,\r
5046 Storage->BrowserStorage->Size);\r
5047 } else {\r
5048 ConfigRequest = Storage->ConfigRequest;\r
5049 }\r
5050\r
5051 //\r
5052 // Request current settings from Configuration Driver\r
5053 //\r
5054 Status = mHiiConfigRouting->ExtractConfig (\r
5055 mHiiConfigRouting,\r
5056 ConfigRequest,\r
5057 &Progress,\r
5058 &Result\r
5059 );\r
5060\r
5061 //\r
5062 // If get value fail, extract default from IFR binary\r
5063 //\r
5064 if (EFI_ERROR (Status)) {\r
5065 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE, TRUE);\r
5066 } else {\r
5067 //\r
5068 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
5069 //\r
5070 StrPtr = StrStr (Result, L"&GUID=");\r
5071 if (StrPtr != NULL) {\r
5072 *StrPtr = L'\0';\r
5073 }\r
5074 \r
5075 Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
5076 FreePool (Result);\r
5077 }\r
5078\r
5079 Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
5080\r
5081 //\r
5082 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
5083 //\r
5084 SynchronizeStorage(Storage->BrowserStorage, NULL, TRUE);\r
5085\r
5086 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
5087 if (ConfigRequest != NULL) {\r
5088 FreePool (ConfigRequest);\r
5089 }\r
5090 }\r
5091}\r
5092\r
5093/**\r
5094 Get Value changed status from old question.\r
5095\r
5096 @param NewFormSet FormSet data structure.\r
5097 @param OldQuestion Old question which has value changed.\r
5098\r
5099**/\r
5100VOID\r
5101SyncStatusForQuestion (\r
5102 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5103 IN FORM_BROWSER_STATEMENT *OldQuestion\r
5104 )\r
5105{\r
5106 LIST_ENTRY *Link;\r
5107 LIST_ENTRY *QuestionLink;\r
5108 FORM_BROWSER_FORM *Form;\r
5109 FORM_BROWSER_STATEMENT *Question;\r
5110\r
5111 //\r
5112 // For each form in one formset.\r
5113 //\r
5114 Link = GetFirstNode (&NewFormSet->FormListHead);\r
5115 while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
5116 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5117 Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
5118\r
5119 //\r
5120 // for each question in one form.\r
5121 //\r
5122 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5123 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5124 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5125 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5126\r
5127 if (Question->QuestionId == OldQuestion->QuestionId) {\r
5128 Question->ValueChanged = TRUE;\r
5129 return;\r
5130 }\r
5131 }\r
5132 }\r
5133}\r
5134\r
5135/**\r
5136 Get Value changed status from old formset.\r
5137\r
5138 @param NewFormSet FormSet data structure.\r
5139 @param OldFormSet FormSet data structure.\r
5140\r
5141**/\r
5142VOID\r
5143SyncStatusForFormSet (\r
5144 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5145 IN FORM_BROWSER_FORMSET *OldFormSet\r
5146 )\r
5147{\r
5148 LIST_ENTRY *Link;\r
5149 LIST_ENTRY *QuestionLink;\r
5150 FORM_BROWSER_FORM *Form;\r
5151 FORM_BROWSER_STATEMENT *Question;\r
5152\r
5153 //\r
5154 // For each form in one formset.\r
5155 //\r
5156 Link = GetFirstNode (&OldFormSet->FormListHead);\r
5157 while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
5158 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5159 Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
5160\r
5161 //\r
5162 // for each question in one form.\r
5163 //\r
5164 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5165 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5166 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5167 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5168\r
5169 if (!Question->ValueChanged) {\r
5170 continue;\r
5171 }\r
5172\r
5173 //\r
5174 // Find the same question in new formset and update the value changed flag.\r
5175 //\r
5176 SyncStatusForQuestion (NewFormSet, Question);\r
5177 }\r
5178 }\r
5179}\r
5180\r
5181/**\r
5182 Get current setting of Questions.\r
5183\r
5184 @param FormSet FormSet data structure.\r
5185\r
5186**/\r
5187VOID\r
5188InitializeCurrentSetting (\r
5189 IN OUT FORM_BROWSER_FORMSET *FormSet\r
5190 )\r
5191{\r
5192 LIST_ENTRY *Link;\r
5193 FORMSET_STORAGE *Storage;\r
5194 FORM_BROWSER_FORMSET *OldFormSet;\r
5195\r
5196 //\r
5197 // Try to find pre FormSet in the maintain backup list.\r
5198 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
5199 //\r
5200 OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
5201 if (OldFormSet != NULL) {\r
5202 SyncStatusForFormSet (FormSet, OldFormSet);\r
5203 RemoveEntryList (&OldFormSet->Link);\r
5204 DestroyFormSet (OldFormSet);\r
5205 }\r
5206 InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
5207\r
5208 //\r
5209 // Extract default from IFR binary for no storage questions.\r
5210 // \r
5211 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE, FALSE);\r
5212\r
5213 //\r
5214 // Request current settings from Configuration Driver\r
5215 //\r
5216 Link = GetFirstNode (&FormSet->StorageListHead);\r
5217 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
5218 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
5219\r
5220 LoadStorage (FormSet, Storage);\r
5221\r
5222 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
5223 }\r
5224}\r
5225\r
5226\r
5227/**\r
5228 Fetch the Ifr binary data of a FormSet.\r
5229\r
5230 @param Handle PackageList Handle\r
5231 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5232 specified (NULL or zero GUID), take the first\r
5233 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5234 found in package list.\r
5235 On output, GUID of the formset found(if not NULL).\r
5236 @param BinaryLength The length of the FormSet IFR binary.\r
5237 @param BinaryData The buffer designed to receive the FormSet.\r
5238\r
5239 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
5240 BufferLength was updated.\r
5241 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
5242 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
5243 be found with the requested FormId.\r
5244\r
5245**/\r
5246EFI_STATUS\r
5247GetIfrBinaryData (\r
5248 IN EFI_HII_HANDLE Handle,\r
5249 IN OUT EFI_GUID *FormSetGuid,\r
5250 OUT UINTN *BinaryLength,\r
5251 OUT UINT8 **BinaryData\r
5252 )\r
5253{\r
5254 EFI_STATUS Status;\r
5255 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
5256 UINTN BufferSize;\r
5257 UINT8 *Package;\r
5258 UINT8 *OpCodeData;\r
5259 UINT32 Offset;\r
5260 UINT32 Offset2;\r
5261 UINT32 PackageListLength;\r
5262 EFI_HII_PACKAGE_HEADER PackageHeader;\r
5263 UINT8 Index;\r
5264 UINT8 NumberOfClassGuid;\r
5265 BOOLEAN ClassGuidMatch;\r
5266 EFI_GUID *ClassGuid;\r
5267 EFI_GUID *ComparingGuid;\r
5268\r
5269 OpCodeData = NULL;\r
5270 Package = NULL;\r
5271 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
5272\r
5273 //\r
5274 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
5275 //\r
5276 if (FormSetGuid == NULL) {\r
5277 ComparingGuid = &gZeroGuid;\r
5278 } else {\r
5279 ComparingGuid = FormSetGuid;\r
5280 }\r
5281\r
5282 //\r
5283 // Get HII PackageList\r
5284 //\r
5285 BufferSize = 0;\r
5286 HiiPackageList = NULL;\r
5287 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5288 if (Status == EFI_BUFFER_TOO_SMALL) {\r
5289 HiiPackageList = AllocatePool (BufferSize);\r
5290 ASSERT (HiiPackageList != NULL);\r
5291\r
5292 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5293 }\r
5294 if (EFI_ERROR (Status)) {\r
5295 return Status;\r
5296 }\r
5297 ASSERT (HiiPackageList != NULL);\r
5298\r
5299 //\r
5300 // Get Form package from this HII package List\r
5301 //\r
5302 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
5303 Offset2 = 0;\r
5304 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
5305\r
5306 ClassGuidMatch = FALSE;\r
5307 while (Offset < PackageListLength) {\r
5308 Package = ((UINT8 *) HiiPackageList) + Offset;\r
5309 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
5310\r
5311 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
5312 //\r
5313 // Search FormSet in this Form Package\r
5314 //\r
5315 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
5316 while (Offset2 < PackageHeader.Length) {\r
5317 OpCodeData = Package + Offset2;\r
5318\r
5319 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
5320 //\r
5321 // Try to compare against formset GUID\r
5322 //\r
5323 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
5324 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
5325 break;\r
5326 }\r
5327\r
5328 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
5329 //\r
5330 // Try to compare against formset class GUID\r
5331 //\r
5332 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
5333 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
5334 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
5335 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
5336 ClassGuidMatch = TRUE;\r
5337 break;\r
5338 }\r
5339 }\r
5340 if (ClassGuidMatch) {\r
5341 break;\r
5342 }\r
5343 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
5344 ClassGuidMatch = TRUE;\r
5345 break;\r
5346 }\r
5347 }\r
5348\r
5349 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
5350 }\r
5351\r
5352 if (Offset2 < PackageHeader.Length) {\r
5353 //\r
5354 // Target formset found\r
5355 //\r
5356 break;\r
5357 }\r
5358 }\r
5359\r
5360 Offset += PackageHeader.Length;\r
5361 }\r
5362\r
5363 if (Offset >= PackageListLength) {\r
5364 //\r
5365 // Form package not found in this Package List\r
5366 //\r
5367 FreePool (HiiPackageList);\r
5368 return EFI_NOT_FOUND;\r
5369 }\r
5370\r
5371 if (FormSetGuid != NULL) {\r
5372 //\r
5373 // Return the FormSet GUID\r
5374 //\r
5375 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
5376 }\r
5377\r
5378 //\r
5379 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
5380 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
5381 // of the Form Package.\r
5382 //\r
5383 *BinaryLength = PackageHeader.Length - Offset2;\r
5384 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
5385\r
5386 FreePool (HiiPackageList);\r
5387\r
5388 if (*BinaryData == NULL) {\r
5389 return EFI_OUT_OF_RESOURCES;\r
5390 }\r
5391\r
5392 return EFI_SUCCESS;\r
5393}\r
5394\r
5395\r
5396/**\r
5397 Initialize the internal data structure of a FormSet.\r
5398\r
5399 @param Handle PackageList Handle\r
5400 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5401 specified (NULL or zero GUID), take the first\r
5402 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5403 found in package list.\r
5404 On output, GUID of the formset found(if not NULL).\r
5405 @param FormSet FormSet data structure.\r
5406\r
5407 @retval EFI_SUCCESS The function completed successfully.\r
5408 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
5409\r
5410**/\r
5411EFI_STATUS\r
5412InitializeFormSet (\r
5413 IN EFI_HII_HANDLE Handle,\r
5414 IN OUT EFI_GUID *FormSetGuid,\r
5415 OUT FORM_BROWSER_FORMSET *FormSet\r
5416 )\r
5417{\r
5418 EFI_STATUS Status;\r
5419 EFI_HANDLE DriverHandle;\r
5420\r
5421 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
5422 if (EFI_ERROR (Status)) {\r
5423 return Status;\r
5424 }\r
5425\r
5426 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
5427 FormSet->HiiHandle = Handle;\r
5428 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
5429 FormSet->QuestionInited = FALSE;\r
5430\r
5431 //\r
5432 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
5433 //\r
5434 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
5435 if (EFI_ERROR (Status)) {\r
5436 return Status;\r
5437 }\r
5438 FormSet->DriverHandle = DriverHandle;\r
5439 Status = gBS->HandleProtocol (\r
5440 DriverHandle,\r
5441 &gEfiHiiConfigAccessProtocolGuid,\r
5442 (VOID **) &FormSet->ConfigAccess\r
5443 );\r
5444 if (EFI_ERROR (Status)) {\r
5445 //\r
5446 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
5447 // list, then there will be no configuration action required\r
5448 //\r
5449 FormSet->ConfigAccess = NULL;\r
5450 }\r
5451\r
5452 //\r
5453 // Parse the IFR binary OpCodes\r
5454 //\r
5455 Status = ParseOpCodes (FormSet);\r
5456\r
5457 return Status;\r
5458}\r
5459\r
5460\r
5461/**\r
5462 Save globals used by previous call to SendForm(). SendForm() may be called from \r
5463 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
5464 So, save globals of previous call to SendForm() and restore them upon exit.\r
5465\r
5466**/\r
5467VOID\r
5468SaveBrowserContext (\r
5469 VOID\r
5470 )\r
5471{\r
5472 BROWSER_CONTEXT *Context;\r
5473 FORM_ENTRY_INFO *MenuList;\r
5474\r
5475 gBrowserContextCount++;\r
5476 if (gBrowserContextCount == 1) {\r
5477 //\r
5478 // This is not reentry of SendForm(), no context to save\r
5479 //\r
5480 return;\r
5481 }\r
5482\r
5483 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
5484 ASSERT (Context != NULL);\r
5485\r
5486 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
5487\r
5488 //\r
5489 // Save FormBrowser context\r
5490 //\r
5491 Context->Selection = gCurrentSelection;\r
5492 Context->ResetRequired = gResetRequired;\r
5493 Context->ExitRequired = gExitRequired;\r
5494 Context->HiiHandle = mCurrentHiiHandle;\r
5495 Context->FormId = mCurrentFormId;\r
5496 CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
5497\r
5498 //\r
5499 // Save the menu history data.\r
5500 //\r
5501 InitializeListHead(&Context->FormHistoryList);\r
5502 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
5503 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
5504 RemoveEntryList (&MenuList->Link);\r
5505\r
5506 InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
5507 }\r
5508\r
5509 //\r
5510 // Insert to FormBrowser context list\r
5511 //\r
5512 InsertHeadList (&gBrowserContextList, &Context->Link);\r
5513}\r
5514\r
5515\r
5516/**\r
5517 Restore globals used by previous call to SendForm().\r
5518\r
5519**/\r
5520VOID\r
5521RestoreBrowserContext (\r
5522 VOID\r
5523 )\r
5524{\r
5525 LIST_ENTRY *Link;\r
5526 BROWSER_CONTEXT *Context;\r
5527 FORM_ENTRY_INFO *MenuList;\r
5528\r
5529 ASSERT (gBrowserContextCount != 0);\r
5530 gBrowserContextCount--;\r
5531 if (gBrowserContextCount == 0) {\r
5532 //\r
5533 // This is not reentry of SendForm(), no context to restore\r
5534 //\r
5535 return;\r
5536 }\r
5537\r
5538 ASSERT (!IsListEmpty (&gBrowserContextList));\r
5539\r
5540 Link = GetFirstNode (&gBrowserContextList);\r
5541 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
5542\r
5543 //\r
5544 // Restore FormBrowser context\r
5545 //\r
5546 gCurrentSelection = Context->Selection;\r
5547 gResetRequired = Context->ResetRequired;\r
5548 gExitRequired = Context->ExitRequired;\r
5549 mCurrentHiiHandle = Context->HiiHandle;\r
5550 mCurrentFormId = Context->FormId;\r
5551 CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
5552\r
5553 //\r
5554 // Restore the menu history data.\r
5555 //\r
5556 while (!IsListEmpty (&Context->FormHistoryList)) {\r
5557 MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
5558 RemoveEntryList (&MenuList->Link);\r
5559\r
5560 InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
5561 }\r
5562\r
5563 //\r
5564 // Remove from FormBrowser context list\r
5565 //\r
5566 RemoveEntryList (&Context->Link);\r
5567 gBS->FreePool (Context);\r
5568}\r
5569\r
5570/**\r
5571 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
5572 \r
5573 @param Handle The Hii Handle.\r
5574 \r
5575 @return the found FormSet context. If no found, NULL will return.\r
5576\r
5577**/\r
5578FORM_BROWSER_FORMSET * \r
5579GetFormSetFromHiiHandle (\r
5580 EFI_HII_HANDLE Handle\r
5581 )\r
5582{\r
5583 LIST_ENTRY *Link;\r
5584 FORM_BROWSER_FORMSET *FormSet;\r
5585\r
5586 Link = GetFirstNode (&gBrowserFormSetList);\r
5587 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5588 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
5589 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5590 if (!ValidateFormSet(FormSet)) {\r
5591 continue;\r
5592 }\r
5593 if (FormSet->HiiHandle == Handle) {\r
5594 return FormSet;\r
5595 }\r
5596 }\r
5597 \r
5598 return NULL;\r
5599}\r
5600\r
5601/**\r
5602 Check whether the input HII handle is the FormSet that is being used.\r
5603 \r
5604 @param Handle The Hii Handle.\r
5605 \r
5606 @retval TRUE HII handle is being used.\r
5607 @retval FALSE HII handle is not being used.\r
5608\r
5609**/\r
5610BOOLEAN\r
5611IsHiiHandleInBrowserContext (\r
5612 EFI_HII_HANDLE Handle\r
5613 )\r
5614{\r
5615 LIST_ENTRY *Link;\r
5616 BROWSER_CONTEXT *Context;\r
5617\r
5618 //\r
5619 // HiiHandle is Current FormSet.\r
5620 //\r
5621 if (mCurrentHiiHandle == Handle) {\r
5622 return TRUE;\r
5623 }\r
5624\r
5625 //\r
5626 // Check whether HiiHandle is in BrowserContext.\r
5627 //\r
5628 Link = GetFirstNode (&gBrowserContextList);\r
5629 while (!IsNull (&gBrowserContextList, Link)) {\r
5630 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
5631 if (Context->HiiHandle == Handle) {\r
5632 //\r
5633 // HiiHandle is in BrowserContext\r
5634 //\r
5635 return TRUE;\r
5636 }\r
5637 Link = GetNextNode (&gBrowserContextList, Link);\r
5638 }\r
5639 \r
5640 return FALSE;\r
5641}\r
5642\r
5643/**\r
5644 Perform Password check. \r
5645 Passwork may be encrypted by driver that requires the specific check.\r
5646 \r
5647 @param Form Form where Password Statement is in.\r
5648 @param Statement Password statement\r
5649 @param PasswordString Password string to be checked. It may be NULL.\r
5650 NULL means to restore password.\r
5651 "" string can be used to checked whether old password does exist.\r
5652 \r
5653 @return Status Status of Password check.\r
5654**/\r
5655EFI_STATUS\r
5656EFIAPI\r
5657PasswordCheck (\r
5658 IN FORM_DISPLAY_ENGINE_FORM *Form,\r
5659 IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
5660 IN EFI_STRING PasswordString OPTIONAL\r
5661 )\r
5662{\r
5663 EFI_STATUS Status;\r
5664 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
5665 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
5666 EFI_IFR_TYPE_VALUE IfrTypeValue;\r
5667 FORM_BROWSER_STATEMENT *Question;\r
5668\r
5669 ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
5670 Question = GetBrowserStatement(Statement);\r
5671 ASSERT (Question != NULL);\r
5672\r
5673 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
5674 if (ConfigAccess == NULL) {\r
5675 return EFI_UNSUPPORTED;\r
5676 }\r
5677 } else {\r
5678 if (PasswordString == NULL) {\r
5679 return EFI_SUCCESS;\r
5680 } \r
5681\r
5682 //\r
5683 // Check whether has preexisted password.\r
5684 //\r
5685 if (PasswordString[0] == 0) {\r
5686 if (*((CHAR16 *) Question->BufferValue) == 0) {\r
5687 return EFI_SUCCESS;\r
5688 } else {\r
5689 return EFI_NOT_READY;\r
5690 }\r
5691 }\r
5692\r
5693 //\r
5694 // Check whether the input password is same as preexisted password.\r
5695 //\r
5696 if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
5697 return EFI_SUCCESS;\r
5698 } else {\r
5699 return EFI_NOT_READY;\r
5700 }\r
5701 }\r
5702 \r
5703 //\r
5704 // Prepare password string in HII database\r
5705 //\r
5706 if (PasswordString != NULL) {\r
5707 IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
5708 } else {\r
5709 IfrTypeValue.string = 0;\r
5710 }\r
5711\r
5712 //\r
5713 // Send password to Configuration Driver for validation\r
5714 //\r
5715 Status = ConfigAccess->Callback (\r
5716 ConfigAccess,\r
5717 EFI_BROWSER_ACTION_CHANGING,\r
5718 Question->QuestionId,\r
5719 Question->HiiValue.Type,\r
5720 &IfrTypeValue,\r
5721 &ActionRequest\r
5722 );\r
5723\r
5724 //\r
5725 // Remove password string from HII database\r
5726 //\r
5727 if (PasswordString != NULL) {\r
5728 DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
5729 }\r
5730\r
5731 return Status;\r
5732}\r
5733\r
5734/**\r
5735 Find the registered HotKey based on KeyData.\r
5736 \r
5737 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
5738 information for the hot key.\r
5739\r
5740 @return The registered HotKey context. If no found, NULL will return.\r
5741**/\r
5742BROWSER_HOT_KEY *\r
5743GetHotKeyFromRegisterList (\r
5744 IN EFI_INPUT_KEY *KeyData\r
5745 )\r
5746{\r
5747 LIST_ENTRY *Link;\r
5748 BROWSER_HOT_KEY *HotKey;\r
5749\r
5750 Link = GetFirstNode (&gBrowserHotKeyList);\r
5751 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
5752 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
5753 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
5754 return HotKey;\r
5755 }\r
5756 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
5757 }\r
5758 \r
5759 return NULL;\r
5760}\r
5761\r
5762/**\r
5763 Configure what scope the hot key will impact.\r
5764 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
5765 If no scope is set, the default scope will be FormSet level.\r
5766 After all registered hot keys are removed, previous Scope can reset to another level.\r
5767 \r
5768 @param[in] Scope Scope level to be set. \r
5769 \r
5770 @retval EFI_SUCCESS Scope is set correctly.\r
5771 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
5772 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
5773\r
5774**/\r
5775EFI_STATUS\r
5776EFIAPI\r
5777SetScope (\r
5778 IN BROWSER_SETTING_SCOPE Scope\r
5779 )\r
5780{\r
5781 if (Scope >= MaxLevel) {\r
5782 return EFI_INVALID_PARAMETER;\r
5783 }\r
5784\r
5785 //\r
5786 // When no hot key registered in system or on the first setting,\r
5787 // Scope can be set.\r
5788 //\r
5789 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
5790 gBrowserSettingScope = Scope;\r
5791 mBrowserScopeFirstSet = FALSE;\r
5792 } else if (Scope != gBrowserSettingScope) {\r
5793 return EFI_UNSUPPORTED;\r
5794 }\r
5795\r
5796 return EFI_SUCCESS;\r
5797}\r
5798\r
5799/**\r
5800 Register the hot key with its browser action, or unregistered the hot key.\r
5801 Only support hot key that is not printable character (control key, function key, etc.).\r
5802 If the action value is zero, the hot key will be unregistered if it has been registered.\r
5803 If the same hot key has been registered, the new action and help string will override the previous ones.\r
5804 \r
5805 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
5806 information for the hot key. Its type is EFI_INPUT_KEY to \r
5807 be supported by all ConsoleIn devices.\r
5808 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
5809 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
5810 @param[in] HelpString Help string that describes the hot key information.\r
5811 Its value may be NULL for the unregistered hot key.\r
5812 \r
5813 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
5814 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
5815 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
5816 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
5817**/\r
5818EFI_STATUS\r
5819EFIAPI\r
5820RegisterHotKey (\r
5821 IN EFI_INPUT_KEY *KeyData,\r
5822 IN UINT32 Action,\r
5823 IN UINT16 DefaultId,\r
5824 IN EFI_STRING HelpString OPTIONAL\r
5825 )\r
5826{\r
5827 BROWSER_HOT_KEY *HotKey;\r
5828\r
5829 //\r
5830 // Check input parameters.\r
5831 //\r
5832 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
5833 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
5834 return EFI_INVALID_PARAMETER;\r
5835 }\r
5836\r
5837 //\r
5838 // Check whether the input KeyData is in BrowserHotKeyList.\r
5839 //\r
5840 HotKey = GetHotKeyFromRegisterList (KeyData);\r
5841 \r
5842 //\r
5843 // Unregister HotKey\r
5844 //\r
5845 if (Action == BROWSER_ACTION_UNREGISTER) {\r
5846 if (HotKey != NULL) {\r
5847 //\r
5848 // The registered HotKey is found. \r
5849 // Remove it from List, and free its resource.\r
5850 //\r
5851 RemoveEntryList (&HotKey->Link);\r
5852 FreePool (HotKey->KeyData);\r
5853 FreePool (HotKey->HelpString);\r
5854 return EFI_SUCCESS;\r
5855 } else {\r
5856 //\r
5857 // The registered HotKey is not found. \r
5858 //\r
5859 return EFI_NOT_FOUND;\r
5860 }\r
5861 }\r
5862 \r
5863 //\r
5864 // Register HotKey into List.\r
5865 //\r
5866 if (HotKey == NULL) {\r
5867 //\r
5868 // Create new Key, and add it into List.\r
5869 //\r
5870 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
5871 ASSERT (HotKey != NULL);\r
5872 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
5873 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
5874 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
5875 }\r
5876\r
5877 //\r
5878 // Fill HotKey information.\r
5879 //\r
5880 HotKey->Action = Action;\r
5881 HotKey->DefaultId = DefaultId;\r
5882 if (HotKey->HelpString != NULL) {\r
5883 FreePool (HotKey->HelpString);\r
5884 }\r
5885 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
5886\r
5887 return EFI_SUCCESS;\r
5888}\r
5889\r
5890/**\r
5891 Register Exit handler function. \r
5892 When more than one handler function is registered, the latter one will override the previous one. \r
5893 When NULL handler is specified, the previous Exit handler will be unregistered. \r
5894 \r
5895 @param[in] Handler Pointer to handler function. \r
5896\r
5897**/\r
5898VOID\r
5899EFIAPI\r
5900RegiserExitHandler (\r
5901 IN EXIT_HANDLER Handler\r
5902 )\r
5903{\r
5904 ExitHandlerFunction = Handler;\r
5905 return;\r
5906}\r
5907\r
5908/**\r
5909 Check whether the browser data has been modified.\r
5910\r
5911 @retval TRUE Browser data is modified.\r
5912 @retval FALSE No browser data is modified.\r
5913\r
5914**/\r
5915BOOLEAN\r
5916EFIAPI\r
5917IsBrowserDataModified (\r
5918 VOID\r
5919 )\r
5920{\r
5921 LIST_ENTRY *Link;\r
5922 FORM_BROWSER_FORMSET *FormSet;\r
5923\r
5924 switch (gBrowserSettingScope) {\r
5925 case FormLevel:\r
5926 if (gCurrentSelection == NULL) {\r
5927 return FALSE;\r
5928 }\r
5929 return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
5930\r
5931 case FormSetLevel:\r
5932 if (gCurrentSelection == NULL) {\r
5933 return FALSE;\r
5934 }\r
5935 return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
5936\r
5937 case SystemLevel:\r
5938 Link = GetFirstNode (&gBrowserFormSetList);\r
5939 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5940 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
5941 if (!ValidateFormSet(FormSet)) {\r
5942 continue;\r
5943 }\r
5944\r
5945 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
5946 return TRUE;\r
5947 }\r
5948 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5949 }\r
5950 return FALSE;\r
5951\r
5952 default:\r
5953 return FALSE;\r
5954 }\r
5955}\r
5956\r
5957/**\r
5958 Execute the action requested by the Action parameter.\r
5959\r
5960 @param[in] Action Execute the request action.\r
5961 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
5962\r
5963 @retval EFI_SUCCESS Execute the request action succss.\r
5964 @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
5965\r
5966**/\r
5967EFI_STATUS \r
5968EFIAPI\r
5969ExecuteAction (\r
5970 IN UINT32 Action,\r
5971 IN UINT16 DefaultId\r
5972 )\r
5973{\r
5974 EFI_STATUS Status;\r
5975 FORM_BROWSER_FORMSET *FormSet;\r
5976 FORM_BROWSER_FORM *Form;\r
5977\r
5978 if (gBrowserSettingScope < SystemLevel && gCurrentSelection == NULL) {\r
5979 return EFI_NOT_READY;\r
5980 }\r
5981\r
5982 Status = EFI_SUCCESS;\r
5983 FormSet = NULL;\r
5984 Form = NULL;\r
5985 if (gBrowserSettingScope < SystemLevel) {\r
5986 FormSet = gCurrentSelection->FormSet;\r
5987 Form = gCurrentSelection->Form; \r
5988 }\r
5989\r
5990 //\r
5991 // Executet the discard action.\r
5992 //\r
5993 if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
5994 Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
5995 if (EFI_ERROR (Status)) {\r
5996 return Status;\r
5997 }\r
5998 }\r
5999\r
6000 //\r
6001 // Executet the difault action.\r
6002 //\r
6003 if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
6004 Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
6005 if (EFI_ERROR (Status)) {\r
6006 return Status;\r
6007 }\r
6008 UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
6009 }\r
6010\r
6011 //\r
6012 // Executet the submit action.\r
6013 //\r
6014 if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
6015 Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
6016 if (EFI_ERROR (Status)) {\r
6017 return Status;\r
6018 }\r
6019 }\r
6020\r
6021 //\r
6022 // Executet the reset action.\r
6023 //\r
6024 if ((Action & BROWSER_ACTION_RESET) != 0) {\r
6025 gResetRequired = TRUE;\r
6026 }\r
6027\r
6028 //\r
6029 // Executet the exit action.\r
6030 //\r
6031 if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
6032 DiscardForm (FormSet, Form, gBrowserSettingScope);\r
6033 if (gBrowserSettingScope == SystemLevel) {\r
6034 if (ExitHandlerFunction != NULL) {\r
6035 ExitHandlerFunction ();\r
6036 }\r
6037 }\r
6038\r
6039 gExitRequired = TRUE;\r
6040 }\r
6041\r
6042 return Status;\r
6043}\r
6044\r
6045/**\r
6046 Create reminder to let user to choose save or discard the changed browser data.\r
6047 Caller can use it to actively check the changed browser data.\r
6048\r
6049 @retval BROWSER_NO_CHANGES No browser data is changed.\r
6050 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
6051 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
6052 @retval BROWSER_KEEP_CURRENT Browser keep current changes.\r
6053\r
6054**/\r
6055UINT32\r
6056EFIAPI\r
6057SaveReminder (\r
6058 VOID\r
6059 )\r
6060{\r
6061 LIST_ENTRY *Link;\r
6062 FORM_BROWSER_FORMSET *FormSet;\r
6063 BOOLEAN IsDataChanged;\r
6064 UINT32 DataSavedAction;\r
6065 UINT32 ConfirmRet;\r
6066\r
6067 DataSavedAction = BROWSER_NO_CHANGES;\r
6068 IsDataChanged = FALSE;\r
6069 Link = GetFirstNode (&gBrowserFormSetList);\r
6070 while (!IsNull (&gBrowserFormSetList, Link)) {\r
6071 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
6072 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6073 if (!ValidateFormSet(FormSet)) {\r
6074 continue;\r
6075 }\r
6076 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
6077 IsDataChanged = TRUE;\r
6078 break;\r
6079 }\r
6080 }\r
6081 \r
6082 //\r
6083 // No data is changed. No save is required. \r
6084 //\r
6085 if (!IsDataChanged) {\r
6086 return DataSavedAction;\r
6087 }\r
6088 \r
6089 //\r
6090 // If data is changed, prompt user to save or discard it. \r
6091 //\r
6092 do {\r
6093 ConfirmRet = (UINT32) mFormDisplay->ConfirmDataChange();\r
6094\r
6095 if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
6096 SubmitForm (NULL, NULL, SystemLevel);\r
6097 DataSavedAction = BROWSER_SAVE_CHANGES;\r
6098 break;\r
6099 } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
6100 DiscardForm (NULL, NULL, SystemLevel);\r
6101 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
6102 break;\r
6103 } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
6104 DataSavedAction = BROWSER_KEEP_CURRENT;\r
6105 break;\r
6106 }\r
6107 } while (1);\r
6108\r
6109 return DataSavedAction;\r
6110}\r
6111\r
6112/**\r
6113 Check whether the Reset Required for the browser\r
6114\r
6115 @retval TRUE Browser required to reset after exit.\r
6116 @retval FALSE Browser not need to reset after exit.\r
6117\r
6118**/\r
6119BOOLEAN\r
6120EFIAPI\r
6121IsResetRequired (\r
6122 VOID\r
6123 )\r
6124{\r
6125 return gResetRequired;\r
6126}\r
6127\r