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