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