]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Add type cast to avoid sign extension on x64 tip.
[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
3029\r
3030 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
3031 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
3032 ) {\r
3033 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
3034\r
3035 return EFI_SUCCESS;\r
3036 }\r
3037\r
3038 Link = GetNextNode (&Question->OptionListHead, Link);\r
3039 }\r
3040 }\r
3041 }\r
3042\r
3043 //\r
3044 // EFI_IFR_CHECKBOX - lowest priority\r
3045 //\r
3046 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
3047 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3048 //\r
3049 // Checkbox could only provide Standard and Manufacturing default\r
3050 //\r
3051 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
3052 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
3053 ) {\r
3054 HiiValue->Value.b = TRUE;\r
3055 } else {\r
3056 HiiValue->Value.b = FALSE;\r
3057 }\r
3058\r
3059 return EFI_SUCCESS;\r
3060 }\r
3061 }\r
3062\r
3063 //\r
3064 // For Questions without default\r
3065 //\r
48a9d5f7 3066 Status = EFI_NOT_FOUND;\r
7936fb6a 3067 switch (Question->Operand) {\r
cf4c5a42
LG
3068 case EFI_IFR_NUMERIC_OP:\r
3069 //\r
3070 // Take minimum value as numeric default value\r
3071 //\r
3072 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
3073 HiiValue->Value.u64 = Question->Minimum;\r
48a9d5f7 3074 Status = EFI_SUCCESS;\r
cf4c5a42
LG
3075 }\r
3076 break;\r
3077\r
7936fb6a 3078 case EFI_IFR_ONE_OF_OP:\r
3079 //\r
3080 // Take first oneof option as oneof's default value\r
3081 //\r
d66e6c16 3082 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed
LG
3083 Link = GetFirstNode (&Question->OptionListHead);\r
3084 if (!IsNull (&Question->OptionListHead, Link)) {\r
3085 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3086 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 3087 Status = EFI_SUCCESS;\r
0a1147ed 3088 }\r
7936fb6a 3089 }\r
3090 break;\r
3091\r
3092 case EFI_IFR_ORDERED_LIST_OP:\r
3093 //\r
3094 // Take option sequence in IFR as ordered list's default value\r
3095 //\r
3096 Index = 0;\r
3097 Link = GetFirstNode (&Question->OptionListHead);\r
3098 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 3099 Status = EFI_SUCCESS;\r
7936fb6a 3100 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3101\r
d02847d3 3102 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 3103\r
3104 Index++;\r
3105 if (Index >= Question->MaxContainers) {\r
3106 break;\r
3107 }\r
3108\r
3109 Link = GetNextNode (&Question->OptionListHead, Link);\r
3110 }\r
3111 break;\r
3112\r
3113 default:\r
7936fb6a 3114 break;\r
3115 }\r
3116\r
3117 return Status;\r
3118}\r
3119\r
3120\r
3121/**\r
9776099f 3122 Reset Questions to their initial value or default value in a Form, Formset or System.\r
7936fb6a 3123\r
09cdd7d2
ED
3124 GetDefaultValueScope parameter decides which questions will reset \r
3125 to its default value.\r
3126\r
7936fb6a 3127 @param FormSet FormSet data structure.\r
48a9d5f7 3128 @param Form Form data structure.\r
7936fb6a 3129 @param DefaultId The Class of the default.\r
48a9d5f7 3130 @param SettingScope Setting Scope for Default action.\r
09cdd7d2 3131 @param GetDefaultValueScope Get default value scope.\r
3347d410 3132 @param Storage Get default value only for this storage.\r
9776099f
ED
3133 @param RetrieveValueFirst Whether call the retrieve call back to\r
3134 get the initial value before get default\r
3135 value.\r
7936fb6a 3136\r
3137 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 3138 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 3139\r
3140**/\r
3141EFI_STATUS\r
48a9d5f7 3142ExtractDefault (\r
7936fb6a 3143 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
3144 IN FORM_BROWSER_FORM *Form,\r
3145 IN UINT16 DefaultId,\r
3347d410 3146 IN BROWSER_SETTING_SCOPE SettingScope,\r
09cdd7d2 3147 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
9776099f
ED
3148 IN FORMSET_STORAGE *Storage OPTIONAL,\r
3149 IN BOOLEAN RetrieveValueFirst\r
7936fb6a 3150 )\r
3151{\r
3152 EFI_STATUS Status;\r
4f33c838 3153 LIST_ENTRY *FormLink;\r
48a9d5f7 3154 LIST_ENTRY *Link;\r
7936fb6a 3155 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7
LG
3156 FORM_BROWSER_FORMSET *BackUpFormSet;\r
3157 FORM_BROWSER_FORMSET *LocalFormSet;\r
3158 EFI_HII_HANDLE *HiiHandles;\r
3159 UINTN Index;\r
3160 EFI_GUID ZeroGuid;\r
7936fb6a 3161\r
9776099f
ED
3162 Status = EFI_SUCCESS;\r
3163\r
48a9d5f7
LG
3164 //\r
3165 // Check the supported setting level.\r
3166 //\r
09cdd7d2
ED
3167 if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
3168 return EFI_UNSUPPORTED;\r
3169 }\r
3170\r
3171 if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
48a9d5f7
LG
3172 return EFI_UNSUPPORTED;\r
3173 }\r
3174 \r
3175 if (SettingScope == FormLevel) {\r
8d00a0f1 3176 //\r
4f33c838 3177 // Extract Form default\r
8d00a0f1 3178 //\r
48a9d5f7
LG
3179 Link = GetFirstNode (&Form->StatementListHead);\r
3180 while (!IsNull (&Form->StatementListHead, Link)) {\r
3181 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3182 Link = GetNextNode (&Form->StatementListHead, Link);\r
3347d410
ED
3183\r
3184 //\r
3185 // If get default value only for this storage, check the storage first.\r
3186 //\r
09cdd7d2
ED
3187 if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
3188 continue;\r
3189 }\r
3190\r
3191 //\r
3192 // If get default value only for no storage question, just skip the question which has storage.\r
3193 //\r
3194 if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
3347d410
ED
3195 continue;\r
3196 }\r
3197\r
4f33c838
ED
3198 //\r
3199 // If Question is disabled, don't reset it to default\r
3200 //\r
31585af4
ED
3201 if (Question->Expression != NULL) {\r
3202 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4f33c838
ED
3203 continue;\r
3204 }\r
8d00a0f1 3205 }\r
9776099f
ED
3206\r
3207 if (RetrieveValueFirst) {\r
3208 //\r
3209 // Call the Retrieve call back to get the initial question value.\r
3210 //\r
3211 Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question);\r
3212 }\r
3213\r
4f33c838 3214 //\r
9776099f 3215 // If not request to get the initial value or get initial value fail, then get default value.\r
4f33c838 3216 //\r
9776099f
ED
3217 if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
3218 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
3219 if (EFI_ERROR (Status)) {\r
3220 continue;\r
3221 }\r
4f33c838 3222 }\r
9776099f 3223\r
4f33c838
ED
3224 //\r
3225 // Synchronize Buffer storage's Edit buffer\r
3226 //\r
3227 if ((Question->Storage != NULL) &&\r
3228 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
816a7110 3229 SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
48a9d5f7
LG
3230 //\r
3231 // Update Form NV flag.\r
3232 //\r
3233 Form->NvUpdateRequired = TRUE;\r
3234 }\r
3235 }\r
3236 } else if (SettingScope == FormSetLevel) {\r
3237 FormLink = GetFirstNode (&FormSet->FormListHead);\r
3238 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
3239 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
9776099f 3240 ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
48a9d5f7
LG
3241 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
3242 }\r
3243 } else if (SettingScope == SystemLevel) {\r
3244 //\r
3245 // Open all FormSet by locate HII packages.\r
3246 // Initiliaze the maintain FormSet to store default data as back up data.\r
3247 //\r
48a9d5f7
LG
3248 BackUpFormSet = gOldFormSet;\r
3249 gOldFormSet = NULL;\r
3250\r
3251 //\r
3252 // Get all the Hii handles\r
3253 //\r
3254 HiiHandles = HiiGetHiiHandles (NULL);\r
3255 ASSERT (HiiHandles != NULL);\r
3256\r
3257 //\r
3258 // Search for formset of each class type\r
3259 //\r
3260 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
3261 //\r
3262 // Check HiiHandles[Index] does exist in global maintain list. \r
3263 //\r
3264 if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
3265 continue;\r
4f33c838 3266 }\r
48a9d5f7
LG
3267 \r
3268 //\r
3269 // Initilize FormSet Setting\r
3270 //\r
3271 LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
3272 ASSERT (LocalFormSet != NULL);\r
3273 ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
db40504e 3274 Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet, FALSE);\r
48a9d5f7
LG
3275 if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
3276 DestroyFormSet (LocalFormSet);\r
3277 continue;\r
3278 }\r
3279 Status = InitializeCurrentSetting (LocalFormSet);\r
3280 if (EFI_ERROR (Status)) {\r
3281 DestroyFormSet (LocalFormSet);\r
3282 continue;\r
3283 }\r
7d1b202d
LG
3284 //\r
3285 // Initilize Questions' Value\r
3286 //\r
d6bee311 3287 Status = LoadFormSetConfig (NULL, LocalFormSet);\r
7d1b202d
LG
3288 if (EFI_ERROR (Status)) {\r
3289 DestroyFormSet (LocalFormSet);\r
3290 continue;\r
3291 }\r
3292\r
48a9d5f7
LG
3293 //\r
3294 // Add FormSet into the maintain list.\r
3295 //\r
3296 InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link);\r
3297 }\r
3298 \r
3299 //\r
3300 // Free resources, and restore gOldFormSet and gClassOfVfr\r
3301 //\r
3302 FreePool (HiiHandles);\r
3303 gOldFormSet = BackUpFormSet;\r
48a9d5f7
LG
3304 \r
3305 //\r
3306 // Set Default Value for each FormSet in the maintain list.\r
3307 //\r
3308 Link = GetFirstNode (&gBrowserFormSetList);\r
3309 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3310 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
9776099f 3311 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
48a9d5f7 3312 Link = GetNextNode (&gBrowserFormSetList, Link);\r
7936fb6a 3313 }\r
3314 }\r
3315\r
3316 return EFI_SUCCESS;\r
3317}\r
3318\r
7936fb6a 3319/**\r
3320 Initialize Question's Edit copy from Storage.\r
3321\r
eccfeab1
LG
3322 @param Selection Selection contains the information about \r
3323 the Selection, form and formset to be displayed.\r
3324 Selection action may be updated in retrieve callback.\r
7d1b202d 3325 If Selection is NULL, only initialize Question value.\r
7936fb6a 3326 @param FormSet FormSet data structure.\r
3327 @param Form Form data structure.\r
3328\r
3329 @retval EFI_SUCCESS The function completed successfully.\r
3330\r
3331**/\r
3332EFI_STATUS\r
3333LoadFormConfig (\r
eccfeab1
LG
3334 IN OUT UI_MENU_SELECTION *Selection,\r
3335 IN FORM_BROWSER_FORMSET *FormSet,\r
3336 IN FORM_BROWSER_FORM *Form\r
7936fb6a 3337 )\r
3338{\r
eccfeab1
LG
3339 EFI_STATUS Status;\r
3340 LIST_ENTRY *Link;\r
3341 FORM_BROWSER_STATEMENT *Question;\r
3342 UINT8 *BufferValue;\r
3343 UINTN StorageWidth;\r
eccfeab1 3344 \r
7936fb6a 3345 Link = GetFirstNode (&Form->StatementListHead);\r
3346 while (!IsNull (&Form->StatementListHead, Link)) {\r
3347 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3348\r
3349 //\r
3350 // Initialize local copy of Value for each Question\r
3351 //\r
816a7110 3352 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
7936fb6a 3353 if (EFI_ERROR (Status)) {\r
3354 return Status;\r
3355 }\r
e2100bfa
ED
3356\r
3357 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
3358 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
3359 }\r
3360\r
8ca6180f 3361 //\r
9776099f 3362 // Call the Retrieve call back function for all questions.\r
eccfeab1 3363 //\r
9776099f 3364 if ((FormSet->ConfigAccess != NULL) && (Selection != NULL) &&\r
eccfeab1 3365 ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
eccfeab1
LG
3366 //\r
3367 // Check QuestionValue does exist.\r
3368 //\r
3369 StorageWidth = Question->StorageWidth;\r
3370 if (Question->BufferValue != NULL) {\r
3371 BufferValue = Question->BufferValue;\r
3372 } else {\r
3373 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
3374 }\r
eccfeab1 3375\r
9776099f
ED
3376 //\r
3377 // For efivarstore storage, initial question value first.\r
3378 //\r
3379 if ((Question->Storage != NULL) && (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
3380 Status = gRT->GetVariable (\r
3381 Question->VariableName,\r
3382 &Question->Storage->Guid,\r
3383 NULL,\r
3384 &StorageWidth,\r
3385 BufferValue\r
3386 );\r
eccfeab1 3387 }\r
9776099f
ED
3388\r
3389 Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
eccfeab1 3390 }\r
7936fb6a 3391\r
3392 Link = GetNextNode (&Form->StatementListHead, Link);\r
3393 }\r
3394\r
3395 return EFI_SUCCESS;\r
3396}\r
3397\r
d66e6c16 3398/**\r
3399 Initialize Question's Edit copy from Storage for the whole Formset.\r
3400\r
eccfeab1
LG
3401 @param Selection Selection contains the information about \r
3402 the Selection, form and formset to be displayed.\r
3403 Selection action may be updated in retrieve callback.\r
7d1b202d 3404 If Selection is NULL, only initialize Question value.\r
d66e6c16 3405 @param FormSet FormSet data structure.\r
3406\r
3407 @retval EFI_SUCCESS The function completed successfully.\r
3408\r
3409**/\r
3410EFI_STATUS\r
3411LoadFormSetConfig (\r
eccfeab1
LG
3412 IN OUT UI_MENU_SELECTION *Selection,\r
3413 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 3414 )\r
3415{\r
eccfeab1
LG
3416 EFI_STATUS Status;\r
3417 LIST_ENTRY *Link;\r
3418 FORM_BROWSER_FORM *Form;\r
d66e6c16 3419\r
3420 Link = GetFirstNode (&FormSet->FormListHead);\r
3421 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3422 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3423\r
3424 //\r
3425 // Initialize local copy of Value for each Form\r
3426 //\r
eccfeab1 3427 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 3428 if (EFI_ERROR (Status)) {\r
3429 return Status;\r
3430 }\r
3431\r
3432 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3433 }\r
3434\r
3435 return EFI_SUCCESS;\r
3436}\r
3437\r
7936fb6a 3438/**\r
3439 Fill storage's edit copy with settings requested from Configuration Driver.\r
3440\r
3441 @param FormSet FormSet data structure.\r
3442 @param Storage Buffer Storage.\r
3443\r
3444 @retval EFI_SUCCESS The function completed successfully.\r
3445\r
3446**/\r
3447EFI_STATUS\r
3448LoadStorage (\r
3449 IN FORM_BROWSER_FORMSET *FormSet,\r
3450 IN FORMSET_STORAGE *Storage\r
3451 )\r
3452{\r
3453 EFI_STATUS Status;\r
3454 EFI_STRING Progress;\r
3455 EFI_STRING Result;\r
3456 CHAR16 *StrPtr;\r
3457\r
3458 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3459 return EFI_SUCCESS;\r
3460 }\r
3461\r
cce6230f
ED
3462 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
3463 Status = gRT->GetVariable (\r
3464 Storage->Name,\r
3465 &Storage->Guid,\r
3466 NULL,\r
3467 (UINTN*)&Storage->Size,\r
3468 Storage->EditBuffer\r
3469 );\r
3470 return Status;\r
3471 }\r
3472\r
7936fb6a 3473 if (FormSet->ConfigAccess == NULL) {\r
3474 return EFI_NOT_FOUND;\r
3475 }\r
3476\r
3477 if (Storage->ElementCount == 0) {\r
3478 //\r
3479 // Skip if there is no RequestElement\r
3480 //\r
3481 return EFI_SUCCESS;\r
3482 }\r
3483\r
3484 //\r
3485 // Request current settings from Configuration Driver\r
3486 //\r
3487 Status = FormSet->ConfigAccess->ExtractConfig (\r
3488 FormSet->ConfigAccess,\r
3489 Storage->ConfigRequest,\r
3490 &Progress,\r
3491 &Result\r
3492 );\r
3493 if (EFI_ERROR (Status)) {\r
3494 return Status;\r
3495 }\r
3496\r
3497 //\r
3498 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
3499 //\r
3500 StrPtr = StrStr (Result, L"ALTCFG");\r
3501 if (StrPtr != NULL) {\r
3502 *StrPtr = L'\0';\r
3503 }\r
3504\r
3505 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 3506 FreePool (Result);\r
7936fb6a 3507 return Status;\r
3508}\r
3509\r
3510\r
d66e6c16 3511/**\r
3512 Copy uncommitted data from source Storage to destination Storage.\r
3513\r
3514 @param Dst Target Storage for uncommitted data.\r
3515 @param Src Source Storage for uncommitted data.\r
3516\r
3517 @retval EFI_SUCCESS The function completed successfully.\r
3518 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
3519\r
3520**/\r
3521EFI_STATUS\r
3522CopyStorage (\r
3523 IN OUT FORMSET_STORAGE *Dst,\r
3524 IN FORMSET_STORAGE *Src\r
3525 )\r
3526{\r
3527 LIST_ENTRY *Link;\r
3528 NAME_VALUE_NODE *Node;\r
3529\r
3530 if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
3531 return EFI_INVALID_PARAMETER;\r
3532 }\r
3533\r
3534 switch (Src->Type) {\r
3535 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 3536 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
d66e6c16 3537 CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
b18e7050 3538 CopyMem (Dst->Buffer, Src->Buffer, Src->Size);\r
d66e6c16 3539 break;\r
3540\r
3541 case EFI_HII_VARSTORE_NAME_VALUE:\r
3542 Link = GetFirstNode (&Src->NameValueListHead);\r
3543 while (!IsNull (&Src->NameValueListHead, Link)) {\r
3544 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
3545\r
816a7110
ED
3546 SetValueByName (Dst, Node->Name, Node->EditValue, GetSetValueWithEditBuffer);\r
3547 SetValueByName (Dst, Node->Name, Node->Value, GetSetValueWithBuffer);\r
d66e6c16 3548\r
3549 Link = GetNextNode (&Src->NameValueListHead, Link);\r
3550 }\r
3551 break;\r
3552\r
3553 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
3554 default:\r
3555 break;\r
3556 }\r
3557\r
3558 return EFI_SUCCESS;\r
3559}\r
3560\r
9776099f
ED
3561/**\r
3562 Get old question value from the saved formset.\r
3563\r
3564 @param Statement The question which need to get old question value.\r
3565 @param OldFormSet FormSet data structure saved in the list.\r
3566\r
3567**/\r
3568VOID \r
3569GetOldQuestionValue (\r
3570 IN OUT FORM_BROWSER_STATEMENT *Statement,\r
3571 IN FORM_BROWSER_FORMSET *OldFormSet\r
3572 )\r
3573{\r
3574 LIST_ENTRY *FormLink;\r
3575 LIST_ENTRY *Link;\r
3576 FORM_BROWSER_STATEMENT *Question;\r
3577 FORM_BROWSER_FORM *Form;\r
3578\r
3579 FormLink = GetFirstNode (&OldFormSet->FormListHead);\r
3580 while (!IsNull (&OldFormSet->FormListHead, FormLink)) {\r
3581 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
3582 FormLink = GetNextNode (&OldFormSet->FormListHead, FormLink);\r
3583\r
3584 Link = GetFirstNode (&Form->StatementListHead);\r
3585 while (!IsNull (&Form->StatementListHead, Link)) {\r
3586 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3587 Link = GetNextNode (&Form->StatementListHead, Link);\r
3588\r
3589 if (Question->QuestionId != Statement->QuestionId) {\r
3590 continue;\r
3591 }\r
3592\r
3593 CopyMem (&Statement->HiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
3594 return;\r
3595 }\r
3596 }\r
3597}\r
3598\r
3599/**\r
3600 Get old question value from the saved formset, all these questions not have\r
3601 storage.\r
3602\r
3603 @param FormSet FormSet data structure which is used now.\r
3604 @param OldFormSet FormSet data structure saved in the list.\r
3605\r
3606**/\r
3607VOID\r
3608CopyOldValueForNoStorageQst (\r
3609 IN OUT FORM_BROWSER_FORMSET *FormSet,\r
3610 IN FORM_BROWSER_FORMSET *OldFormSet\r
3611 )\r
3612{\r
3613 LIST_ENTRY *FormLink;\r
3614 LIST_ENTRY *Link;\r
3615 FORM_BROWSER_STATEMENT *Question;\r
3616 FORM_BROWSER_FORM *Form;\r
3617\r
3618 FormLink = GetFirstNode (&FormSet->FormListHead);\r
3619 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
3620 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
3621 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
3622\r
3623 Link = GetFirstNode (&Form->StatementListHead);\r
3624 while (!IsNull (&Form->StatementListHead, Link)) {\r
3625 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3626 Link = GetNextNode (&Form->StatementListHead, Link);\r
3627\r
3628 if (Question->Storage == NULL) {\r
3629 GetOldQuestionValue (Question, OldFormSet);\r
3630 }\r
3631 }\r
3632 }\r
3633}\r
d66e6c16 3634\r
7936fb6a 3635/**\r
3636 Get current setting of Questions.\r
3637\r
3638 @param FormSet FormSet data structure.\r
3639\r
3640 @retval EFI_SUCCESS The function completed successfully.\r
3641\r
3642**/\r
3643EFI_STATUS\r
3644InitializeCurrentSetting (\r
3645 IN OUT FORM_BROWSER_FORMSET *FormSet\r
3646 )\r
3647{\r
3648 LIST_ENTRY *Link;\r
d66e6c16 3649 LIST_ENTRY *Link2;\r
7936fb6a 3650 FORMSET_STORAGE *Storage;\r
d66e6c16 3651 FORMSET_STORAGE *StorageSrc;\r
3652 FORMSET_STORAGE *OldStorage;\r
7936fb6a 3653 FORM_BROWSER_FORM *Form;\r
b00964a9 3654 FORM_BROWSER_FORM *Form2;\r
7936fb6a 3655 EFI_STATUS Status;\r
3656\r
7936fb6a 3657 //\r
3658 // Request current settings from Configuration Driver\r
3659 //\r
3660 Link = GetFirstNode (&FormSet->StorageListHead);\r
3661 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3662 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
3663\r
d66e6c16 3664 OldStorage = NULL;\r
3665 if (gOldFormSet != NULL) {\r
3666 //\r
3667 // Try to find the Storage in backup formset gOldFormSet\r
3668 //\r
3669 Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
3670 while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
3671 StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
3672\r
3673 if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
3674 OldStorage = StorageSrc;\r
3675 break;\r
3676 }\r
3677\r
3678 Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
3679 }\r
3680 }\r
3681\r
3682 if (OldStorage == NULL) {\r
3683 //\r
3684 // Storage is not found in backup formset, request it from ConfigDriver\r
3685 //\r
3686 Status = LoadStorage (FormSet, Storage);\r
3347d410
ED
3687\r
3688 if (EFI_ERROR (Status)) {\r
3689 //\r
3690 // If get last time changed value failed, extract default from IFR binary\r
3691 //\r
9776099f 3692 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);\r
3347d410
ED
3693 //\r
3694 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag\r
3695 // in current situation.\r
3696 //\r
3697 UpdateNvInfoInForm (FormSet, FALSE);\r
3698 }\r
3699\r
b18e7050 3700 //\r
3347d410 3701 // Now Edit Buffer is filled with default values(lower priority) or current\r
b18e7050
ED
3702 // settings(higher priority), sychronize it to shadow Buffer\r
3703 //\r
3347d410 3704 SynchronizeStorage (Storage, TRUE);\r
d66e6c16 3705 } else {\r
3706 //\r
3707 // Storage found in backup formset, use it\r
3708 //\r
3709 Status = CopyStorage (Storage, OldStorage);\r
3710 }\r
7936fb6a 3711\r
7936fb6a 3712 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3713 }\r
3714\r
b00964a9
ED
3715 //\r
3716 // If has old formset, get the old nv update status.\r
3717 //\r
3718 if (gOldFormSet != NULL) {\r
9776099f
ED
3719 //\r
3720 // Restore question value for questions without storage.\r
3721 //\r
3722 CopyOldValueForNoStorageQst (FormSet, gOldFormSet);\r
b00964a9 3723\r
9776099f
ED
3724 Link = GetFirstNode (&FormSet->FormListHead);\r
3725 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3726 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
b00964a9 3727\r
9776099f
ED
3728 Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
3729 while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
3730 Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
b00964a9 3731\r
9776099f
ED
3732 if (Form->FormId == Form2->FormId) {\r
3733 Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
3734 break;\r
b00964a9 3735 }\r
9776099f
ED
3736\r
3737 Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
b00964a9 3738 }\r
9776099f
ED
3739 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3740 }\r
3741 } else {\r
3742 //\r
3743 // Extract default from IFR binary for no storage questions.\r
3744 // \r
3745 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE);\r
b00964a9
ED
3746 }\r
3747\r
7936fb6a 3748 return EFI_SUCCESS;\r
3749}\r
3750\r
3751\r
3752/**\r
3753 Fetch the Ifr binary data of a FormSet.\r
3754\r
3755 @param Handle PackageList Handle\r
f5006bd9 3756 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
3757 specified (NULL or zero GUID), take the first\r
3758 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
3759 found in package list.\r
3760 On output, GUID of the formset found(if not NULL).\r
7936fb6a 3761 @param BinaryLength The length of the FormSet IFR binary.\r
3762 @param BinaryData The buffer designed to receive the FormSet.\r
3763\r
3764 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
3765 BufferLength was updated.\r
3766 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
3767 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
3768 be found with the requested FormId.\r
3769\r
3770**/\r
3771EFI_STATUS\r
3772GetIfrBinaryData (\r
3773 IN EFI_HII_HANDLE Handle,\r
3774 IN OUT EFI_GUID *FormSetGuid,\r
3775 OUT UINTN *BinaryLength,\r
3776 OUT UINT8 **BinaryData\r
3777 )\r
3778{\r
3779 EFI_STATUS Status;\r
3780 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
3781 UINTN BufferSize;\r
3782 UINT8 *Package;\r
3783 UINT8 *OpCodeData;\r
3784 UINT32 Offset;\r
3785 UINT32 Offset2;\r
7936fb6a 3786 UINT32 PackageListLength;\r
3787 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
3788 UINT8 Index;\r
3789 UINT8 NumberOfClassGuid;\r
f5006bd9 3790 BOOLEAN ClassGuidMatch;\r
0a1147ed 3791 EFI_GUID *ClassGuid;\r
f5006bd9 3792 EFI_GUID *ComparingGuid;\r
7936fb6a 3793\r
3794 OpCodeData = NULL;\r
3795 Package = NULL;\r
0c66bc76 3796 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 3797\r
3798 //\r
f5006bd9 3799 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 3800 //\r
48a9d5f7
LG
3801 if (FormSetGuid == NULL) {\r
3802 ComparingGuid = &gZeroGuid;\r
7936fb6a 3803 } else {\r
f5006bd9 3804 ComparingGuid = FormSetGuid;\r
7936fb6a 3805 }\r
3806\r
3807 //\r
3808 // Get HII PackageList\r
3809 //\r
3810 BufferSize = 0;\r
3811 HiiPackageList = NULL;\r
3812 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3813 if (Status == EFI_BUFFER_TOO_SMALL) {\r
3814 HiiPackageList = AllocatePool (BufferSize);\r
3815 ASSERT (HiiPackageList != NULL);\r
3816\r
3817 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3818 }\r
3819 if (EFI_ERROR (Status)) {\r
3820 return Status;\r
3821 }\r
db0bd81c 3822 ASSERT (HiiPackageList != NULL);\r
d66e6c16 3823\r
7936fb6a 3824 //\r
3825 // Get Form package from this HII package List\r
3826 //\r
3827 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
3828 Offset2 = 0;\r
3829 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
3830\r
f5006bd9 3831 ClassGuidMatch = FALSE;\r
7936fb6a 3832 while (Offset < PackageListLength) {\r
3833 Package = ((UINT8 *) HiiPackageList) + Offset;\r
3834 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3835\r
8d00a0f1 3836 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 3837 //\r
3838 // Search FormSet in this Form Package\r
3839 //\r
3840 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
3841 while (Offset2 < PackageHeader.Length) {\r
3842 OpCodeData = Package + Offset2;\r
3843\r
3844 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
3845 //\r
f5006bd9 3846 // Try to compare against formset GUID\r
7936fb6a 3847 //\r
48a9d5f7
LG
3848 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
3849 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 3850 break;\r
7936fb6a 3851 }\r
3852\r
d228526f
LG
3853 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
3854 //\r
3855 // Try to compare against formset class GUID\r
3856 //\r
3857 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
3858 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
3859 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
3860 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
3861 ClassGuidMatch = TRUE;\r
3862 break;\r
3863 }\r
3864 }\r
3865 if (ClassGuidMatch) {\r
f5006bd9 3866 break;\r
3867 }\r
d228526f
LG
3868 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
3869 ClassGuidMatch = TRUE;\r
7936fb6a 3870 break;\r
3871 }\r
3872 }\r
3873\r
3874 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
3875 }\r
3876\r
3877 if (Offset2 < PackageHeader.Length) {\r
3878 //\r
3879 // Target formset found\r
3880 //\r
3881 break;\r
3882 }\r
3883 }\r
3884\r
3885 Offset += PackageHeader.Length;\r
3886 }\r
3887\r
3888 if (Offset >= PackageListLength) {\r
3889 //\r
3890 // Form package not found in this Package List\r
3891 //\r
f4113e1f 3892 FreePool (HiiPackageList);\r
7936fb6a 3893 return EFI_NOT_FOUND;\r
3894 }\r
3895\r
48a9d5f7 3896 if (FormSetGuid != NULL) {\r
7936fb6a 3897 //\r
f5006bd9 3898 // Return the FormSet GUID\r
7936fb6a 3899 //\r
3900 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
3901 }\r
3902\r
3903 //\r
3904 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
3905 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
3906 // of the Form Package.\r
3907 //\r
3908 *BinaryLength = PackageHeader.Length - Offset2;\r
3909 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
3910\r
f4113e1f 3911 FreePool (HiiPackageList);\r
7936fb6a 3912\r
3913 if (*BinaryData == NULL) {\r
3914 return EFI_OUT_OF_RESOURCES;\r
3915 }\r
3916\r
3917 return EFI_SUCCESS;\r
3918}\r
3919\r
3920\r
3921/**\r
3922 Initialize the internal data structure of a FormSet.\r
3923\r
3924 @param Handle PackageList Handle\r
f5006bd9 3925 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
3926 specified (NULL or zero GUID), take the first\r
3927 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
3928 found in package list.\r
3929 On output, GUID of the formset found(if not NULL).\r
7936fb6a 3930 @param FormSet FormSet data structure.\r
db40504e 3931 @param UpdateGlobalVar Whether need to update the global variable.\r
7936fb6a 3932\r
3933 @retval EFI_SUCCESS The function completed successfully.\r
3934 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
3935\r
3936**/\r
3937EFI_STATUS\r
3938InitializeFormSet (\r
3939 IN EFI_HII_HANDLE Handle,\r
3940 IN OUT EFI_GUID *FormSetGuid,\r
db40504e
ED
3941 OUT FORM_BROWSER_FORMSET *FormSet,\r
3942 IN BOOLEAN UpdateGlobalVar \r
7936fb6a 3943 )\r
3944{\r
3945 EFI_STATUS Status;\r
3946 EFI_HANDLE DriverHandle;\r
3947 UINT16 Index;\r
3948\r
3949 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
3950 if (EFI_ERROR (Status)) {\r
3951 return Status;\r
3952 }\r
3953\r
48a9d5f7 3954 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 3955 FormSet->HiiHandle = Handle;\r
3956 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
3957\r
3958 //\r
3959 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
3960 //\r
3961 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
3962 if (EFI_ERROR (Status)) {\r
3963 return Status;\r
3964 }\r
3965 FormSet->DriverHandle = DriverHandle;\r
3966 Status = gBS->HandleProtocol (\r
3967 DriverHandle,\r
3968 &gEfiHiiConfigAccessProtocolGuid,\r
3969 (VOID **) &FormSet->ConfigAccess\r
3970 );\r
3971 if (EFI_ERROR (Status)) {\r
3972 //\r
3973 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
3974 // list, then there will be no configuration action required\r
3975 //\r
3976 FormSet->ConfigAccess = NULL;\r
3977 }\r
3978\r
3979 //\r
3980 // Parse the IFR binary OpCodes\r
3981 //\r
3982 Status = ParseOpCodes (FormSet);\r
3983 if (EFI_ERROR (Status)) {\r
3984 return Status;\r
3985 }\r
3986\r
db40504e
ED
3987 // \r
3988 // If not need to update the global variable, just return.\r
3989 //\r
3990 if (!UpdateGlobalVar) {\r
3991 return Status;\r
3992 }\r
3993\r
40245175
LG
3994 //\r
3995 // Set VFR type by FormSet SubClass field\r
3996 //\r
0a1147ed
LG
3997 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
3998 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
3999 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
40245175
LG
4000 }\r
4001 \r
4002 //\r
4003 // Set VFR type by FormSet class guid\r
4004 //\r
4005 for (Index = 0; Index < 3; Index ++) {\r
4006 if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
4007 gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
4008 break;\r
4009 }\r
4010 }\r
4011\r
4012 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
0a1147ed 4013 gFrontPageHandle = FormSet->HiiHandle;\r
48a9d5f7 4014 gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING;\r
7936fb6a 4015 }\r
4016\r
4017 //\r
4018 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
4019 //\r
4020 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
4021 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
4022 //\r
4023 // Update the function key setting.\r
4024 //\r
4025 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
7936fb6a 4026 }\r
4027 }\r
4028\r
48a9d5f7 4029 return EFI_SUCCESS;\r
7936fb6a 4030}\r
ce6d12cc 4031\r
4032\r
4033/**\r
4034 Save globals used by previous call to SendForm(). SendForm() may be called from \r
4035 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
4036 So, save globals of previous call to SendForm() and restore them upon exit.\r
4037\r
4038**/\r
4039VOID\r
4040SaveBrowserContext (\r
4041 VOID\r
4042 )\r
4043{\r
4044 BROWSER_CONTEXT *Context;\r
4045\r
4046 gBrowserContextCount++;\r
4047 if (gBrowserContextCount == 1) {\r
4048 //\r
4049 // This is not reentry of SendForm(), no context to save\r
4050 //\r
4051 return;\r
4052 }\r
4053\r
4054 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
4055 ASSERT (Context != NULL);\r
4056\r
4057 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
4058\r
4059 //\r
4060 // Save FormBrowser context\r
4061 //\r
4062 Context->BannerData = gBannerData;\r
4063 Context->ClassOfVfr = gClassOfVfr;\r
4064 Context->FunctionKeySetting = gFunctionKeySetting;\r
4065 Context->ResetRequired = gResetRequired;\r
ce6d12cc 4066 Context->Direction = gDirection;\r
ce6d12cc 4067 Context->EnterString = gEnterString;\r
4068 Context->EnterCommitString = gEnterCommitString;\r
4069 Context->EnterEscapeString = gEnterEscapeString;\r
4070 Context->EscapeString = gEscapeString;\r
ce6d12cc 4071 Context->MoveHighlight = gMoveHighlight;\r
4072 Context->MakeSelection = gMakeSelection;\r
4073 Context->DecNumericInput = gDecNumericInput;\r
4074 Context->HexNumericInput = gHexNumericInput;\r
4075 Context->ToggleCheckBox = gToggleCheckBox;\r
4076 Context->PromptForData = gPromptForData;\r
4077 Context->PromptForPassword = gPromptForPassword;\r
4078 Context->PromptForNewPassword = gPromptForNewPassword;\r
4079 Context->ConfirmPassword = gConfirmPassword;\r
4080 Context->ConfirmError = gConfirmError;\r
4081 Context->PassowordInvalid = gPassowordInvalid;\r
4082 Context->PressEnter = gPressEnter;\r
4083 Context->EmptyString = gEmptyString;\r
4084 Context->AreYouSure = gAreYouSure;\r
4085 Context->YesResponse = gYesResponse;\r
4086 Context->NoResponse = gNoResponse;\r
4087 Context->MiniString = gMiniString;\r
4088 Context->PlusString = gPlusString;\r
4089 Context->MinusString = gMinusString;\r
4090 Context->AdjustNumber = gAdjustNumber;\r
4091 Context->SaveChanges = gSaveChanges;\r
4092 Context->OptionMismatch = gOptionMismatch;\r
2bb526f3 4093 Context->FormSuppress = gFormSuppress;\r
ce6d12cc 4094 Context->PromptBlockWidth = gPromptBlockWidth;\r
4095 Context->OptionBlockWidth = gOptionBlockWidth;\r
4096 Context->HelpBlockWidth = gHelpBlockWidth;\r
4097 Context->OldFormSet = gOldFormSet;\r
4098 Context->MenuRefreshHead = gMenuRefreshHead;\r
4099\r
4100 CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
4101 CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
4102\r
4103 //\r
4104 // Insert to FormBrowser context list\r
4105 //\r
4106 InsertHeadList (&gBrowserContextList, &Context->Link);\r
4107}\r
4108\r
4109\r
4110/**\r
4111 Restore globals used by previous call to SendForm().\r
4112\r
4113**/\r
4114VOID\r
4115RestoreBrowserContext (\r
4116 VOID\r
4117 )\r
4118{\r
4119 LIST_ENTRY *Link;\r
4120 BROWSER_CONTEXT *Context;\r
4121\r
4122 ASSERT (gBrowserContextCount != 0);\r
4123 gBrowserContextCount--;\r
4124 if (gBrowserContextCount == 0) {\r
4125 //\r
4126 // This is not reentry of SendForm(), no context to restore\r
4127 //\r
4128 return;\r
4129 }\r
4130\r
4131 ASSERT (!IsListEmpty (&gBrowserContextList));\r
4132\r
4133 Link = GetFirstNode (&gBrowserContextList);\r
4134 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
4135\r
4136 //\r
4137 // Restore FormBrowser context\r
4138 //\r
4139 gBannerData = Context->BannerData;\r
4140 gClassOfVfr = Context->ClassOfVfr;\r
4141 gFunctionKeySetting = Context->FunctionKeySetting;\r
4142 gResetRequired = Context->ResetRequired;\r
ce6d12cc 4143 gDirection = Context->Direction;\r
ce6d12cc 4144 gEnterString = Context->EnterString;\r
4145 gEnterCommitString = Context->EnterCommitString;\r
4146 gEnterEscapeString = Context->EnterEscapeString;\r
4147 gEscapeString = Context->EscapeString;\r
ce6d12cc 4148 gMoveHighlight = Context->MoveHighlight;\r
4149 gMakeSelection = Context->MakeSelection;\r
4150 gDecNumericInput = Context->DecNumericInput;\r
4151 gHexNumericInput = Context->HexNumericInput;\r
4152 gToggleCheckBox = Context->ToggleCheckBox;\r
4153 gPromptForData = Context->PromptForData;\r
4154 gPromptForPassword = Context->PromptForPassword;\r
4155 gPromptForNewPassword = Context->PromptForNewPassword;\r
4156 gConfirmPassword = Context->ConfirmPassword;\r
4157 gConfirmError = Context->ConfirmError;\r
4158 gPassowordInvalid = Context->PassowordInvalid;\r
4159 gPressEnter = Context->PressEnter;\r
4160 gEmptyString = Context->EmptyString;\r
4161 gAreYouSure = Context->AreYouSure;\r
4162 gYesResponse = Context->YesResponse;\r
4163 gNoResponse = Context->NoResponse;\r
4164 gMiniString = Context->MiniString;\r
4165 gPlusString = Context->PlusString;\r
4166 gMinusString = Context->MinusString;\r
4167 gAdjustNumber = Context->AdjustNumber;\r
4168 gSaveChanges = Context->SaveChanges;\r
4169 gOptionMismatch = Context->OptionMismatch;\r
2bb526f3 4170 gFormSuppress = Context->FormSuppress;\r
ce6d12cc 4171 gPromptBlockWidth = Context->PromptBlockWidth;\r
4172 gOptionBlockWidth = Context->OptionBlockWidth;\r
4173 gHelpBlockWidth = Context->HelpBlockWidth;\r
4174 gOldFormSet = Context->OldFormSet;\r
4175 gMenuRefreshHead = Context->MenuRefreshHead;\r
4176\r
4177 CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
4178 CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
4179\r
4180 //\r
4181 // Remove from FormBrowser context list\r
4182 //\r
4183 RemoveEntryList (&Context->Link);\r
4184 gBS->FreePool (Context);\r
4185}\r
48a9d5f7
LG
4186\r
4187/**\r
4188 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
4189 \r
4190 @param Handle The Hii Handle.\r
4191 \r
4192 @return the found FormSet context. If no found, NULL will return.\r
4193\r
4194**/\r
4195FORM_BROWSER_FORMSET * \r
4196GetFormSetFromHiiHandle (\r
4197 EFI_HII_HANDLE Handle\r
4198 )\r
4199{\r
4200 LIST_ENTRY *Link;\r
4201 FORM_BROWSER_FORMSET *FormSet;\r
4202\r
4203 Link = GetFirstNode (&gBrowserFormSetList);\r
4204 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4205 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
4206 if (FormSet->HiiHandle == Handle) {\r
4207 return FormSet;\r
4208 }\r
4209 Link = GetNextNode (&gBrowserFormSetList, Link);\r
4210 }\r
4211 \r
4212 return NULL;\r
4213}\r
4214\r
4215/**\r
4216 Check whether the input HII handle is the FormSet that is being used.\r
4217 \r
4218 @param Handle The Hii Handle.\r
4219 \r
4220 @retval TRUE HII handle is being used.\r
4221 @retval FALSE HII handle is not being used.\r
4222\r
4223**/\r
4224BOOLEAN\r
4225IsHiiHandleInBrowserContext (\r
4226 EFI_HII_HANDLE Handle\r
4227 )\r
4228{\r
4229 LIST_ENTRY *Link;\r
4230 BROWSER_CONTEXT *Context;\r
4231\r
4232 //\r
4233 // HiiHandle is Current FormSet.\r
4234 //\r
4235 if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {\r
4236 return TRUE;\r
4237 }\r
4238\r
4239 //\r
4240 // Check whether HiiHandle is in BrowserContext.\r
4241 //\r
4242 Link = GetFirstNode (&gBrowserContextList);\r
4243 while (!IsNull (&gBrowserContextList, Link)) {\r
4244 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
4245 if (Context->OldFormSet->HiiHandle == Handle) {\r
4246 //\r
4247 // HiiHandle is in BrowserContext\r
4248 //\r
4249 return TRUE;\r
4250 }\r
4251 Link = GetNextNode (&gBrowserContextList, Link);\r
4252 }\r
4253 \r
4254 return FALSE;\r
4255}\r
4256\r
4257/**\r
4258 Find the registered HotKey based on KeyData.\r
4259 \r
4260 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
4261 information for the hot key.\r
4262\r
4263 @return The registered HotKey context. If no found, NULL will return.\r
4264**/\r
4265BROWSER_HOT_KEY *\r
4266GetHotKeyFromRegisterList (\r
4267 IN EFI_INPUT_KEY *KeyData\r
4268 )\r
4269{\r
4270 LIST_ENTRY *Link;\r
4271 BROWSER_HOT_KEY *HotKey;\r
4272\r
4273 Link = GetFirstNode (&gBrowserHotKeyList);\r
4274 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
4275 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
4276 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
4277 return HotKey;\r
4278 }\r
4279 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
4280 }\r
4281 \r
4282 return NULL;\r
4283}\r
4284\r
4285/**\r
4286 Configure what scope the hot key will impact.\r
4287 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
4288 If no scope is set, the default scope will be FormSet level.\r
4289 After all registered hot keys are removed, previous Scope can reset to another level.\r
4290 \r
4291 @param[in] Scope Scope level to be set. \r
4292 \r
4293 @retval EFI_SUCCESS Scope is set correctly.\r
4294 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
4295 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
4296\r
4297**/\r
4298EFI_STATUS\r
4299EFIAPI\r
4300SetScope (\r
4301 IN BROWSER_SETTING_SCOPE Scope\r
4302 )\r
4303{\r
4304 if (Scope >= MaxLevel) {\r
4305 return EFI_INVALID_PARAMETER;\r
4306 }\r
4307 \r
4308 //\r
4309 // When no hot key registered in system or on the first setting,\r
4310 // Scope can be set.\r
4311 //\r
4312 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
4313 gBrowserSettingScope = Scope;\r
4314 mBrowserScopeFirstSet = FALSE;\r
4315 } else if (Scope != gBrowserSettingScope) {\r
4316 return EFI_UNSUPPORTED;\r
4317 }\r
4318\r
4319 return EFI_SUCCESS;\r
4320}\r
4321\r
4322/**\r
4323 Register the hot key with its browser action, or unregistered the hot key.\r
4324 Only support hot key that is not printable character (control key, function key, etc.).\r
4325 If the action value is zero, the hot key will be unregistered if it has been registered.\r
4326 If the same hot key has been registered, the new action and help string will override the previous ones.\r
4327 \r
4328 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
4329 information for the hot key. Its type is EFI_INPUT_KEY to \r
4330 be supported by all ConsoleIn devices.\r
4331 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
4332 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
4333 @param[in] HelpString Help string that describes the hot key information.\r
4334 Its value may be NULL for the unregistered hot key.\r
4335 \r
4336 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
4337 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
4338 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
4339 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
4340**/\r
4341EFI_STATUS\r
4342EFIAPI\r
4343RegisterHotKey (\r
4344 IN EFI_INPUT_KEY *KeyData,\r
4345 IN UINT32 Action,\r
4346 IN UINT16 DefaultId,\r
4347 IN EFI_STRING HelpString OPTIONAL\r
4348 )\r
4349{\r
4350 BROWSER_HOT_KEY *HotKey;\r
4351\r
4352 //\r
4353 // Check input parameters.\r
4354 //\r
4355 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
4356 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
4357 return EFI_INVALID_PARAMETER;\r
4358 }\r
4359\r
4360 //\r
4361 // Check whether the input KeyData is in BrowserHotKeyList.\r
4362 //\r
4363 HotKey = GetHotKeyFromRegisterList (KeyData);\r
4364 \r
4365 //\r
4366 // Unregister HotKey\r
4367 //\r
4368 if (Action == BROWSER_ACTION_UNREGISTER) {\r
4369 if (HotKey != NULL) {\r
4370 //\r
4371 // The registered HotKey is found. \r
4372 // Remove it from List, and free its resource.\r
4373 //\r
4374 RemoveEntryList (&HotKey->Link);\r
4375 FreePool (HotKey->KeyData);\r
4376 FreePool (HotKey->HelpString);\r
4377 return EFI_SUCCESS;\r
4378 } else {\r
4379 //\r
4380 // The registered HotKey is not found. \r
4381 //\r
4382 return EFI_NOT_FOUND;\r
4383 }\r
4384 }\r
4385 \r
4386 //\r
4387 // Register HotKey into List.\r
4388 //\r
4389 if (HotKey == NULL) {\r
4390 //\r
4391 // Create new Key, and add it into List.\r
4392 //\r
4393 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
4394 ASSERT (HotKey != NULL);\r
4395 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
4396 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
4397 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
4398 }\r
4399\r
4400 //\r
4401 // Fill HotKey information.\r
4402 //\r
4403 HotKey->Action = Action;\r
4404 HotKey->DefaultId = DefaultId;\r
4405 if (HotKey->HelpString != NULL) {\r
4406 FreePool (HotKey->HelpString);\r
4407 }\r
4408 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
4409\r
4410 return EFI_SUCCESS;\r
4411}\r
4412\r
4413/**\r
4414 Register Exit handler function. \r
4415 When more than one handler function is registered, the latter one will override the previous one. \r
4416 When NULL handler is specified, the previous Exit handler will be unregistered. \r
4417 \r
4418 @param[in] Handler Pointer to handler function. \r
4419\r
4420**/\r
4421VOID\r
4422EFIAPI\r
4423RegiserExitHandler (\r
4424 IN EXIT_HANDLER Handler\r
4425 )\r
4426{\r
4427 ExitHandlerFunction = Handler;\r
4428 return;\r
4429}\r
4430\r
4431/**\r
4432 Create reminder to let user to choose save or discard the changed browser data.\r
4433 Caller can use it to actively check the changed browser data.\r
4434\r
4435 @retval BROWSER_NO_CHANGES No browser data is changed.\r
4436 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
4437 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
4438\r
4439**/\r
4440UINT32\r
4441EFIAPI\r
4442SaveReminder (\r
4443 VOID\r
4444 )\r
4445{\r
4446 LIST_ENTRY *Link;\r
4447 FORM_BROWSER_FORMSET *FormSet;\r
4448 BOOLEAN IsDataChanged;\r
4449 UINT32 DataSavedAction;\r
4450 CHAR16 *YesResponse;\r
4451 CHAR16 *NoResponse;\r
4452 CHAR16 *EmptyString;\r
4453 CHAR16 *ChangeReminderString;\r
4454 CHAR16 *SaveConfirmString;\r
4455 EFI_INPUT_KEY Key;\r
48a9d5f7
LG
4456\r
4457 DataSavedAction = BROWSER_NO_CHANGES;\r
4458 IsDataChanged = FALSE;\r
4459 Link = GetFirstNode (&gBrowserFormSetList);\r
4460 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4461 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
4462 if (IsNvUpdateRequired (FormSet)) {\r
4463 IsDataChanged = TRUE;\r
4464 break;\r
4465 }\r
4466 Link = GetNextNode (&gBrowserFormSetList, Link);\r
4467 }\r
4468 \r
4469 //\r
4470 // No data is changed. No save is required. \r
4471 //\r
4472 if (!IsDataChanged) {\r
4473 return DataSavedAction;\r
4474 }\r
4475 \r
4476 //\r
4477 // If data is changed, prompt user\r
4478 //\r
7538d536 4479 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
48a9d5f7
LG
4480\r
4481 YesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
4482 ASSERT (YesResponse != NULL);\r
4483 NoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
4484 ASSERT (NoResponse != NULL);\r
4485 EmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
4486 ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle);\r
4487 SaveConfirmString = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle);\r
4488\r
4489 do {\r
4490 CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString);\r
4491 } while\r
4492 (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
4493 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET))\r
4494 );\r
4495\r
4496 //\r
4497 // If the user hits the YesResponse key\r
4498 //\r
4499 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) {\r
4500 SubmitForm (NULL, NULL, SystemLevel);\r
4501 DataSavedAction = BROWSER_SAVE_CHANGES;\r
4502 } else {\r
4503 DiscardForm (NULL, NULL, SystemLevel);\r
4504 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
4505 gResetRequired = FALSE;\r
4506 }\r
4507\r
4508 FreePool (YesResponse);\r
4509 FreePool (NoResponse);\r
4510 FreePool (EmptyString);\r
4511 FreePool (SaveConfirmString);\r
4512 FreePool (ChangeReminderString);\r
4513\r
4514 return DataSavedAction;\r
4515}\r