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