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