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