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