]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
EmulatorPkg: Add structure braces { } to fix build warning
[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
816a7110
ED
2265 if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
2266 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
2267 } else {\r
2268 TypeValue = &Question->HiiValue.Value;\r
2269 }\r
2270\r
2271 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2272 FormSet->ConfigAccess->Callback (\r
2273 FormSet->ConfigAccess,\r
2274 EFI_BROWSER_ACTION_CHANGED,\r
2275 Question->QuestionId,\r
2276 Question->HiiValue.Type,\r
2277 TypeValue,\r
2278 &ActionRequest\r
2279 );\r
2280 }\r
2281}\r
b18e7050 2282\r
938baa1f
ED
2283/**\r
2284 Validate the FormSet. If the formset is not validate, remove it from the list.\r
2285\r
2286 @param FormSet The input FormSet which need to validate.\r
2287\r
2288 @retval TRUE The handle is validate.\r
2289 @retval FALSE The handle is invalidate.\r
2290\r
2291**/\r
2292BOOLEAN\r
2293ValidateFormSet (\r
2294 FORM_BROWSER_FORMSET *FormSet\r
2295 )\r
2296{\r
2297 EFI_HII_HANDLE *HiiHandles;\r
2298 UINTN Index;\r
2299 BOOLEAN Find;\r
2300\r
2301 ASSERT (FormSet != NULL);\r
2302 Find = FALSE;\r
2303 //\r
2304 // Get all the Hii handles\r
2305 //\r
2306 HiiHandles = HiiGetHiiHandles (NULL);\r
2307 ASSERT (HiiHandles != NULL);\r
2308\r
2309 //\r
2310 // Search for formset of each class type\r
2311 //\r
2312 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
2313 if (HiiHandles[Index] == FormSet->HiiHandle) {\r
2314 Find = TRUE;\r
2315 break;\r
2316 }\r
2317 }\r
2318\r
2319 if (!Find) {\r
0a6f8af5 2320 CleanBrowserStorage(FormSet);\r
938baa1f
ED
2321 RemoveEntryList (&FormSet->Link);\r
2322 DestroyFormSet (FormSet);\r
2323 }\r
2324\r
2325 FreePool (HiiHandles);\r
2326\r
2327 return Find;\r
2328}\r
7c6c064c
ED
2329/**\r
2330 Check whether need to enable the reset flag in form level.\r
2331 Also clean all ValueChanged flag in question.\r
2332\r
2333 @param SetFlag Whether need to set the Reset Flag.\r
2334 @param Form Form data structure.\r
2335\r
2336**/\r
2337VOID\r
2338UpdateFlagForForm (\r
2339 IN BOOLEAN SetFlag,\r
2340 IN FORM_BROWSER_FORM *Form\r
2341 )\r
2342{\r
2343 LIST_ENTRY *Link;\r
2344 FORM_BROWSER_STATEMENT *Question;\r
2345 BOOLEAN FindOne;\r
2346\r
2347 FindOne = FALSE;\r
2348 Link = GetFirstNode (&Form->StatementListHead);\r
2349 while (!IsNull (&Form->StatementListHead, Link)) {\r
2350 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2351 \r
2352 if (SetFlag && Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
2353 gResetRequired = TRUE;\r
2354 } \r
2355\r
2356 if (Question->ValueChanged) {\r
2357 Question->ValueChanged = FALSE;\r
2358 }\r
2359 \r
2360 Link = GetNextNode (&Form->StatementListHead, Link);\r
2361 }\r
2362}\r
2363\r
2364/**\r
2365 Check whether need to enable the reset flag.\r
2366 Also clean ValueChanged flag for all statements.\r
2367\r
2368 Form level or formset level, only one.\r
2369 \r
2370 @param SetFlag Whether need to set the Reset Flag.\r
2371 @param FormSet FormSet data structure.\r
2372 @param Form Form data structure.\r
2373\r
2374**/\r
2375VOID\r
2376ValueChangeResetFlagUpdate (\r
2377 IN BOOLEAN SetFlag,\r
2378 IN FORM_BROWSER_FORMSET *FormSet,\r
2379 IN FORM_BROWSER_FORM *Form \r
2380 )\r
2381{\r
2382 FORM_BROWSER_FORM *CurrentForm;\r
2383 LIST_ENTRY *Link;\r
2384\r
2385 //\r
2386 // Form != NULL means only check form level.\r
2387 //\r
2388 if (Form != NULL) {\r
2389 UpdateFlagForForm(SetFlag, Form);\r
2390 return;\r
2391 }\r
2392\r
2393 Link = GetFirstNode (&FormSet->FormListHead);\r
2394 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2395 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2396 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2397\r
2398 UpdateFlagForForm(SetFlag, CurrentForm);\r
2399 }\r
2400}\r
938baa1f 2401\r
b18e7050 2402/**\r
48a9d5f7 2403 Discard data based on the input setting scope (Form, FormSet or System).\r
7936fb6a 2404\r
2405 @param FormSet FormSet data structure.\r
2406 @param Form Form data structure.\r
48a9d5f7 2407 @param SettingScope Setting Scope for Discard action.\r
b18e7050
ED
2408\r
2409 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2410 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
b18e7050
ED
2411\r
2412**/\r
2413EFI_STATUS\r
2414DiscardForm (\r
2415 IN FORM_BROWSER_FORMSET *FormSet,\r
2416 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2417 IN BROWSER_SETTING_SCOPE SettingScope\r
b18e7050
ED
2418 )\r
2419{\r
48a9d5f7
LG
2420 LIST_ENTRY *Link;\r
2421 FORMSET_STORAGE *Storage;\r
b18e7050 2422 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
6e74560f
ED
2423 FORM_BROWSER_FORMSET *LocalFormSet;\r
2424 FORM_BROWSER_FORMSET *OldFormSet;\r
b18e7050 2425\r
48a9d5f7
LG
2426 //\r
2427 // Check the supported setting level.\r
2428 //\r
2429 if (SettingScope >= MaxLevel) {\r
2430 return EFI_UNSUPPORTED;\r
2431 }\r
b18e7050 2432\r
7c6c064c 2433 if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
48a9d5f7
LG
2434 ConfigInfo = NULL;\r
2435 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2436 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2437 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2438 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
b18e7050 2439\r
48a9d5f7
LG
2440 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2441 continue;\r
2442 }\r
2443\r
2444 //\r
2445 // Skip if there is no RequestElement\r
2446 //\r
2447 if (ConfigInfo->ElementCount == 0) {\r
2448 continue;\r
b18e7050
ED
2449 }\r
2450\r
48a9d5f7
LG
2451 //\r
2452 // Prepare <ConfigResp>\r
2453 //\r
7c6c064c 2454 SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
816a7110 2455\r
816a7110
ED
2456 //\r
2457 // Call callback with Changed type to inform the driver.\r
2458 //\r
2459 SendDiscardInfoToDriver (FormSet, Form);\r
2460 }\r
2461\r
7c6c064c
ED
2462 ValueChangeResetFlagUpdate (FALSE, NULL, Form);\r
2463 } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
f1660263 2464\r
48a9d5f7
LG
2465 //\r
2466 // Discard Buffer storage or Name/Value storage\r
2467 //\r
2468 Link = GetFirstNode (&FormSet->StorageListHead);\r
2469 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2470 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2471 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2472\r
94f3aae7 2473 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
48a9d5f7
LG
2474 continue;\r
2475 }\r
2476\r
b18e7050 2477 //\r
48a9d5f7 2478 // Skip if there is no RequestElement\r
b18e7050 2479 //\r
48a9d5f7
LG
2480 if (Storage->ElementCount == 0) {\r
2481 continue;\r
2482 }\r
b18e7050 2483\r
7c6c064c 2484 SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
48a9d5f7 2485 }\r
f1660263
ED
2486\r
2487 Link = GetFirstNode (&FormSet->FormListHead);\r
2488 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2489 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2490 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2491 \r
2492 //\r
2493 // Call callback with Changed type to inform the driver.\r
2494 //\r
2495 SendDiscardInfoToDriver (FormSet, Form);\r
2496 }\r
b18e7050 2497\r
7c6c064c 2498 ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
48a9d5f7
LG
2499 } else if (SettingScope == SystemLevel) {\r
2500 //\r
2501 // System Level Discard.\r
2502 //\r
6e74560f
ED
2503 OldFormSet = mSystemLevelFormSet;\r
2504\r
48a9d5f7
LG
2505 //\r
2506 // Discard changed value for each FormSet in the maintain list.\r
2507 //\r
2508 Link = GetFirstNode (&gBrowserFormSetList);\r
2509 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2510 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 2511 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
2512 if (!ValidateFormSet(LocalFormSet)) {\r
2513 continue;\r
2514 }\r
6e74560f
ED
2515\r
2516 mSystemLevelFormSet = LocalFormSet;\r
2517\r
938baa1f 2518 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
48a9d5f7 2519 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
b18e7050 2520 //\r
48a9d5f7 2521 // Remove maintain backup list after discard except for the current using FormSet.\r
b18e7050 2522 //\r
0a6f8af5 2523 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7
LG
2524 RemoveEntryList (&LocalFormSet->Link);\r
2525 DestroyFormSet (LocalFormSet);\r
b18e7050 2526 }\r
b18e7050 2527 }\r
6e74560f
ED
2528\r
2529 mSystemLevelFormSet = OldFormSet;\r
b18e7050
ED
2530 }\r
2531\r
2532 return EFI_SUCCESS; \r
2533}\r
2534\r
2535/**\r
48a9d5f7 2536 Submit data based on the input Setting level (Form, FormSet or System).\r
b18e7050
ED
2537\r
2538 @param FormSet FormSet data structure.\r
2539 @param Form Form data structure.\r
48a9d5f7 2540 @param SettingScope Setting Scope for Submit action.\r
7936fb6a 2541\r
2542 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2543 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 2544\r
2545**/\r
2546EFI_STATUS\r
2547SubmitForm (\r
2548 IN FORM_BROWSER_FORMSET *FormSet,\r
b18e7050 2549 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2550 IN BROWSER_SETTING_SCOPE SettingScope\r
7936fb6a 2551 )\r
2552{\r
2553 EFI_STATUS Status;\r
2554 LIST_ENTRY *Link;\r
2555 EFI_STRING ConfigResp;\r
2556 EFI_STRING Progress;\r
94f3aae7
ED
2557 BROWSER_STORAGE *Storage;\r
2558 FORMSET_STORAGE *FormSetStorage;\r
48a9d5f7 2559 FORM_BROWSER_FORMSET *LocalFormSet;\r
b18e7050 2560 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 2561\r
48a9d5f7
LG
2562 //\r
2563 // Check the supported setting level.\r
2564 //\r
2565 if (SettingScope >= MaxLevel) {\r
2566 return EFI_UNSUPPORTED;\r
2567 }\r
2568\r
7936fb6a 2569 //\r
2570 // Validate the Form by NoSubmit check\r
2571 //\r
48a9d5f7
LG
2572 Status = EFI_SUCCESS;\r
2573 if (SettingScope == FormLevel) {\r
b18e7050 2574 Status = NoSubmitCheck (FormSet, Form);\r
48a9d5f7 2575 } else if (SettingScope == FormSetLevel) {\r
b18e7050
ED
2576 Status = NoSubmitCheck (FormSet, NULL);\r
2577 }\r
7936fb6a 2578 if (EFI_ERROR (Status)) {\r
2579 return Status;\r
2580 }\r
2581\r
7c6c064c 2582 if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
b18e7050
ED
2583 ConfigInfo = NULL;\r
2584 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2585 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2586 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2587 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
7936fb6a 2588\r
cce6230f
ED
2589 Storage = ConfigInfo->Storage;\r
2590 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
b18e7050
ED
2591 continue;\r
2592 }\r
7936fb6a 2593\r
b18e7050
ED
2594 //\r
2595 // Skip if there is no RequestElement\r
2596 //\r
2597 if (ConfigInfo->ElementCount == 0) {\r
2598 continue;\r
2599 }\r
7936fb6a 2600\r
b18e7050 2601 //\r
cce6230f 2602 // 1. Prepare <ConfigResp>\r
b18e7050 2603 //\r
7c6c064c 2604 Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
b18e7050
ED
2605 if (EFI_ERROR (Status)) {\r
2606 return Status;\r
2607 }\r
2608\r
2609 //\r
7248790e 2610 // 2. Set value to hii config routine protocol.\r
b18e7050 2611 //\r
7248790e
ED
2612 Status = mHiiConfigRouting->RouteConfig (\r
2613 mHiiConfigRouting,\r
2614 ConfigResp,\r
2615 &Progress\r
2616 );\r
2617 if (EFI_ERROR (Status)) {\r
2618 FreePool (ConfigResp);\r
2619 return Status;\r
b18e7050 2620 }\r
7248790e 2621\r
b18e7050 2622 FreePool (ConfigResp);\r
b18e7050 2623 //\r
cce6230f 2624 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
b18e7050 2625 //\r
7c6c064c 2626 SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
7936fb6a 2627 }\r
2628\r
cce6230f
ED
2629 //\r
2630 // 4. Update the NV flag.\r
2631 // \r
7c6c064c
ED
2632 ValueChangeResetFlagUpdate(TRUE, NULL, Form);\r
2633 } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
7936fb6a 2634 //\r
b18e7050 2635 // Submit Buffer storage or Name/Value storage\r
7936fb6a 2636 //\r
b18e7050
ED
2637 Link = GetFirstNode (&FormSet->StorageListHead);\r
2638 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
94f3aae7
ED
2639 FormSetStorage = (FORMSET_STORAGE_FROM_LINK (Link));\r
2640 Storage = FormSetStorage->BrowserStorage;\r
b18e7050
ED
2641 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2642\r
2643 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2644 continue;\r
2645 }\r
2646\r
2647 //\r
2648 // Skip if there is no RequestElement\r
2649 //\r
94f3aae7 2650 if (FormSetStorage->ElementCount == 0) {\r
b18e7050
ED
2651 continue;\r
2652 }\r
2653\r
2654 //\r
cce6230f 2655 // 1. Prepare <ConfigResp>\r
b18e7050 2656 //\r
7c6c064c 2657 Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
7936fb6a 2658 if (EFI_ERROR (Status)) {\r
7936fb6a 2659 return Status;\r
2660 }\r
b18e7050 2661\r
7248790e
ED
2662 //\r
2663 // 2. Send <ConfigResp> to Routine config Protocol.\r
2664 //\r
2665 Status = mHiiConfigRouting->RouteConfig (\r
2666 mHiiConfigRouting,\r
2667 ConfigResp,\r
2668 &Progress\r
2669 );\r
2670 if (EFI_ERROR (Status)) {\r
2671 FreePool (ConfigResp);\r
2672 return Status;\r
b18e7050 2673 }\r
7248790e 2674\r
b18e7050 2675 FreePool (ConfigResp);\r
b18e7050 2676 //\r
cce6230f 2677 // 3. Config success, update storage shadow Buffer\r
b18e7050 2678 //\r
7c6c064c 2679 SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE);\r
7936fb6a 2680 }\r
7936fb6a 2681\r
cce6230f
ED
2682 //\r
2683 // 4. Update the NV flag.\r
2684 // \r
7c6c064c 2685 ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
48a9d5f7
LG
2686 } else if (SettingScope == SystemLevel) {\r
2687 //\r
2688 // System Level Save.\r
2689 //\r
2690\r
2691 //\r
2692 // Save changed value for each FormSet in the maintain list.\r
2693 //\r
2694 Link = GetFirstNode (&gBrowserFormSetList);\r
2695 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2696 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 2697 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
2698 if (!ValidateFormSet(LocalFormSet)) {\r
2699 continue;\r
2700 }\r
2701 SubmitForm (LocalFormSet, NULL, FormSetLevel);\r
48a9d5f7
LG
2702 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
2703 //\r
2704 // Remove maintain backup list after save except for the current using FormSet.\r
2705 //\r
0a6f8af5 2706 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7
LG
2707 RemoveEntryList (&LocalFormSet->Link);\r
2708 DestroyFormSet (LocalFormSet);\r
2709 }\r
2710 }\r
7936fb6a 2711 }\r
2712\r
7936fb6a 2713 return EFI_SUCCESS;\r
2714}\r
2715\r
ee31d1be
ED
2716/**\r
2717 Get Question default value from AltCfg string.\r
2718\r
2719 @param FormSet The form set.\r
2720 @param Question The question.\r
2721 @param DefaultId The default Id.\r
2722\r
2723 @retval EFI_SUCCESS Question is reset to default value.\r
2724\r
2725**/\r
2726EFI_STATUS\r
2727GetDefaultValueFromAltCfg (\r
2728 IN FORM_BROWSER_FORMSET *FormSet,\r
2729 IN OUT FORM_BROWSER_STATEMENT *Question,\r
2730 IN UINT16 DefaultId\r
2731 )\r
2732{\r
2733 BOOLEAN IsBufferStorage;\r
2734 BOOLEAN IsString; \r
2735 UINTN Length;\r
94f3aae7 2736 BROWSER_STORAGE *Storage;\r
ee31d1be
ED
2737 CHAR16 *ConfigRequest;\r
2738 CHAR16 *Progress;\r
2739 CHAR16 *Result;\r
2740 CHAR16 *ConfigResp;\r
2741 CHAR16 *Value;\r
2742 CHAR16 *StringPtr;\r
2743 UINTN LengthStr;\r
2744 UINT8 *Dst;\r
2745 CHAR16 TemStr[5];\r
2746 UINTN Index;\r
2747 UINT8 DigitUint8;\r
2748 EFI_STATUS Status;\r
2749\r
2750 Status = EFI_NOT_FOUND;\r
2751 Length = 0;\r
2752 Dst = NULL;\r
2753 ConfigRequest = NULL;\r
2754 Result = NULL;\r
2755 ConfigResp = NULL;\r
0194d26c 2756 Value = NULL;\r
ee31d1be
ED
2757 Storage = Question->Storage;\r
2758\r
7248790e 2759 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
ee31d1be
ED
2760 return Status;\r
2761 }\r
2762\r
2763 //\r
2764 // Question Value is provided by Buffer Storage or NameValue Storage\r
2765 //\r
2766 if (Question->BufferValue != NULL) {\r
2767 //\r
2768 // This Question is password or orderedlist\r
2769 //\r
2770 Dst = Question->BufferValue;\r
2771 } else {\r
2772 //\r
2773 // Other type of Questions\r
2774 //\r
2775 Dst = (UINT8 *) &Question->HiiValue.Value;\r
2776 }\r
2777\r
7248790e
ED
2778 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
2779 IsBufferStorage = TRUE;\r
2780 } else {\r
2781 IsBufferStorage = FALSE;\r
2782 }\r
ee31d1be
ED
2783 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
2784\r
2785 //\r
2786 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
2787 // <ConfigHdr> + "&" + <VariableName>\r
2788 //\r
2789 if (IsBufferStorage) {\r
2790 Length = StrLen (Storage->ConfigHdr);\r
2791 Length += StrLen (Question->BlockName);\r
2792 } else {\r
2793 Length = StrLen (Storage->ConfigHdr);\r
2794 Length += StrLen (Question->VariableName) + 1;\r
2795 }\r
2796 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
2797 ASSERT (ConfigRequest != NULL);\r
2798\r
2799 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
2800 if (IsBufferStorage) {\r
2801 StrCat (ConfigRequest, Question->BlockName);\r
2802 } else {\r
2803 StrCat (ConfigRequest, L"&");\r
2804 StrCat (ConfigRequest, Question->VariableName);\r
2805 }\r
2806\r
7248790e
ED
2807 Status = mHiiConfigRouting->ExtractConfig (\r
2808 mHiiConfigRouting,\r
ee31d1be
ED
2809 ConfigRequest,\r
2810 &Progress,\r
2811 &Result\r
2812 );\r
2813 if (EFI_ERROR (Status)) {\r
2814 goto Done;\r
2815 }\r
2816\r
2817 //\r
2818 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
2819 // Get the default configuration string according to the default ID.\r
2820 //\r
2821 Status = mHiiConfigRouting->GetAltConfig (\r
2822 mHiiConfigRouting,\r
2823 Result,\r
2824 &Storage->Guid,\r
2825 Storage->Name,\r
2826 NULL,\r
2827 &DefaultId, // it can be NULL to get the current setting.\r
2828 &ConfigResp\r
2829 );\r
2830 \r
2831 //\r
2832 // The required setting can't be found. So, it is not required to be validated and set.\r
2833 //\r
2834 if (EFI_ERROR (Status)) {\r
2835 goto Done;\r
2836 }\r
2837\r
7248790e
ED
2838 if (ConfigResp == NULL) {\r
2839 Status = EFI_NOT_FOUND;\r
2840 goto Done;\r
2841 }\r
2842\r
ee31d1be
ED
2843 //\r
2844 // Skip <ConfigRequest>\r
2845 //\r
ee31d1be 2846 if (IsBufferStorage) {\r
0194d26c
ED
2847 Value = StrStr (ConfigResp, L"&VALUE");\r
2848 ASSERT (Value != NULL);\r
ee31d1be
ED
2849 //\r
2850 // Skip "&VALUE"\r
2851 //\r
2852 Value = Value + 6;\r
0194d26c
ED
2853 } else {\r
2854 Value = StrStr (ConfigResp, Question->VariableName);\r
2855 ASSERT (Value != NULL);\r
2856\r
2857 Value = Value + StrLen (Question->VariableName);\r
ee31d1be
ED
2858 }\r
2859 if (*Value != '=') {\r
2860 Status = EFI_NOT_FOUND;\r
2861 goto Done;\r
2862 }\r
2863 //\r
2864 // Skip '=', point to value\r
2865 //\r
2866 Value = Value + 1;\r
2867\r
2868 //\r
2869 // Suppress <AltResp> if any\r
2870 //\r
2871 StringPtr = Value;\r
2872 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2873 StringPtr++;\r
2874 }\r
2875 *StringPtr = L'\0';\r
2876\r
2877 LengthStr = StrLen (Value);\r
2878 if (!IsBufferStorage && IsString) {\r
2879 StringPtr = (CHAR16 *) Dst;\r
2880 ZeroMem (TemStr, sizeof (TemStr));\r
2881 for (Index = 0; Index < LengthStr; Index += 4) {\r
2882 StrnCpy (TemStr, Value + Index, 4);\r
2883 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
2884 }\r
2885 //\r
2886 // Add tailing L'\0' character\r
2887 //\r
25361615
ED
2888 StringPtr[Index/4] = L'\0';\r
2889 } else {\r
2890 ZeroMem (TemStr, sizeof (TemStr));\r
2891 for (Index = 0; Index < LengthStr; Index ++) {\r
2892 TemStr[0] = Value[LengthStr - Index - 1];\r
2893 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
2894 if ((Index & 1) == 0) {\r
2895 Dst [Index/2] = DigitUint8;\r
2896 } else {\r
2897 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
2898 }\r
2899 }\r
2900 }\r
b9feb4bd 2901\r
7c6c064c
ED
2902Done:\r
2903 if (ConfigRequest != NULL){\r
2904 FreePool (ConfigRequest);\r
2905 }\r
2906\r
2907 if (ConfigResp != NULL) {\r
2908 FreePool (ConfigResp);\r
2909 }\r
2910 \r
2911 if (Result != NULL) {\r
2912 FreePool (Result);\r
2913 }\r
2914\r
2915 return Status;\r
2916}\r
2917\r
2918/**\r
2919 Get default Id value used for browser.\r
2920\r
2921 @param DefaultId The default id value used by hii.\r
2922\r
2923 @retval Browser used default value.\r
2924\r
2925**/\r
2926INTN\r
2927GetDefaultIdForCallBack (\r
2928 UINTN DefaultId\r
2929 )\r
2930{ \r
2931 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2932 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
2933 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2934 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
2935 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
2936 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
2937 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
2938 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
2939 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
2940 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
2941 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
2942 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
2943 } else {\r
2944 return -1;\r
2945 }\r
2946}\r
2947\r
2948\r
2949\r
2950/**\r
2951 Return data element in an Array by its Index.\r
2952\r
2953 @param Array The data array.\r
2954 @param Type Type of the data in this array.\r
2955 @param Index Zero based index for data in this array.\r
2956\r
2957 @retval Value The data to be returned\r
2958\r
2959**/\r
2960UINT64\r
2961GetArrayData (\r
2962 IN VOID *Array,\r
2963 IN UINT8 Type,\r
2964 IN UINTN Index\r
2965 )\r
2966{\r
2967 UINT64 Data;\r
2968\r
2969 ASSERT (Array != NULL);\r
2970\r
2971 Data = 0;\r
2972 switch (Type) {\r
2973 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2974 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
2975 break;\r
2976\r
2977 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2978 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
2979 break;\r
2980\r
2981 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2982 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
2983 break;\r
2984\r
2985 case EFI_IFR_TYPE_NUM_SIZE_64:\r
2986 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
2987 break;\r
2988\r
2989 default:\r
2990 break;\r
2991 }\r
2992\r
2993 return Data;\r
2994}\r
2995\r
2996\r
2997/**\r
2998 Set value of a data element in an Array by its Index.\r
2999\r
3000 @param Array The data array.\r
3001 @param Type Type of the data in this array.\r
3002 @param Index Zero based index for data in this array.\r
3003 @param Value The value to be set.\r
3004\r
3005**/\r
3006VOID\r
3007SetArrayData (\r
3008 IN VOID *Array,\r
3009 IN UINT8 Type,\r
3010 IN UINTN Index,\r
3011 IN UINT64 Value\r
3012 )\r
3013{\r
3014\r
3015 ASSERT (Array != NULL);\r
b9feb4bd 3016\r
7c6c064c
ED
3017 switch (Type) {\r
3018 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3019 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
3020 break;\r
25361615 3021\r
7c6c064c
ED
3022 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3023 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
3024 break;\r
3025\r
3026 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3027 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
3028 break;\r
3029\r
3030 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3031 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
3032 break;\r
3033\r
3034 default:\r
3035 break;\r
3036 }\r
ee31d1be
ED
3037}\r
3038\r
3039/**\r
7c6c064c 3040 Search an Option of a Question by its value.\r
ee31d1be 3041\r
7c6c064c
ED
3042 @param Question The Question\r
3043 @param OptionValue Value for Option to be searched.\r
ee31d1be 3044\r
7c6c064c
ED
3045 @retval Pointer Pointer to the found Option.\r
3046 @retval NULL Option not found.\r
ee31d1be
ED
3047\r
3048**/\r
7c6c064c
ED
3049QUESTION_OPTION *\r
3050ValueToOption (\r
3051 IN FORM_BROWSER_STATEMENT *Question,\r
3052 IN EFI_HII_VALUE *OptionValue\r
ee31d1be 3053 )\r
7c6c064c
ED
3054{\r
3055 LIST_ENTRY *Link;\r
3056 QUESTION_OPTION *Option;\r
3057 INTN Result;\r
3058\r
3059 Link = GetFirstNode (&Question->OptionListHead);\r
3060 while (!IsNull (&Question->OptionListHead, Link)) {\r
3061 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3062\r
3063 if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
3064 //\r
3065 // Check the suppressif condition, only a valid option can be return.\r
3066 //\r
3067 if ((Option->SuppressExpression == NULL) ||\r
3068 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
3069 return Option;\r
3070 }\r
3071 }\r
3072\r
3073 Link = GetNextNode (&Question->OptionListHead, Link);\r
ee31d1be 3074 }\r
7c6c064c
ED
3075\r
3076 return NULL;\r
ee31d1be 3077}\r
7936fb6a 3078\r
7c6c064c 3079\r
7936fb6a 3080/**\r
3081 Reset Question to its default value.\r
3082\r
3083 @param FormSet The form set.\r
3084 @param Form The form.\r
3085 @param Question The question.\r
3086 @param DefaultId The Class of the default.\r
3087\r
3088 @retval EFI_SUCCESS Question is reset to default value.\r
3089\r
3090**/\r
3091EFI_STATUS\r
3092GetQuestionDefault (\r
3093 IN FORM_BROWSER_FORMSET *FormSet,\r
3094 IN FORM_BROWSER_FORM *Form,\r
3095 IN FORM_BROWSER_STATEMENT *Question,\r
3096 IN UINT16 DefaultId\r
3097 )\r
3098{\r
3099 EFI_STATUS Status;\r
3100 LIST_ENTRY *Link;\r
3101 QUESTION_DEFAULT *Default;\r
3102 QUESTION_OPTION *Option;\r
3103 EFI_HII_VALUE *HiiValue;\r
3104 UINT8 Index;\r
086cd2c8 3105 EFI_STRING StrValue;\r
ee31d1be
ED
3106 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3107 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
3108 INTN Action;\r
061d5462 3109 CHAR16 *NewString;\r
7936fb6a 3110\r
48a9d5f7 3111 Status = EFI_NOT_FOUND;\r
086cd2c8 3112 StrValue = NULL;\r
7936fb6a 3113\r
3114 //\r
3115 // Statement don't have storage, skip them\r
3116 //\r
3117 if (Question->QuestionId == 0) {\r
3118 return Status;\r
3119 }\r
3120\r
3121 //\r
ee31d1be
ED
3122 // There are Five ways to specify default value for a Question:\r
3123 // 1, use call back function (highest priority)\r
3124 // 2, use ExtractConfig function\r
3125 // 3, use nested EFI_IFR_DEFAULT \r
3126 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
3127 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 3128 //\r
3129 HiiValue = &Question->HiiValue;\r
3130\r
ee31d1be
ED
3131 //\r
3132 // Get Question defaut value from call back function.\r
3133 //\r
3134 ConfigAccess = FormSet->ConfigAccess;\r
3135 Action = GetDefaultIdForCallBack (DefaultId);\r
3136 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
3137 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
3138 Status = ConfigAccess->Callback (\r
3139 ConfigAccess,\r
3140 Action,\r
3141 Question->QuestionId,\r
3142 HiiValue->Type,\r
3143 &HiiValue->Value,\r
3144 &ActionRequest\r
3145 );\r
3146 if (!EFI_ERROR (Status)) {\r
061d5462
ED
3147 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3148 NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
3149 ASSERT (NewString != NULL);\r
3150\r
3151 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
3152 if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
3153 CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
3154 } else {\r
3155 CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
3156 }\r
3157\r
3158 FreePool (NewString);\r
3159 }\r
ee31d1be
ED
3160 return Status;\r
3161 }\r
3162 }\r
3163\r
3164 //\r
3165 // Get default value from altcfg string.\r
3166 //\r
3167 if (ConfigAccess != NULL) { \r
3168 Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
3169 if (!EFI_ERROR (Status)) {\r
3170 return Status;\r
3171 }\r
3172 }\r
3173\r
7936fb6a 3174 //\r
3175 // EFI_IFR_DEFAULT has highest priority\r
3176 //\r
3177 if (!IsListEmpty (&Question->DefaultListHead)) {\r
3178 Link = GetFirstNode (&Question->DefaultListHead);\r
3179 while (!IsNull (&Question->DefaultListHead, Link)) {\r
3180 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
3181\r
3182 if (Default->DefaultId == DefaultId) {\r
3183 if (Default->ValueExpression != NULL) {\r
3184 //\r
3185 // Default is provided by an Expression, evaluate it\r
3186 //\r
3187 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
3188 if (EFI_ERROR (Status)) {\r
3189 return Status;\r
3190 }\r
3191\r
901ba0e7
ED
3192 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
3193 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
3194 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
3195 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
3196 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
3197 } else {\r
3198 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
3199 Question->HiiValue.BufferLen = Question->StorageWidth;\r
3200 }\r
3201 FreePool (Default->ValueExpression->Result.Buffer);\r
3202 }\r
3203 HiiValue->Type = Default->ValueExpression->Result.Type;\r
3204 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 3205 } else {\r
3206 //\r
3207 // Default value is embedded in EFI_IFR_DEFAULT\r
3208 //\r
3209 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
3210 }\r
3211\r
086cd2c8
LG
3212 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3213 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
3214 if (StrValue == NULL) {\r
3215 return EFI_NOT_FOUND;\r
3216 }\r
ba944801
ED
3217 if (Question->StorageWidth > StrSize (StrValue)) {\r
3218 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
3219 } else {\r
3220 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
3221 }\r
086cd2c8
LG
3222 }\r
3223\r
7936fb6a 3224 return EFI_SUCCESS;\r
3225 }\r
3226\r
3227 Link = GetNextNode (&Question->DefaultListHead, Link);\r
3228 }\r
3229 }\r
3230\r
3231 //\r
3232 // EFI_ONE_OF_OPTION\r
3233 //\r
3234 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
3235 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3236 //\r
3237 // OneOfOption could only provide Standard and Manufacturing default\r
3238 //\r
3239 Link = GetFirstNode (&Question->OptionListHead);\r
3240 while (!IsNull (&Question->OptionListHead, Link)) {\r
3241 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
3242 Link = GetNextNode (&Question->OptionListHead, Link);\r
3243\r
3244 if ((Option->SuppressExpression != NULL) &&\r
3245 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3246 continue;\r
3247 }\r
7936fb6a 3248\r
3249 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
3250 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
3251 ) {\r
3252 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
3253\r
3254 return EFI_SUCCESS;\r
3255 }\r
7936fb6a 3256 }\r
3257 }\r
3258 }\r
3259\r
3260 //\r
3261 // EFI_IFR_CHECKBOX - lowest priority\r
3262 //\r
3263 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
3264 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3265 //\r
3266 // Checkbox could only provide Standard and Manufacturing default\r
3267 //\r
3268 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
3269 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
3270 ) {\r
3271 HiiValue->Value.b = TRUE;\r
3272 } else {\r
3273 HiiValue->Value.b = FALSE;\r
3274 }\r
3275\r
3276 return EFI_SUCCESS;\r
3277 }\r
3278 }\r
3279\r
3280 //\r
3281 // For Questions without default\r
3282 //\r
48a9d5f7 3283 Status = EFI_NOT_FOUND;\r
7936fb6a 3284 switch (Question->Operand) {\r
cf4c5a42
LG
3285 case EFI_IFR_NUMERIC_OP:\r
3286 //\r
3287 // Take minimum value as numeric default value\r
3288 //\r
3289 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
3290 HiiValue->Value.u64 = Question->Minimum;\r
48a9d5f7 3291 Status = EFI_SUCCESS;\r
cf4c5a42
LG
3292 }\r
3293 break;\r
3294\r
7936fb6a 3295 case EFI_IFR_ONE_OF_OP:\r
3296 //\r
3297 // Take first oneof option as oneof's default value\r
3298 //\r
d66e6c16 3299 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed 3300 Link = GetFirstNode (&Question->OptionListHead);\r
82612023 3301 while (!IsNull (&Question->OptionListHead, Link)) {\r
0a1147ed 3302 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
3303 Link = GetNextNode (&Question->OptionListHead, Link);\r
3304\r
3305 if ((Option->SuppressExpression != NULL) &&\r
3306 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3307 continue;\r
3308 }\r
3309\r
0a1147ed 3310 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 3311 Status = EFI_SUCCESS;\r
82612023 3312 break;\r
0a1147ed 3313 }\r
7936fb6a 3314 }\r
3315 break;\r
3316\r
3317 case EFI_IFR_ORDERED_LIST_OP:\r
3318 //\r
3319 // Take option sequence in IFR as ordered list's default value\r
3320 //\r
3321 Index = 0;\r
3322 Link = GetFirstNode (&Question->OptionListHead);\r
3323 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 3324 Status = EFI_SUCCESS;\r
7936fb6a 3325 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
3326 Link = GetNextNode (&Question->OptionListHead, Link);\r
3327\r
3328 if ((Option->SuppressExpression != NULL) &&\r
3329 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3330 continue;\r
3331 }\r
7936fb6a 3332\r
d02847d3 3333 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 3334\r
3335 Index++;\r
3336 if (Index >= Question->MaxContainers) {\r
3337 break;\r
3338 }\r
7936fb6a 3339 }\r
3340 break;\r
3341\r
3342 default:\r
7936fb6a 3343 break;\r
3344 }\r
3345\r
3346 return Status;\r
3347}\r
3348\r
3349\r
3350/**\r
9776099f 3351 Reset Questions to their initial value or default value in a Form, Formset or System.\r
7936fb6a 3352\r
09cdd7d2
ED
3353 GetDefaultValueScope parameter decides which questions will reset \r
3354 to its default value.\r
3355\r
7936fb6a 3356 @param FormSet FormSet data structure.\r
48a9d5f7 3357 @param Form Form data structure.\r
7936fb6a 3358 @param DefaultId The Class of the default.\r
48a9d5f7 3359 @param SettingScope Setting Scope for Default action.\r
09cdd7d2 3360 @param GetDefaultValueScope Get default value scope.\r
3347d410 3361 @param Storage Get default value only for this storage.\r
9776099f
ED
3362 @param RetrieveValueFirst Whether call the retrieve call back to\r
3363 get the initial value before get default\r
3364 value.\r
7936fb6a 3365\r
3366 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 3367 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 3368\r
3369**/\r
3370EFI_STATUS\r
48a9d5f7 3371ExtractDefault (\r
7936fb6a 3372 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
3373 IN FORM_BROWSER_FORM *Form,\r
3374 IN UINT16 DefaultId,\r
3347d410 3375 IN BROWSER_SETTING_SCOPE SettingScope,\r
09cdd7d2 3376 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
94f3aae7 3377 IN BROWSER_STORAGE *Storage OPTIONAL,\r
9776099f 3378 IN BOOLEAN RetrieveValueFirst\r
7936fb6a 3379 )\r
3380{\r
3381 EFI_STATUS Status;\r
4f33c838 3382 LIST_ENTRY *FormLink;\r
48a9d5f7 3383 LIST_ENTRY *Link;\r
7936fb6a 3384 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7 3385 FORM_BROWSER_FORMSET *LocalFormSet;\r
6e74560f 3386 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 3387\r
9776099f
ED
3388 Status = EFI_SUCCESS;\r
3389\r
48a9d5f7
LG
3390 //\r
3391 // Check the supported setting level.\r
3392 //\r
09cdd7d2
ED
3393 if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
3394 return EFI_UNSUPPORTED;\r
3395 }\r
3396\r
3397 if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
48a9d5f7
LG
3398 return EFI_UNSUPPORTED;\r
3399 }\r
3400 \r
3401 if (SettingScope == FormLevel) {\r
8d00a0f1 3402 //\r
4f33c838 3403 // Extract Form default\r
8d00a0f1 3404 //\r
48a9d5f7
LG
3405 Link = GetFirstNode (&Form->StatementListHead);\r
3406 while (!IsNull (&Form->StatementListHead, Link)) {\r
3407 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3408 Link = GetNextNode (&Form->StatementListHead, Link);\r
3347d410
ED
3409\r
3410 //\r
3411 // If get default value only for this storage, check the storage first.\r
3412 //\r
09cdd7d2
ED
3413 if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
3414 continue;\r
3415 }\r
3416\r
3417 //\r
3418 // If get default value only for no storage question, just skip the question which has storage.\r
3419 //\r
3420 if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
3347d410
ED
3421 continue;\r
3422 }\r
3423\r
4f33c838
ED
3424 //\r
3425 // If Question is disabled, don't reset it to default\r
3426 //\r
31585af4
ED
3427 if (Question->Expression != NULL) {\r
3428 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4f33c838
ED
3429 continue;\r
3430 }\r
8d00a0f1 3431 }\r
9776099f
ED
3432\r
3433 if (RetrieveValueFirst) {\r
3434 //\r
3435 // Call the Retrieve call back to get the initial question value.\r
3436 //\r
061d5462 3437 Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question, FormSet);\r
9776099f
ED
3438 }\r
3439\r
4f33c838 3440 //\r
9776099f 3441 // If not request to get the initial value or get initial value fail, then get default value.\r
4f33c838 3442 //\r
9776099f
ED
3443 if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
3444 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
3445 if (EFI_ERROR (Status)) {\r
3446 continue;\r
3447 }\r
4f33c838 3448 }\r
9776099f 3449\r
4f33c838
ED
3450 //\r
3451 // Synchronize Buffer storage's Edit buffer\r
3452 //\r
3453 if ((Question->Storage != NULL) &&\r
3454 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
816a7110 3455 SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
48a9d5f7
LG
3456 }\r
3457 }\r
3458 } else if (SettingScope == FormSetLevel) {\r
3459 FormLink = GetFirstNode (&FormSet->FormListHead);\r
3460 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
3461 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
9776099f 3462 ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
48a9d5f7
LG
3463 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
3464 }\r
3465 } else if (SettingScope == SystemLevel) {\r
3466 //\r
7c6c064c 3467 // Preload all Hii formset.\r
48a9d5f7 3468 //\r
7c6c064c 3469 LoadAllHiiFormset();\r
6e74560f
ED
3470\r
3471 OldFormSet = mSystemLevelFormSet;\r
3472\r
48a9d5f7
LG
3473 //\r
3474 // Set Default Value for each FormSet in the maintain list.\r
3475 //\r
3476 Link = GetFirstNode (&gBrowserFormSetList);\r
3477 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3478 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 3479 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
3480 if (!ValidateFormSet(LocalFormSet)) {\r
3481 continue;\r
3482 }\r
6e74560f
ED
3483\r
3484 mSystemLevelFormSet = LocalFormSet;\r
3485\r
938baa1f 3486 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
7936fb6a 3487 }\r
6e74560f
ED
3488\r
3489 mSystemLevelFormSet = OldFormSet;\r
7936fb6a 3490 }\r
3491\r
3492 return EFI_SUCCESS;\r
3493}\r
3494\r
7c6c064c
ED
3495\r
3496/**\r
3497 Validate whether this question's value has changed.\r
3498\r
3499 @param FormSet FormSet data structure.\r
3500 @param Form Form data structure.\r
3501 @param Question Question to be initialized.\r
3502 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
3503\r
3504 @retval TRUE Question's value has changed.\r
3505 @retval FALSE Question's value has not changed\r
3506\r
3507**/\r
3508BOOLEAN\r
3509IsQuestionValueChanged (\r
3510 IN FORM_BROWSER_FORMSET *FormSet,\r
3511 IN FORM_BROWSER_FORM *Form,\r
3512 IN OUT FORM_BROWSER_STATEMENT *Question,\r
3513 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
3514 )\r
3515{\r
3516 EFI_HII_VALUE BackUpValue;\r
3517 CHAR8 *BackUpBuffer;\r
3518 EFI_STATUS Status;\r
3519 BOOLEAN ValueChanged;\r
3520 UINTN BufferWidth;\r
3521\r
3522 //\r
3523 // For quetion without storage, always mark it as data not changed.\r
3524 //\r
3525 if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
3526 return FALSE;\r
3527 }\r
3528\r
3529 BackUpBuffer = NULL;\r
3530 ValueChanged = FALSE;\r
3531\r
3532 switch (Question->Operand) {\r
3533 case EFI_IFR_ORDERED_LIST_OP:\r
3534 BufferWidth = Question->StorageWidth;\r
3535 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
3536 ASSERT (BackUpBuffer != NULL);\r
3537 break;\r
3538\r
3539 case EFI_IFR_STRING_OP:\r
3540 case EFI_IFR_PASSWORD_OP:\r
3541 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
3542 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
3543 ASSERT (BackUpBuffer != NULL);\r
3544 break;\r
3545\r
3546 default:\r
3547 BufferWidth = 0;\r
3548 break;\r
3549 }\r
3550 CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
3551\r
3552 Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
3553 ASSERT_EFI_ERROR(Status);\r
3554\r
3555 if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
3556 CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
3557 ValueChanged = TRUE;\r
3558 }\r
3559\r
3560 CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
3561 CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
3562\r
3563 if (BackUpBuffer != NULL) {\r
3564 FreePool (BackUpBuffer);\r
3565 }\r
3566\r
892eccc8
ED
3567 Question->ValueChanged = ValueChanged;\r
3568\r
7c6c064c
ED
3569 return ValueChanged;\r
3570}\r
3571\r
7936fb6a 3572/**\r
3573 Initialize Question's Edit copy from Storage.\r
3574\r
eccfeab1
LG
3575 @param Selection Selection contains the information about \r
3576 the Selection, form and formset to be displayed.\r
3577 Selection action may be updated in retrieve callback.\r
7d1b202d 3578 If Selection is NULL, only initialize Question value.\r
7936fb6a 3579 @param FormSet FormSet data structure.\r
3580 @param Form Form data structure.\r
3581\r
3582 @retval EFI_SUCCESS The function completed successfully.\r
3583\r
3584**/\r
3585EFI_STATUS\r
3586LoadFormConfig (\r
eccfeab1
LG
3587 IN OUT UI_MENU_SELECTION *Selection,\r
3588 IN FORM_BROWSER_FORMSET *FormSet,\r
3589 IN FORM_BROWSER_FORM *Form\r
7936fb6a 3590 )\r
3591{\r
eccfeab1
LG
3592 EFI_STATUS Status;\r
3593 LIST_ENTRY *Link;\r
3594 FORM_BROWSER_STATEMENT *Question;\r
eccfeab1 3595 \r
7936fb6a 3596 Link = GetFirstNode (&Form->StatementListHead);\r
3597 while (!IsNull (&Form->StatementListHead, Link)) {\r
3598 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3599\r
3600 //\r
3601 // Initialize local copy of Value for each Question\r
3602 //\r
7c6c064c
ED
3603 if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
3604 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
3605 } else {\r
3606 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
3607 }\r
7936fb6a 3608 if (EFI_ERROR (Status)) {\r
3609 return Status;\r
3610 }\r
e2100bfa
ED
3611\r
3612 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
3613 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
3614 }\r
3615\r
7936fb6a 3616 Link = GetNextNode (&Form->StatementListHead, Link);\r
3617 }\r
3618\r
3619 return EFI_SUCCESS;\r
3620}\r
3621\r
d66e6c16 3622/**\r
3623 Initialize Question's Edit copy from Storage for the whole Formset.\r
3624\r
eccfeab1
LG
3625 @param Selection Selection contains the information about \r
3626 the Selection, form and formset to be displayed.\r
3627 Selection action may be updated in retrieve callback.\r
7d1b202d 3628 If Selection is NULL, only initialize Question value.\r
d66e6c16 3629 @param FormSet FormSet data structure.\r
3630\r
3631 @retval EFI_SUCCESS The function completed successfully.\r
3632\r
3633**/\r
3634EFI_STATUS\r
3635LoadFormSetConfig (\r
eccfeab1
LG
3636 IN OUT UI_MENU_SELECTION *Selection,\r
3637 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 3638 )\r
3639{\r
eccfeab1
LG
3640 EFI_STATUS Status;\r
3641 LIST_ENTRY *Link;\r
3642 FORM_BROWSER_FORM *Form;\r
d66e6c16 3643\r
3644 Link = GetFirstNode (&FormSet->FormListHead);\r
3645 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3646 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3647\r
3648 //\r
3649 // Initialize local copy of Value for each Form\r
3650 //\r
eccfeab1 3651 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 3652 if (EFI_ERROR (Status)) {\r
3653 return Status;\r
3654 }\r
3655\r
3656 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3657 }\r
3658\r
7c6c064c
ED
3659 //\r
3660 // Finished question initialization.\r
3661 // \r
3662 FormSet->QuestionInited = TRUE;\r
3663\r
d66e6c16 3664 return EFI_SUCCESS;\r
3665}\r
3666\r
0a6f8af5
ED
3667/**\r
3668 Remove the Request element from the Config Request.\r
3669\r
3670 @param Storage Pointer to the browser storage.\r
3671 @param RequestElement The pointer to the Request element.\r
3672\r
3673**/\r
3674VOID\r
3675RemoveElement (\r
3676 IN OUT BROWSER_STORAGE *Storage,\r
3677 IN CHAR16 *RequestElement\r
3678 )\r
3679{\r
3680 CHAR16 *NewStr;\r
3681 CHAR16 *DestStr;\r
3682\r
3683 ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
3684\r
3685 NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
3686\r
3687 if (NewStr == NULL) {\r
3688 return;\r
3689 }\r
3690\r
3691 //\r
3692 // Remove this element from this ConfigRequest.\r
3693 //\r
3694 DestStr = NewStr;\r
3695 NewStr += StrLen (RequestElement);\r
3696 CopyMem (DestStr, NewStr, StrSize (NewStr));\r
3697 \r
3698 Storage->SpareStrLen += StrLen (RequestElement); \r
3699}\r
3700\r
3701/**\r
3702 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
3703\r
3704 @param Storage Pointer to the browser storage.\r
3705 @param ConfigRequest The pointer to the Request element.\r
3706\r
3707**/\r
3708VOID\r
3709RemoveConfigRequest (\r
3710 BROWSER_STORAGE *Storage,\r
3711 CHAR16 *ConfigRequest\r
3712 )\r
3713{\r
3714 CHAR16 *RequestElement;\r
3715 CHAR16 *NextRequestElement;\r
3716 CHAR16 *SearchKey;\r
3717\r
7c6c064c
ED
3718 //\r
3719 // No request element in it, just return.\r
3720 //\r
3721 if (ConfigRequest == NULL) {\r
3722 return;\r
3723 }\r
3724\r
0a6f8af5
ED
3725 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3726 //\r
3727 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
3728 //\r
3729 SearchKey = L"&";\r
3730 } else {\r
3731 //\r
3732 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
3733 //\r
3734 SearchKey = L"&OFFSET";\r
3735 }\r
3736\r
3737 //\r
3738 // Find SearchKey storage\r
3739 //\r
3740 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3741 RequestElement = StrStr (ConfigRequest, L"PATH");\r
3742 ASSERT (RequestElement != NULL);\r
3743 RequestElement = StrStr (RequestElement, SearchKey); \r
3744 } else {\r
3745 RequestElement = StrStr (ConfigRequest, SearchKey);\r
3746 }\r
3747\r
3748 while (RequestElement != NULL) {\r
3749 //\r
3750 // +1 to avoid find header itself.\r
3751 //\r
3752 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
3753\r
3754 //\r
3755 // The last Request element in configRequest string.\r
3756 //\r
3757 if (NextRequestElement != NULL) {\r
3758 //\r
3759 // Replace "&" with '\0'.\r
3760 //\r
3761 *NextRequestElement = L'\0';\r
3762 }\r
3763\r
3764 RemoveElement (Storage, RequestElement);\r
3765\r
3766 if (NextRequestElement != NULL) {\r
3767 //\r
3768 // Restore '&' with '\0' for later used.\r
3769 //\r
3770 *NextRequestElement = L'&';\r
3771 }\r
3772\r
3773 RequestElement = NextRequestElement;\r
3774 }\r
3775\r
3776 //\r
3777 // If no request element remain, just remove the ConfigRequest string.\r
3778 //\r
3779 if (StrCmp (Storage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
3780 FreePool (Storage->ConfigRequest);\r
3781 Storage->ConfigRequest = NULL;\r
3782 Storage->SpareStrLen = 0;\r
3783 }\r
3784}\r
3785\r
3786/**\r
3787 Base on the current formset info, clean the ConfigRequest string in browser storage.\r
3788\r
3789 @param FormSet Pointer of the FormSet\r
3790\r
3791**/\r
3792VOID\r
3793CleanBrowserStorage (\r
3794 IN OUT FORM_BROWSER_FORMSET *FormSet\r
3795 )\r
3796{\r
3797 LIST_ENTRY *Link;\r
3798 FORMSET_STORAGE *Storage;\r
3799\r
3800 Link = GetFirstNode (&FormSet->StorageListHead);\r
3801 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3802 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
3803 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3804\r
fae73624
ED
3805 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
3806 if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
3807 continue;\r
3808 }\r
0a6f8af5 3809\r
9d34cac8 3810 RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest);\r
fae73624
ED
3811 } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
3812 Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3813 if (Storage->BrowserStorage->ConfigRequest != NULL) { \r
3814 FreePool (Storage->BrowserStorage->ConfigRequest);\r
5dc6ab16 3815 Storage->BrowserStorage->ConfigRequest = NULL;\r
fae73624
ED
3816 }\r
3817 Storage->BrowserStorage->Initialized = FALSE;\r
0a6f8af5 3818 }\r
0a6f8af5
ED
3819 }\r
3820}\r
3821\r
efffd9c1
ED
3822/**\r
3823 Check whether current element in the ConfigReqeust string.\r
3824\r
3825 @param BrowserStorage Storage which includes ConfigReqeust.\r
3826 @param RequestElement New element need to check.\r
3827\r
3828 @retval TRUE The Element is in the ConfigReqeust string.\r
3829 @retval FALSE The Element not in the configReqeust String.\r
3830\r
3831**/\r
3832BOOLEAN \r
3833ElementValidation (\r
3834 BROWSER_STORAGE *BrowserStorage,\r
3835 CHAR16 *RequestElement\r
3836 )\r
3837{\r
3838 return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
3839}\r
3840\r
3841/**\r
3842 Append the Request element to the Config Request.\r
3843\r
3844 @param ConfigRequest Current ConfigRequest info.\r
3845 @param SpareStrLen Current remain free buffer for config reqeust.\r
3846 @param RequestElement New Request element.\r
3847\r
3848**/\r
3849VOID\r
3850AppendConfigRequest (\r
3851 IN OUT CHAR16 **ConfigRequest,\r
3852 IN OUT UINTN *SpareStrLen,\r
3853 IN CHAR16 *RequestElement\r
3854 )\r
3855{\r
3856 CHAR16 *NewStr;\r
3857 UINTN StringSize;\r
3858 UINTN StrLength;\r
3859\r
0a6f8af5 3860 StrLength = StrLen (RequestElement);\r
efffd9c1
ED
3861\r
3862 //\r
3863 // Append <RequestElement> to <ConfigRequest>\r
3864 //\r
3865 if (StrLength > *SpareStrLen) {\r
3866 //\r
3867 // Old String buffer is not sufficient for RequestElement, allocate a new one\r
3868 //\r
3869 StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
3870 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
3871 ASSERT (NewStr != NULL);\r
3872\r
3873 if (*ConfigRequest != NULL) {\r
3874 CopyMem (NewStr, *ConfigRequest, StringSize);\r
3875 FreePool (*ConfigRequest);\r
3876 }\r
3877 *ConfigRequest = NewStr;\r
3878 *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
3879 }\r
3880\r
3881 StrCat (*ConfigRequest, RequestElement);\r
3882 *SpareStrLen -= StrLength;\r
3883}\r
3884\r
3885/**\r
3886 Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
3887\r
3888 @param Storage Form set Storage.\r
9d34cac8
ED
3889 @param Request The input request string.\r
3890 @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
efffd9c1
ED
3891\r
3892 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
3893 @retval FALSE All elements covered by current used elements.\r
3894\r
3895**/\r
3896BOOLEAN \r
3897ConfigRequestAdjust (\r
9d34cac8
ED
3898 IN BROWSER_STORAGE *Storage,\r
3899 IN CHAR16 *Request,\r
3900 IN BOOLEAN RespString\r
efffd9c1
ED
3901 )\r
3902{\r
3903 CHAR16 *RequestElement;\r
3904 CHAR16 *NextRequestElement;\r
9d34cac8 3905 CHAR16 *NextElementBakup;\r
efffd9c1
ED
3906 UINTN SpareBufLen;\r
3907 CHAR16 *SearchKey;\r
9d34cac8 3908 CHAR16 *ValueKey;\r
efffd9c1 3909 BOOLEAN RetVal;\r
9d34cac8 3910 CHAR16 *ConfigRequest;\r
efffd9c1
ED
3911\r
3912 SpareBufLen = 0;\r
efffd9c1 3913 RetVal = FALSE;\r
9d34cac8
ED
3914 NextElementBakup = NULL;\r
3915 ValueKey = NULL;\r
efffd9c1 3916\r
9d34cac8
ED
3917 if (Request != NULL) {\r
3918 ConfigRequest = Request;\r
3919 } else {\r
3920 ConfigRequest = Storage->ConfigRequest;\r
3921 }\r
3922\r
3923 if (Storage->ConfigRequest == NULL) {\r
3924 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
efffd9c1
ED
3925 return TRUE;\r
3926 }\r
3927\r
9d34cac8 3928 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
efffd9c1
ED
3929 //\r
3930 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
3931 //\r
3932 SearchKey = L"&";\r
3933 } else {\r
3934 //\r
3935 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
3936 //\r
3937 SearchKey = L"&OFFSET";\r
9d34cac8 3938 ValueKey = L"&VALUE";\r
efffd9c1
ED
3939 }\r
3940\r
efffd9c1
ED
3941 //\r
3942 // Find SearchKey storage\r
3943 //\r
9d34cac8
ED
3944 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3945 RequestElement = StrStr (ConfigRequest, L"PATH");\r
efffd9c1
ED
3946 ASSERT (RequestElement != NULL);\r
3947 RequestElement = StrStr (RequestElement, SearchKey); \r
3948 } else {\r
9d34cac8 3949 RequestElement = StrStr (ConfigRequest, SearchKey);\r
efffd9c1
ED
3950 }\r
3951\r
3952 while (RequestElement != NULL) {\r
9d34cac8 3953\r
efffd9c1
ED
3954 //\r
3955 // +1 to avoid find header itself.\r
3956 //\r
3957 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
3958\r
3959 //\r
3960 // The last Request element in configRequest string.\r
3961 //\r
3962 if (NextRequestElement != NULL) {\r
9d34cac8
ED
3963 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
3964 NextElementBakup = NextRequestElement;\r
3965 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 3966 ASSERT (NextRequestElement != NULL);\r
9d34cac8 3967 }\r
efffd9c1
ED
3968 //\r
3969 // Replace "&" with '\0'.\r
3970 //\r
3971 *NextRequestElement = L'\0';\r
9d34cac8
ED
3972 } else {\r
3973 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
3974 NextElementBakup = NextRequestElement;\r
3975 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 3976 ASSERT (NextRequestElement != NULL);\r
9d34cac8
ED
3977 //\r
3978 // Replace "&" with '\0'.\r
3979 //\r
3980 *NextRequestElement = L'\0';\r
3981 }\r
efffd9c1
ED
3982 }\r
3983 \r
9d34cac8 3984 if (!ElementValidation (Storage, RequestElement)) {\r
efffd9c1
ED
3985 //\r
3986 // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
3987 //\r
9d34cac8 3988 AppendConfigRequest(&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
efffd9c1
ED
3989 RetVal = TRUE;\r
3990 }\r
3991\r
3992 if (NextRequestElement != NULL) {\r
3993 //\r
3994 // Restore '&' with '\0' for later used.\r
3995 //\r
3996 *NextRequestElement = L'&';\r
3997 }\r
3998\r
9d34cac8
ED
3999 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4000 RequestElement = NextElementBakup;\r
4001 } else {\r
4002 RequestElement = NextRequestElement;\r
7c6c064c 4003 }\r
efffd9c1
ED
4004 }\r
4005\r
4006 return RetVal;\r
4007}\r
4008\r
7c6c064c
ED
4009/**\r
4010\r
4011 Base on ConfigRequest info to get default value for current formset. \r
4012\r
4013 ConfigRequest info include the info about which questions in current formset need to \r
4014 get default value. This function only get these questions default value.\r
4015 \r
4016 @param FormSet FormSet data structure.\r
4017 @param Storage Storage need to update value.\r
4018 @param ConfigRequest The config request string.\r
4019\r
4020**/\r
4021VOID\r
4022GetDefaultForFormset (\r
4023 IN FORM_BROWSER_FORMSET *FormSet,\r
4024 IN BROWSER_STORAGE *Storage,\r
4025 IN CHAR16 *ConfigRequest\r
4026 )\r
4027{\r
4028 UINT8 *BackUpBuf;\r
4029 UINTN BufferSize;\r
4030 LIST_ENTRY BackUpList;\r
4031 NAME_VALUE_NODE *Node;\r
4032 LIST_ENTRY *Link;\r
4033 LIST_ENTRY *NodeLink;\r
4034 NAME_VALUE_NODE *TmpNode;\r
4035 EFI_STATUS Status;\r
4036 EFI_STRING Progress;\r
4037 EFI_STRING Result;\r
4038\r
4039 BackUpBuf = NULL;\r
4040 InitializeListHead(&BackUpList);\r
4041\r
4042 //\r
4043 // Back update the edit buffer.\r
4044 // \r
4045 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
4046 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4047 BackUpBuf = AllocateCopyPool (Storage->Size, Storage->EditBuffer);\r
4048 ASSERT (BackUpBuf != NULL);\r
4049 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4050 Link = GetFirstNode (&Storage->NameValueListHead);\r
4051 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
4052 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
4053 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
4054\r
4055 //\r
4056 // Only back Node belong to this formset.\r
4057 //\r
4058 if (StrStr (Storage->ConfigRequest, Node->Name) == NULL) {\r
4059 continue;\r
4060 }\r
4061\r
4062 TmpNode = AllocateCopyPool (sizeof (NAME_VALUE_NODE), Node);\r
523f48e7 4063 ASSERT (TmpNode != NULL);\r
7c6c064c 4064 TmpNode->Name = AllocateCopyPool (StrSize(Node->Name) * sizeof (CHAR16), Node->Name);\r
523f48e7 4065 ASSERT (TmpNode->Name != NULL);\r
7c6c064c 4066 TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
523f48e7 4067 ASSERT (TmpNode->EditValue != NULL);\r
7c6c064c
ED
4068\r
4069 InsertTailList(&BackUpList, &TmpNode->Link);\r
4070 }\r
4071 }\r
4072\r
4073 //\r
4074 // Get default value.\r
4075 //\r
4076 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);\r
4077\r
4078 //\r
4079 // Update the question value based on the input ConfigRequest.\r
4080 //\r
4081 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
4082 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4083 ASSERT (BackUpBuf != NULL);\r
4084 BufferSize = Storage->Size;\r
4085 Status = mHiiConfigRouting->BlockToConfig(\r
4086 mHiiConfigRouting,\r
4087 ConfigRequest,\r
4088 Storage->EditBuffer,\r
4089 BufferSize,\r
4090 &Result,\r
4091 &Progress\r
4092 );\r
4093 ASSERT_EFI_ERROR (Status);\r
4094 \r
4095 Status = mHiiConfigRouting->ConfigToBlock (\r
4096 mHiiConfigRouting,\r
4097 Result,\r
4098 BackUpBuf,\r
4099 &BufferSize,\r
4100 &Progress\r
4101 );\r
4102 ASSERT_EFI_ERROR (Status);\r
4103\r
4104 if (Result != NULL) {\r
4105 FreePool (Result);\r
4106 }\r
4107 \r
4108 CopyMem (Storage->EditBuffer, BackUpBuf, Storage->Size);\r
4109 FreePool (BackUpBuf);\r
4110 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4111 //\r
4112 // Update question value, only element in ConfigReqeust will be update.\r
4113 //\r
4114 Link = GetFirstNode (&BackUpList);\r
4115 while (!IsNull (&BackUpList, Link)) {\r
4116 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
4117 Link = GetNextNode (&BackUpList, Link);\r
4118\r
4119 if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
4120 continue;\r
4121 }\r
4122\r
4123 NodeLink = GetFirstNode (&Storage->NameValueListHead);\r
4124 while (!IsNull (&Storage->NameValueListHead, NodeLink)) {\r
4125 TmpNode = NAME_VALUE_NODE_FROM_LINK (NodeLink);\r
4126 NodeLink = GetNextNode (&Storage->NameValueListHead, NodeLink);\r
4127 \r
4128 if (StrCmp (Node->Name, TmpNode->Name) != 0) {\r
4129 continue;\r
4130 }\r
4131\r
4132 FreePool (TmpNode->EditValue);\r
4133 TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
4134\r
4135 RemoveEntryList (&Node->Link);\r
4136 FreePool (Node->EditValue);\r
4137 FreePool (Node->Name);\r
4138 FreePool (Node);\r
4139 }\r
4140 }\r
4141\r
4142 //\r
4143 // Restore the Name/Value node.\r
4144 // \r
4145 Link = GetFirstNode (&BackUpList);\r
4146 while (!IsNull (&BackUpList, Link)) {\r
4147 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
4148 Link = GetNextNode (&BackUpList, Link);\r
4149 \r
4150 //\r
4151 // Free this node.\r
4152 //\r
4153 RemoveEntryList (&Node->Link);\r
4154 FreePool (Node->EditValue);\r
4155 FreePool (Node->Name);\r
4156 FreePool (Node);\r
4157 }\r
4158 }\r
4159}\r
4160\r
7936fb6a 4161/**\r
4162 Fill storage's edit copy with settings requested from Configuration Driver.\r
4163\r
4164 @param FormSet FormSet data structure.\r
4165 @param Storage Buffer Storage.\r
4166\r
7936fb6a 4167**/\r
7c6c064c 4168VOID\r
7936fb6a 4169LoadStorage (\r
4170 IN FORM_BROWSER_FORMSET *FormSet,\r
4171 IN FORMSET_STORAGE *Storage\r
4172 )\r
4173{\r
4174 EFI_STATUS Status;\r
4175 EFI_STRING Progress;\r
4176 EFI_STRING Result;\r
4177 CHAR16 *StrPtr;\r
98c4caa1
ED
4178 EFI_STRING ConfigRequest;\r
4179 UINTN StrLen;\r
4180\r
4181 ConfigRequest = NULL;\r
7936fb6a 4182\r
7c6c064c
ED
4183 switch (Storage->BrowserStorage->Type) {\r
4184 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
4185 return;\r
4186\r
4187 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
6e74560f 4188 if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
9d34cac8 4189 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
7c6c064c
ED
4190 return;\r
4191 }\r
7c6c064c 4192 break;\r
cce6230f 4193\r
7c6c064c
ED
4194 case EFI_HII_VARSTORE_BUFFER:\r
4195 case EFI_HII_VARSTORE_NAME_VALUE:\r
4196 //\r
27c304f4 4197 // Skip if there is no RequestElement.\r
7c6c064c 4198 //\r
27c304f4 4199 if (Storage->ElementCount == 0) {\r
7c6c064c
ED
4200 return;\r
4201 }\r
27c304f4
ED
4202\r
4203 //\r
4204 // Just update the ConfigRequest, if storage already initialized. \r
4205 //\r
4206 if (Storage->BrowserStorage->Initialized) {\r
9d34cac8 4207 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
27c304f4
ED
4208 return;\r
4209 }\r
4210\r
fae73624 4211 Storage->BrowserStorage->Initialized = TRUE;\r
7c6c064c 4212 break;\r
7936fb6a 4213\r
7c6c064c 4214 default:\r
7248790e 4215 return;\r
7936fb6a 4216 }\r
7248790e 4217\r
27c304f4
ED
4218 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
4219 //\r
4220 // Create the config request string to get all fields for this storage.\r
4221 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
4222 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
4223 //\r
4224 StrLen = StrSize (Storage->BrowserStorage->ConfigHdr) + 20 * sizeof (CHAR16);\r
4225 ConfigRequest = AllocateZeroPool (StrLen);\r
4226 ASSERT (ConfigRequest != NULL);\r
4227 UnicodeSPrint (\r
4228 ConfigRequest, \r
4229 StrLen, \r
4230 L"%s&OFFSET=0&WIDTH=%04x", \r
4231 Storage->BrowserStorage->ConfigHdr,\r
4232 Storage->BrowserStorage->Size);\r
4233 } else {\r
4234 ConfigRequest = Storage->ConfigRequest;\r
4235 }\r
4236\r
7248790e
ED
4237 //\r
4238 // Request current settings from Configuration Driver\r
4239 //\r
4240 Status = mHiiConfigRouting->ExtractConfig (\r
4241 mHiiConfigRouting,\r
98c4caa1 4242 ConfigRequest,\r
7248790e
ED
4243 &Progress,\r
4244 &Result\r
4245 );\r
4246\r
4247 //\r
4248 // If get value fail, extract default from IFR binary\r
4249 //\r
4250 if (EFI_ERROR (Status)) {\r
4251 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE);\r
4252 } else {\r
4253 //\r
4254 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
4255 //\r
4256 StrPtr = StrStr (Result, L"&GUID=");\r
4257 if (StrPtr != NULL) {\r
4258 *StrPtr = L'\0';\r
4259 }\r
4260 \r
4261 Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
4262 FreePool (Result);\r
4263 }\r
4264\r
4265 Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
4266\r
4267 //\r
4268 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
4269 //\r
4270 SynchronizeStorage(FormSet, Storage->BrowserStorage, NULL, TRUE);\r
98c4caa1 4271\r
27c304f4 4272 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
98c4caa1
ED
4273 if (ConfigRequest != NULL) {\r
4274 FreePool (ConfigRequest);\r
4275 }\r
4276 }\r
7936fb6a 4277}\r
4278\r
892eccc8
ED
4279/**\r
4280 Get Value changed status from old question.\r
4281\r
4282 @param NewFormSet FormSet data structure.\r
4283 @param OldQuestion Old question which has value changed.\r
4284\r
4285**/\r
4286VOID\r
4287SyncStatusForQuestion (\r
4288 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
4289 IN FORM_BROWSER_STATEMENT *OldQuestion\r
4290 )\r
4291{\r
4292 LIST_ENTRY *Link;\r
4293 LIST_ENTRY *QuestionLink;\r
4294 FORM_BROWSER_FORM *Form;\r
4295 FORM_BROWSER_STATEMENT *Question;\r
4296\r
4297 //\r
4298 // For each form in one formset.\r
4299 //\r
4300 Link = GetFirstNode (&NewFormSet->FormListHead);\r
4301 while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
4302 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
4303 Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
4304\r
4305 //\r
4306 // for each question in one form.\r
4307 //\r
4308 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
4309 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
4310 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
4311 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
4312\r
4313 if (Question->QuestionId == OldQuestion->QuestionId) {\r
4314 Question->ValueChanged = TRUE;\r
4315 return;\r
4316 }\r
4317 }\r
4318 }\r
4319}\r
4320\r
4321/**\r
4322 Get Value changed status from old formset.\r
4323\r
4324 @param NewFormSet FormSet data structure.\r
4325 @param OldFormSet FormSet data structure.\r
4326\r
4327**/\r
4328VOID\r
4329SyncStatusForFormSet (\r
4330 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
4331 IN FORM_BROWSER_FORMSET *OldFormSet\r
4332 )\r
4333{\r
4334 LIST_ENTRY *Link;\r
4335 LIST_ENTRY *QuestionLink;\r
4336 FORM_BROWSER_FORM *Form;\r
4337 FORM_BROWSER_STATEMENT *Question;\r
4338\r
4339 //\r
4340 // For each form in one formset.\r
4341 //\r
4342 Link = GetFirstNode (&OldFormSet->FormListHead);\r
4343 while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
4344 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
4345 Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
4346\r
4347 //\r
4348 // for each question in one form.\r
4349 //\r
4350 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
4351 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
4352 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
4353 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
4354\r
4355 if (!Question->ValueChanged) {\r
4356 continue;\r
4357 }\r
4358\r
4359 //\r
4360 // Find the same question in new formset and update the value changed flag.\r
4361 //\r
4362 SyncStatusForQuestion (NewFormSet, Question);\r
4363 }\r
4364 }\r
4365}\r
4366\r
7936fb6a 4367/**\r
4368 Get current setting of Questions.\r
4369\r
4370 @param FormSet FormSet data structure.\r
4371\r
7936fb6a 4372**/\r
7c6c064c 4373VOID\r
7936fb6a 4374InitializeCurrentSetting (\r
4375 IN OUT FORM_BROWSER_FORMSET *FormSet\r
4376 )\r
4377{\r
4378 LIST_ENTRY *Link;\r
4379 FORMSET_STORAGE *Storage;\r
7c6c064c 4380 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 4381\r
6e74560f
ED
4382 //\r
4383 // Try to find pre FormSet in the maintain backup list.\r
4384 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
4385 //\r
4386 OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
4387 if (OldFormSet != NULL) {\r
892eccc8 4388 SyncStatusForFormSet (FormSet, OldFormSet);\r
6e74560f
ED
4389 RemoveEntryList (&OldFormSet->Link);\r
4390 DestroyFormSet (OldFormSet);\r
4391 }\r
4392 InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
4393\r
1deb5cab
ED
4394 //\r
4395 // Extract default from IFR binary for no storage questions.\r
4396 // \r
4397 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE);\r
4398\r
7936fb6a 4399 //\r
4400 // Request current settings from Configuration Driver\r
4401 //\r
4402 Link = GetFirstNode (&FormSet->StorageListHead);\r
4403 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4404 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
4405\r
7c6c064c 4406 LoadStorage (FormSet, Storage);\r
7936fb6a 4407\r
7936fb6a 4408 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4409 }\r
7936fb6a 4410}\r
4411\r
4412\r
4413/**\r
4414 Fetch the Ifr binary data of a FormSet.\r
4415\r
4416 @param Handle PackageList Handle\r
f5006bd9 4417 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
4418 specified (NULL or zero GUID), take the first\r
4419 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
4420 found in package list.\r
4421 On output, GUID of the formset found(if not NULL).\r
7936fb6a 4422 @param BinaryLength The length of the FormSet IFR binary.\r
4423 @param BinaryData The buffer designed to receive the FormSet.\r
4424\r
4425 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
4426 BufferLength was updated.\r
4427 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
4428 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
4429 be found with the requested FormId.\r
4430\r
4431**/\r
4432EFI_STATUS\r
4433GetIfrBinaryData (\r
4434 IN EFI_HII_HANDLE Handle,\r
4435 IN OUT EFI_GUID *FormSetGuid,\r
4436 OUT UINTN *BinaryLength,\r
4437 OUT UINT8 **BinaryData\r
4438 )\r
4439{\r
4440 EFI_STATUS Status;\r
4441 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
4442 UINTN BufferSize;\r
4443 UINT8 *Package;\r
4444 UINT8 *OpCodeData;\r
4445 UINT32 Offset;\r
4446 UINT32 Offset2;\r
7936fb6a 4447 UINT32 PackageListLength;\r
4448 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
4449 UINT8 Index;\r
4450 UINT8 NumberOfClassGuid;\r
f5006bd9 4451 BOOLEAN ClassGuidMatch;\r
0a1147ed 4452 EFI_GUID *ClassGuid;\r
f5006bd9 4453 EFI_GUID *ComparingGuid;\r
7936fb6a 4454\r
4455 OpCodeData = NULL;\r
4456 Package = NULL;\r
0c66bc76 4457 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 4458\r
4459 //\r
f5006bd9 4460 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 4461 //\r
48a9d5f7
LG
4462 if (FormSetGuid == NULL) {\r
4463 ComparingGuid = &gZeroGuid;\r
7936fb6a 4464 } else {\r
f5006bd9 4465 ComparingGuid = FormSetGuid;\r
7936fb6a 4466 }\r
4467\r
4468 //\r
4469 // Get HII PackageList\r
4470 //\r
4471 BufferSize = 0;\r
4472 HiiPackageList = NULL;\r
4473 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
4474 if (Status == EFI_BUFFER_TOO_SMALL) {\r
4475 HiiPackageList = AllocatePool (BufferSize);\r
4476 ASSERT (HiiPackageList != NULL);\r
4477\r
4478 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
4479 }\r
4480 if (EFI_ERROR (Status)) {\r
4481 return Status;\r
4482 }\r
db0bd81c 4483 ASSERT (HiiPackageList != NULL);\r
d66e6c16 4484\r
7936fb6a 4485 //\r
4486 // Get Form package from this HII package List\r
4487 //\r
4488 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
4489 Offset2 = 0;\r
4490 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
4491\r
f5006bd9 4492 ClassGuidMatch = FALSE;\r
7936fb6a 4493 while (Offset < PackageListLength) {\r
4494 Package = ((UINT8 *) HiiPackageList) + Offset;\r
4495 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
4496\r
8d00a0f1 4497 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 4498 //\r
4499 // Search FormSet in this Form Package\r
4500 //\r
4501 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
4502 while (Offset2 < PackageHeader.Length) {\r
4503 OpCodeData = Package + Offset2;\r
4504\r
4505 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
4506 //\r
f5006bd9 4507 // Try to compare against formset GUID\r
7936fb6a 4508 //\r
48a9d5f7
LG
4509 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
4510 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 4511 break;\r
7936fb6a 4512 }\r
4513\r
d228526f
LG
4514 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
4515 //\r
4516 // Try to compare against formset class GUID\r
4517 //\r
4518 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
4519 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
4520 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
4521 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
4522 ClassGuidMatch = TRUE;\r
4523 break;\r
4524 }\r
4525 }\r
4526 if (ClassGuidMatch) {\r
f5006bd9 4527 break;\r
4528 }\r
d228526f
LG
4529 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
4530 ClassGuidMatch = TRUE;\r
7936fb6a 4531 break;\r
4532 }\r
4533 }\r
4534\r
4535 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
4536 }\r
4537\r
4538 if (Offset2 < PackageHeader.Length) {\r
4539 //\r
4540 // Target formset found\r
4541 //\r
4542 break;\r
4543 }\r
4544 }\r
4545\r
4546 Offset += PackageHeader.Length;\r
4547 }\r
4548\r
4549 if (Offset >= PackageListLength) {\r
4550 //\r
4551 // Form package not found in this Package List\r
4552 //\r
f4113e1f 4553 FreePool (HiiPackageList);\r
7936fb6a 4554 return EFI_NOT_FOUND;\r
4555 }\r
4556\r
48a9d5f7 4557 if (FormSetGuid != NULL) {\r
7936fb6a 4558 //\r
f5006bd9 4559 // Return the FormSet GUID\r
7936fb6a 4560 //\r
4561 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
4562 }\r
4563\r
4564 //\r
4565 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
4566 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
4567 // of the Form Package.\r
4568 //\r
4569 *BinaryLength = PackageHeader.Length - Offset2;\r
4570 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
4571\r
f4113e1f 4572 FreePool (HiiPackageList);\r
7936fb6a 4573\r
4574 if (*BinaryData == NULL) {\r
4575 return EFI_OUT_OF_RESOURCES;\r
4576 }\r
4577\r
4578 return EFI_SUCCESS;\r
4579}\r
4580\r
4581\r
4582/**\r
4583 Initialize the internal data structure of a FormSet.\r
4584\r
4585 @param Handle PackageList Handle\r
f5006bd9 4586 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
4587 specified (NULL or zero GUID), take the first\r
4588 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
4589 found in package list.\r
4590 On output, GUID of the formset found(if not NULL).\r
7936fb6a 4591 @param FormSet FormSet data structure.\r
4592\r
4593 @retval EFI_SUCCESS The function completed successfully.\r
4594 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
4595\r
4596**/\r
4597EFI_STATUS\r
4598InitializeFormSet (\r
4599 IN EFI_HII_HANDLE Handle,\r
4600 IN OUT EFI_GUID *FormSetGuid,\r
7c6c064c 4601 OUT FORM_BROWSER_FORMSET *FormSet\r
7936fb6a 4602 )\r
4603{\r
4604 EFI_STATUS Status;\r
4605 EFI_HANDLE DriverHandle;\r
7936fb6a 4606\r
4607 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
4608 if (EFI_ERROR (Status)) {\r
4609 return Status;\r
4610 }\r
4611\r
48a9d5f7 4612 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 4613 FormSet->HiiHandle = Handle;\r
4614 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
7c6c064c 4615 FormSet->QuestionInited = FALSE;\r
7936fb6a 4616\r
4617 //\r
4618 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
4619 //\r
4620 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
4621 if (EFI_ERROR (Status)) {\r
4622 return Status;\r
4623 }\r
4624 FormSet->DriverHandle = DriverHandle;\r
4625 Status = gBS->HandleProtocol (\r
4626 DriverHandle,\r
4627 &gEfiHiiConfigAccessProtocolGuid,\r
4628 (VOID **) &FormSet->ConfigAccess\r
4629 );\r
4630 if (EFI_ERROR (Status)) {\r
4631 //\r
4632 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
4633 // list, then there will be no configuration action required\r
4634 //\r
4635 FormSet->ConfigAccess = NULL;\r
4636 }\r
4637\r
4638 //\r
4639 // Parse the IFR binary OpCodes\r
4640 //\r
4641 Status = ParseOpCodes (FormSet);\r
25361615 4642\r
7c6c064c 4643 return Status;\r
7936fb6a 4644}\r
ce6d12cc 4645\r
4646\r
4647/**\r
4648 Save globals used by previous call to SendForm(). SendForm() may be called from \r
4649 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
4650 So, save globals of previous call to SendForm() and restore them upon exit.\r
4651\r
4652**/\r
4653VOID\r
4654SaveBrowserContext (\r
4655 VOID\r
4656 )\r
4657{\r
4658 BROWSER_CONTEXT *Context;\r
7c6c064c 4659 FORM_ENTRY_INFO *MenuList;\r
ce6d12cc 4660\r
4661 gBrowserContextCount++;\r
4662 if (gBrowserContextCount == 1) {\r
4663 //\r
4664 // This is not reentry of SendForm(), no context to save\r
4665 //\r
4666 return;\r
4667 }\r
4668\r
4669 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
4670 ASSERT (Context != NULL);\r
4671\r
4672 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
4673\r
4674 //\r
4675 // Save FormBrowser context\r
4676 //\r
5a9f73bf 4677 Context->Selection = gCurrentSelection;\r
ce6d12cc 4678 Context->ResetRequired = gResetRequired;\r
7c6c064c
ED
4679 Context->ExitRequired = gExitRequired;\r
4680 Context->HiiHandle = mCurrentHiiHandle;\r
5a9f73bf
ED
4681 Context->FormId = mCurrentFormId;\r
4682 CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
7c6c064c
ED
4683\r
4684 //\r
4685 // Save the menu history data.\r
4686 //\r
4687 InitializeListHead(&Context->FormHistoryList);\r
4688 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
4689 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
4690 RemoveEntryList (&MenuList->Link);\r
4691\r
4692 InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
4693 }\r
ce6d12cc 4694\r
4695 //\r
4696 // Insert to FormBrowser context list\r
4697 //\r
4698 InsertHeadList (&gBrowserContextList, &Context->Link);\r
4699}\r
4700\r
4701\r
4702/**\r
4703 Restore globals used by previous call to SendForm().\r
4704\r
4705**/\r
4706VOID\r
4707RestoreBrowserContext (\r
4708 VOID\r
4709 )\r
4710{\r
4711 LIST_ENTRY *Link;\r
4712 BROWSER_CONTEXT *Context;\r
7c6c064c 4713 FORM_ENTRY_INFO *MenuList;\r
ce6d12cc 4714\r
4715 ASSERT (gBrowserContextCount != 0);\r
4716 gBrowserContextCount--;\r
4717 if (gBrowserContextCount == 0) {\r
4718 //\r
4719 // This is not reentry of SendForm(), no context to restore\r
4720 //\r
4721 return;\r
4722 }\r
4723\r
4724 ASSERT (!IsListEmpty (&gBrowserContextList));\r
4725\r
4726 Link = GetFirstNode (&gBrowserContextList);\r
4727 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
4728\r
4729 //\r
4730 // Restore FormBrowser context\r
4731 //\r
5a9f73bf 4732 gCurrentSelection = Context->Selection;\r
ce6d12cc 4733 gResetRequired = Context->ResetRequired;\r
7c6c064c
ED
4734 gExitRequired = Context->ExitRequired;\r
4735 mCurrentHiiHandle = Context->HiiHandle;\r
5a9f73bf
ED
4736 mCurrentFormId = Context->FormId;\r
4737 CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
7c6c064c
ED
4738\r
4739 //\r
4740 // Restore the menu history data.\r
4741 //\r
4742 while (!IsListEmpty (&Context->FormHistoryList)) {\r
4743 MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
4744 RemoveEntryList (&MenuList->Link);\r
4745\r
4746 InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
4747 }\r
ce6d12cc 4748\r
4749 //\r
4750 // Remove from FormBrowser context list\r
4751 //\r
4752 RemoveEntryList (&Context->Link);\r
4753 gBS->FreePool (Context);\r
4754}\r
48a9d5f7
LG
4755\r
4756/**\r
4757 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
4758 \r
4759 @param Handle The Hii Handle.\r
4760 \r
4761 @return the found FormSet context. If no found, NULL will return.\r
4762\r
4763**/\r
4764FORM_BROWSER_FORMSET * \r
4765GetFormSetFromHiiHandle (\r
4766 EFI_HII_HANDLE Handle\r
4767 )\r
4768{\r
4769 LIST_ENTRY *Link;\r
4770 FORM_BROWSER_FORMSET *FormSet;\r
4771\r
4772 Link = GetFirstNode (&gBrowserFormSetList);\r
4773 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4774 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
4775 Link = GetNextNode (&gBrowserFormSetList, Link);\r
4776 if (!ValidateFormSet(FormSet)) {\r
4777 continue;\r
4778 }\r
48a9d5f7
LG
4779 if (FormSet->HiiHandle == Handle) {\r
4780 return FormSet;\r
4781 }\r
48a9d5f7
LG
4782 }\r
4783 \r
4784 return NULL;\r
4785}\r
4786\r
4787/**\r
4788 Check whether the input HII handle is the FormSet that is being used.\r
4789 \r
4790 @param Handle The Hii Handle.\r
4791 \r
4792 @retval TRUE HII handle is being used.\r
4793 @retval FALSE HII handle is not being used.\r
4794\r
4795**/\r
4796BOOLEAN\r
4797IsHiiHandleInBrowserContext (\r
4798 EFI_HII_HANDLE Handle\r
4799 )\r
4800{\r
4801 LIST_ENTRY *Link;\r
4802 BROWSER_CONTEXT *Context;\r
4803\r
4804 //\r
4805 // HiiHandle is Current FormSet.\r
4806 //\r
7c6c064c 4807 if (mCurrentHiiHandle == Handle) {\r
48a9d5f7
LG
4808 return TRUE;\r
4809 }\r
4810\r
4811 //\r
4812 // Check whether HiiHandle is in BrowserContext.\r
4813 //\r
4814 Link = GetFirstNode (&gBrowserContextList);\r
4815 while (!IsNull (&gBrowserContextList, Link)) {\r
4816 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
7c6c064c 4817 if (Context->HiiHandle == Handle) {\r
48a9d5f7
LG
4818 //\r
4819 // HiiHandle is in BrowserContext\r
4820 //\r
4821 return TRUE;\r
4822 }\r
4823 Link = GetNextNode (&gBrowserContextList, Link);\r
4824 }\r
4825 \r
4826 return FALSE;\r
4827}\r
4828\r
7c6c064c
ED
4829/**\r
4830 Perform Password check. \r
4831 Passwork may be encrypted by driver that requires the specific check.\r
4832 \r
4833 @param Form Form where Password Statement is in.\r
4834 @param Statement Password statement\r
4835 @param PasswordString Password string to be checked. It may be NULL.\r
4836 NULL means to restore password.\r
4837 "" string can be used to checked whether old password does exist.\r
4838 \r
4839 @return Status Status of Password check.\r
4840**/\r
4841EFI_STATUS\r
4842EFIAPI\r
4843PasswordCheck (\r
4844 IN FORM_DISPLAY_ENGINE_FORM *Form,\r
4845 IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
4846 IN EFI_STRING PasswordString OPTIONAL\r
4847 )\r
4848{\r
4849 EFI_STATUS Status;\r
4850 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4851 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
4852 EFI_IFR_TYPE_VALUE IfrTypeValue;\r
4853 FORM_BROWSER_STATEMENT *Question;\r
4854\r
4855 ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
4856 Question = GetBrowserStatement(Statement);\r
4857 ASSERT (Question != NULL);\r
4858\r
4859 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
4860 if (ConfigAccess == NULL) {\r
4861 return EFI_UNSUPPORTED;\r
4862 }\r
4863 } else {\r
4864 if (PasswordString == NULL) {\r
4865 return EFI_SUCCESS;\r
4866 } \r
27582c41
ED
4867\r
4868 //\r
4869 // Check whether has preexisted password.\r
4870 //\r
4871 if (PasswordString[0] == 0) {\r
4872 if (*((CHAR16 *) Question->BufferValue) == 0) {\r
4873 return EFI_SUCCESS;\r
4874 } else {\r
4875 return EFI_NOT_READY;\r
4876 }\r
4877 }\r
4878\r
4879 //\r
4880 // Check whether the input password is same as preexisted password.\r
4881 //\r
7c6c064c
ED
4882 if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
4883 return EFI_SUCCESS;\r
4884 } else {\r
4885 return EFI_NOT_READY;\r
4886 }\r
4887 }\r
4888 \r
4889 //\r
4890 // Prepare password string in HII database\r
4891 //\r
4892 if (PasswordString != NULL) {\r
4893 IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
4894 } else {\r
4895 IfrTypeValue.string = 0;\r
4896 }\r
4897\r
4898 //\r
4899 // Send password to Configuration Driver for validation\r
4900 //\r
4901 Status = ConfigAccess->Callback (\r
4902 ConfigAccess,\r
4903 EFI_BROWSER_ACTION_CHANGING,\r
4904 Question->QuestionId,\r
4905 Question->HiiValue.Type,\r
4906 &IfrTypeValue,\r
4907 &ActionRequest\r
4908 );\r
4909\r
4910 //\r
4911 // Remove password string from HII database\r
4912 //\r
4913 if (PasswordString != NULL) {\r
4914 DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
4915 }\r
4916\r
4917 return Status;\r
4918}\r
4919\r
48a9d5f7
LG
4920/**\r
4921 Find the registered HotKey based on KeyData.\r
4922 \r
4923 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
4924 information for the hot key.\r
4925\r
4926 @return The registered HotKey context. If no found, NULL will return.\r
4927**/\r
4928BROWSER_HOT_KEY *\r
4929GetHotKeyFromRegisterList (\r
4930 IN EFI_INPUT_KEY *KeyData\r
4931 )\r
4932{\r
4933 LIST_ENTRY *Link;\r
4934 BROWSER_HOT_KEY *HotKey;\r
4935\r
4936 Link = GetFirstNode (&gBrowserHotKeyList);\r
4937 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
4938 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
4939 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
4940 return HotKey;\r
4941 }\r
4942 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
4943 }\r
4944 \r
4945 return NULL;\r
4946}\r
4947\r
4948/**\r
4949 Configure what scope the hot key will impact.\r
4950 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
4951 If no scope is set, the default scope will be FormSet level.\r
4952 After all registered hot keys are removed, previous Scope can reset to another level.\r
4953 \r
4954 @param[in] Scope Scope level to be set. \r
4955 \r
4956 @retval EFI_SUCCESS Scope is set correctly.\r
4957 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
4958 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
4959\r
4960**/\r
4961EFI_STATUS\r
4962EFIAPI\r
4963SetScope (\r
4964 IN BROWSER_SETTING_SCOPE Scope\r
4965 )\r
4966{\r
4967 if (Scope >= MaxLevel) {\r
4968 return EFI_INVALID_PARAMETER;\r
4969 }\r
7c6c064c 4970\r
48a9d5f7
LG
4971 //\r
4972 // When no hot key registered in system or on the first setting,\r
4973 // Scope can be set.\r
4974 //\r
4975 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
4976 gBrowserSettingScope = Scope;\r
4977 mBrowserScopeFirstSet = FALSE;\r
4978 } else if (Scope != gBrowserSettingScope) {\r
4979 return EFI_UNSUPPORTED;\r
4980 }\r
4981\r
4982 return EFI_SUCCESS;\r
4983}\r
4984\r
4985/**\r
4986 Register the hot key with its browser action, or unregistered the hot key.\r
4987 Only support hot key that is not printable character (control key, function key, etc.).\r
4988 If the action value is zero, the hot key will be unregistered if it has been registered.\r
4989 If the same hot key has been registered, the new action and help string will override the previous ones.\r
4990 \r
4991 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
4992 information for the hot key. Its type is EFI_INPUT_KEY to \r
4993 be supported by all ConsoleIn devices.\r
4994 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
4995 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
4996 @param[in] HelpString Help string that describes the hot key information.\r
4997 Its value may be NULL for the unregistered hot key.\r
4998 \r
4999 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
5000 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
5001 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
5002 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
5003**/\r
5004EFI_STATUS\r
5005EFIAPI\r
5006RegisterHotKey (\r
5007 IN EFI_INPUT_KEY *KeyData,\r
5008 IN UINT32 Action,\r
5009 IN UINT16 DefaultId,\r
5010 IN EFI_STRING HelpString OPTIONAL\r
5011 )\r
5012{\r
5013 BROWSER_HOT_KEY *HotKey;\r
5014\r
5015 //\r
5016 // Check input parameters.\r
5017 //\r
5018 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
5019 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
5020 return EFI_INVALID_PARAMETER;\r
5021 }\r
5022\r
5023 //\r
5024 // Check whether the input KeyData is in BrowserHotKeyList.\r
5025 //\r
5026 HotKey = GetHotKeyFromRegisterList (KeyData);\r
5027 \r
5028 //\r
5029 // Unregister HotKey\r
5030 //\r
5031 if (Action == BROWSER_ACTION_UNREGISTER) {\r
5032 if (HotKey != NULL) {\r
5033 //\r
5034 // The registered HotKey is found. \r
5035 // Remove it from List, and free its resource.\r
5036 //\r
5037 RemoveEntryList (&HotKey->Link);\r
5038 FreePool (HotKey->KeyData);\r
5039 FreePool (HotKey->HelpString);\r
5040 return EFI_SUCCESS;\r
5041 } else {\r
5042 //\r
5043 // The registered HotKey is not found. \r
5044 //\r
5045 return EFI_NOT_FOUND;\r
5046 }\r
5047 }\r
5048 \r
5049 //\r
5050 // Register HotKey into List.\r
5051 //\r
5052 if (HotKey == NULL) {\r
5053 //\r
5054 // Create new Key, and add it into List.\r
5055 //\r
5056 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
5057 ASSERT (HotKey != NULL);\r
5058 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
5059 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
5060 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
5061 }\r
5062\r
5063 //\r
5064 // Fill HotKey information.\r
5065 //\r
5066 HotKey->Action = Action;\r
5067 HotKey->DefaultId = DefaultId;\r
5068 if (HotKey->HelpString != NULL) {\r
5069 FreePool (HotKey->HelpString);\r
5070 }\r
5071 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
5072\r
5073 return EFI_SUCCESS;\r
5074}\r
5075\r
5076/**\r
5077 Register Exit handler function. \r
5078 When more than one handler function is registered, the latter one will override the previous one. \r
5079 When NULL handler is specified, the previous Exit handler will be unregistered. \r
5080 \r
5081 @param[in] Handler Pointer to handler function. \r
5082\r
5083**/\r
5084VOID\r
5085EFIAPI\r
5086RegiserExitHandler (\r
5087 IN EXIT_HANDLER Handler\r
5088 )\r
5089{\r
5090 ExitHandlerFunction = Handler;\r
5091 return;\r
5092}\r
5093\r
7c6c064c
ED
5094/**\r
5095 Check whether the browser data has been modified.\r
5096\r
5097 @retval TRUE Browser data is modified.\r
5098 @retval FALSE No browser data is modified.\r
5099\r
5100**/\r
5101BOOLEAN\r
5102EFIAPI\r
5103IsBrowserDataModified (\r
5104 VOID\r
5105 )\r
5106{\r
5107 LIST_ENTRY *Link;\r
5108 FORM_BROWSER_FORMSET *FormSet;\r
5109\r
7c6c064c
ED
5110 switch (gBrowserSettingScope) {\r
5111 case FormLevel:\r
27bace9b
ED
5112 if (gCurrentSelection == NULL) {\r
5113 return FALSE;\r
5114 }\r
7c6c064c
ED
5115 return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
5116\r
5117 case FormSetLevel:\r
27bace9b
ED
5118 if (gCurrentSelection == NULL) {\r
5119 return FALSE;\r
5120 }\r
7c6c064c
ED
5121 return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
5122\r
5123 case SystemLevel:\r
5124 Link = GetFirstNode (&gBrowserFormSetList);\r
5125 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5126 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
27bace9b
ED
5127 if (!ValidateFormSet(FormSet)) {\r
5128 continue;\r
5129 }\r
5130\r
7c6c064c
ED
5131 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
5132 return TRUE;\r
5133 }\r
5134 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5135 }\r
5136 return FALSE;\r
5137\r
5138 default:\r
5139 return FALSE;\r
5140 }\r
5141}\r
5142\r
5143/**\r
5144 Execute the action requested by the Action parameter.\r
5145\r
5146 @param[in] Action Execute the request action.\r
5147 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
5148\r
5149 @retval EFI_SUCCESS Execute the request action succss.\r
5150 @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
5151\r
5152**/\r
5153EFI_STATUS \r
5154EFIAPI\r
5155ExecuteAction (\r
5156 IN UINT32 Action,\r
5157 IN UINT16 DefaultId\r
5158 )\r
5159{\r
27bace9b
ED
5160 EFI_STATUS Status;\r
5161 FORM_BROWSER_FORMSET *FormSet;\r
5162 FORM_BROWSER_FORM *Form;\r
7c6c064c 5163\r
27bace9b 5164 if (gBrowserSettingScope < SystemLevel && gCurrentSelection == NULL) {\r
7c6c064c
ED
5165 return EFI_NOT_READY;\r
5166 }\r
5167\r
27bace9b
ED
5168 Status = EFI_SUCCESS;\r
5169 FormSet = NULL;\r
5170 Form = NULL;\r
5171 if (gBrowserSettingScope < SystemLevel) {\r
5172 FormSet = gCurrentSelection->FormSet;\r
5173 Form = gCurrentSelection->Form; \r
5174 }\r
7c6c064c
ED
5175\r
5176 //\r
5177 // Executet the discard action.\r
5178 //\r
5179 if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
27bace9b 5180 Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5181 if (EFI_ERROR (Status)) {\r
5182 return Status;\r
5183 }\r
5184 }\r
5185\r
5186 //\r
5187 // Executet the difault action.\r
5188 //\r
5189 if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
27bace9b 5190 Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
7c6c064c
ED
5191 if (EFI_ERROR (Status)) {\r
5192 return Status;\r
5193 }\r
892eccc8 5194 UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5195 }\r
5196\r
5197 //\r
5198 // Executet the submit action.\r
5199 //\r
5200 if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
27bace9b 5201 Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5202 if (EFI_ERROR (Status)) {\r
5203 return Status;\r
5204 }\r
5205 }\r
5206\r
5207 //\r
5208 // Executet the reset action.\r
5209 //\r
5210 if ((Action & BROWSER_ACTION_RESET) != 0) {\r
5211 gResetRequired = TRUE;\r
5212 }\r
5213\r
5214 //\r
5215 // Executet the exit action.\r
5216 //\r
5217 if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
27bace9b 5218 DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5219 if (gBrowserSettingScope == SystemLevel) {\r
5220 if (ExitHandlerFunction != NULL) {\r
5221 ExitHandlerFunction ();\r
5222 }\r
5223 }\r
5224\r
5225 gExitRequired = TRUE;\r
5226 }\r
5227\r
5228 return Status;\r
5229}\r
5230\r
48a9d5f7
LG
5231/**\r
5232 Create reminder to let user to choose save or discard the changed browser data.\r
5233 Caller can use it to actively check the changed browser data.\r
5234\r
5235 @retval BROWSER_NO_CHANGES No browser data is changed.\r
5236 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
5237 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
27bace9b 5238 @retval BROWSER_KEEP_CURRENT Browser keep current changes.\r
48a9d5f7
LG
5239\r
5240**/\r
5241UINT32\r
5242EFIAPI\r
5243SaveReminder (\r
5244 VOID\r
5245 )\r
5246{\r
5247 LIST_ENTRY *Link;\r
5248 FORM_BROWSER_FORMSET *FormSet;\r
5249 BOOLEAN IsDataChanged;\r
5250 UINT32 DataSavedAction;\r
27bace9b 5251 UINT32 ConfirmRet;\r
48a9d5f7
LG
5252\r
5253 DataSavedAction = BROWSER_NO_CHANGES;\r
5254 IsDataChanged = FALSE;\r
5255 Link = GetFirstNode (&gBrowserFormSetList);\r
5256 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5257 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
5258 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5259 if (!ValidateFormSet(FormSet)) {\r
5260 continue;\r
5261 }\r
7c6c064c 5262 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
48a9d5f7
LG
5263 IsDataChanged = TRUE;\r
5264 break;\r
5265 }\r
48a9d5f7
LG
5266 }\r
5267 \r
5268 //\r
5269 // No data is changed. No save is required. \r
5270 //\r
5271 if (!IsDataChanged) {\r
5272 return DataSavedAction;\r
5273 }\r
5274 \r
5275 //\r
7c6c064c 5276 // If data is changed, prompt user to save or discard it. \r
48a9d5f7 5277 //\r
48a9d5f7 5278 do {\r
27bace9b 5279 ConfirmRet = (UINT32) mFormDisplay->ConfirmDataChange();\r
48a9d5f7 5280\r
27bace9b 5281 if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
7c6c064c 5282 SubmitForm (NULL, NULL, SystemLevel);\r
27bace9b 5283 DataSavedAction = BROWSER_SAVE_CHANGES;\r
7c6c064c 5284 break;\r
27bace9b 5285 } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
7c6c064c 5286 DiscardForm (NULL, NULL, SystemLevel);\r
27bace9b
ED
5287 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
5288 break;\r
5289 } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
5290 DataSavedAction = BROWSER_KEEP_CURRENT;\r
7c6c064c
ED
5291 break;\r
5292 }\r
5293 } while (1);\r
48a9d5f7
LG
5294\r
5295 return DataSavedAction;\r
5296}\r
7da62bc0
ED
5297\r
5298/**\r
5299 Check whether the Reset Required for the browser\r
5300\r
5301 @retval TRUE Browser required to reset after exit.\r
5302 @retval FALSE Browser not need to reset after exit.\r
5303\r
5304**/\r
5305BOOLEAN\r
5306EFIAPI\r
5307IsResetRequired (\r
5308 VOID\r
5309 )\r
5310{\r
5311 return gResetRequired;\r
5312}\r
5313\r