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