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