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