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