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