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