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