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