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