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