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