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