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