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