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