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