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