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