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