]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Support call of SendForm() from Callback(), i.e. nested call of SendForm().
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
d66e6c16 4Copyright (c) 2007 - 2009, Intel Corporation\r
7936fb6a 5All rights reserved. This program and the accompanying materials\r
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
16#include "Ui.h"\r
17\r
18\r
19SETUP_DRIVER_PRIVATE_DATA mPrivateData = {\r
20 SETUP_DRIVER_SIGNATURE,\r
21 NULL,\r
22 {\r
23 SendForm,\r
24 BrowserCallback\r
7936fb6a 25 }\r
26};\r
27\r
28EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
29EFI_HII_STRING_PROTOCOL *mHiiString;\r
30EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
31\r
ce6d12cc 32UINTN gBrowserContextCount = 0;\r
33LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
34\r
0a1147ed
LG
35BANNER_DATA *gBannerData;\r
36EFI_HII_HANDLE gFrontPageHandle;\r
7936fb6a 37UINTN gClassOfVfr;\r
38UINTN gFunctionKeySetting;\r
39BOOLEAN gResetRequired;\r
40BOOLEAN gNvUpdateRequired;\r
41EFI_HII_HANDLE gHiiHandle;\r
7936fb6a 42UINT16 gDirection;\r
43EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
7936fb6a 44\r
45//\r
46// Browser Global Strings\r
47//\r
7936fb6a 48CHAR16 *gFunctionNineString;\r
49CHAR16 *gFunctionTenString;\r
50CHAR16 *gEnterString;\r
51CHAR16 *gEnterCommitString;\r
8d00a0f1 52CHAR16 *gEnterEscapeString;\r
7936fb6a 53CHAR16 *gEscapeString;\r
54CHAR16 *gSaveFailed;\r
55CHAR16 *gMoveHighlight;\r
56CHAR16 *gMakeSelection;\r
57CHAR16 *gDecNumericInput;\r
58CHAR16 *gHexNumericInput;\r
59CHAR16 *gToggleCheckBox;\r
60CHAR16 *gPromptForData;\r
61CHAR16 *gPromptForPassword;\r
62CHAR16 *gPromptForNewPassword;\r
63CHAR16 *gConfirmPassword;\r
64CHAR16 *gConfirmError;\r
65CHAR16 *gPassowordInvalid;\r
66CHAR16 *gPressEnter;\r
67CHAR16 *gEmptyString;\r
68CHAR16 *gAreYouSure;\r
69CHAR16 *gYesResponse;\r
70CHAR16 *gNoResponse;\r
71CHAR16 *gMiniString;\r
72CHAR16 *gPlusString;\r
73CHAR16 *gMinusString;\r
74CHAR16 *gAdjustNumber;\r
ebe43565 75CHAR16 *gSaveChanges;\r
8d00a0f1 76CHAR16 *gOptionMismatch;\r
7936fb6a 77\r
0e8e994d 78CHAR16 *mUnknownString = L"!";\r
79\r
7936fb6a 80CHAR16 gPromptBlockWidth;\r
81CHAR16 gOptionBlockWidth;\r
82CHAR16 gHelpBlockWidth;\r
83\r
84EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
85EFI_GUID gSetupBrowserGuid = {\r
86 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
87};\r
88\r
ce6d12cc 89FORM_BROWSER_FORMSET *gOldFormSet;\r
d66e6c16 90\r
7936fb6a 91FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
92 //\r
93 // Boot Manager\r
94 //\r
95 {\r
96 {\r
97 0x847bc3fe,\r
98 0xb974,\r
99 0x446d,\r
100 {\r
101 0x94,\r
102 0x49,\r
103 0x5a,\r
104 0xd5,\r
105 0x41,\r
106 0x2e,\r
107 0x99,\r
108 0x3b\r
109 }\r
110 },\r
111 NONE_FUNCTION_KEY_SETTING\r
112 },\r
113 //\r
114 // Device Manager\r
115 //\r
116 {\r
117 {\r
118 0x3ebfa8e6,\r
119 0x511d,\r
120 0x4b5b,\r
121 {\r
122 0xa9,\r
123 0x5f,\r
124 0xfb,\r
125 0x38,\r
126 0x26,\r
127 0xf,\r
128 0x1c,\r
129 0x27\r
130 }\r
131 },\r
132 NONE_FUNCTION_KEY_SETTING\r
133 },\r
134 //\r
135 // BMM FormSet.\r
136 //\r
137 {\r
138 {\r
139 0x642237c7,\r
140 0x35d4,\r
141 0x472d,\r
142 {\r
143 0x83,\r
144 0x65,\r
145 0x12,\r
146 0xe0,\r
147 0xcc,\r
148 0xf2,\r
149 0x7a,\r
150 0x22\r
151 }\r
152 },\r
153 NONE_FUNCTION_KEY_SETTING\r
154 },\r
155 //\r
156 // BMM File Explorer FormSet.\r
157 //\r
158 {\r
159 {\r
160 0x1f2d63e1,\r
161 0xfebd,\r
162 0x4dc7,\r
163 {\r
164 0x9c,\r
165 0xc5,\r
166 0xba,\r
167 0x2b,\r
168 0x1c,\r
169 0xef,\r
170 0x9c,\r
171 0x5b\r
172 }\r
173 },\r
174 NONE_FUNCTION_KEY_SETTING\r
175 },\r
176};\r
177\r
178/**\r
179 This is the routine which an external caller uses to direct the browser\r
180 where to obtain it's information.\r
181\r
182\r
183 @param This The Form Browser protocol instanse.\r
184 @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
185 display a list of the formsets for the handles specified.\r
186 @param HandleCount The number of Handles specified in Handle.\r
187 @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
188 field in the EFI_IFR_FORM_SET op-code for the specified\r
189 forms-based package. If FormSetGuid is NULL, then this\r
190 function will display the first found forms package.\r
191 @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
192 displayable page. If this field has a value of 0x0000, then\r
193 the forms browser will render the specified forms in their encoded order.\r
d66e6c16 194 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
7936fb6a 195 characters.\r
f02d0c0f 196 @param ActionRequest Points to the action recommended by the form.\r
7936fb6a 197\r
198 @retval EFI_SUCCESS The function completed successfully.\r
199 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
200 @retval EFI_NOT_FOUND No valid forms could be found to display.\r
201\r
202**/\r
203EFI_STATUS\r
204EFIAPI\r
205SendForm (\r
206 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
207 IN EFI_HII_HANDLE *Handles,\r
208 IN UINTN HandleCount,\r
209 IN EFI_GUID *FormSetGuid, OPTIONAL\r
210 IN UINT16 FormId, OPTIONAL\r
211 IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
212 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
213 )\r
214{\r
519f076a 215 EFI_STATUS Status;\r
216 UI_MENU_SELECTION *Selection;\r
217 UINTN Index;\r
218 FORM_BROWSER_FORMSET *FormSet;\r
7936fb6a 219\r
ce6d12cc 220 //\r
221 // Save globals used by SendForm()\r
222 //\r
223 SaveBrowserContext ();\r
224\r
7936fb6a 225 Status = EFI_SUCCESS;\r
226 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
227\r
228 //\r
229 // Seed the dimensions in the global\r
230 //\r
231 gST->ConOut->QueryMode (\r
232 gST->ConOut,\r
233 gST->ConOut->Mode->Mode,\r
234 &gScreenDimensions.RightColumn,\r
235 &gScreenDimensions.BottomRow\r
236 );\r
237\r
238 if (ScreenDimensions != NULL) {\r
239 //\r
240 // Check local dimension vs. global dimension.\r
241 //\r
242 if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
243 (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
244 ) {\r
ce6d12cc 245 Status = EFI_INVALID_PARAMETER;\r
246 goto Done;\r
7936fb6a 247 } else {\r
248 //\r
249 // Local dimension validation.\r
250 //\r
251 if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
252 (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
253 ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
254 (\r
255 (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
256 SCROLL_ARROW_HEIGHT *\r
257 2 +\r
258 FRONT_PAGE_HEADER_HEIGHT +\r
259 FOOTER_HEIGHT +\r
260 1\r
261 )\r
262 ) {\r
263 CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
264 } else {\r
ce6d12cc 265 Status = EFI_INVALID_PARAMETER;\r
266 goto Done;\r
7936fb6a 267 }\r
268 }\r
269 }\r
270\r
271 gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
272 gHelpBlockWidth = gOptionBlockWidth;\r
273 gPromptBlockWidth = gOptionBlockWidth;\r
274\r
275 //\r
276 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
277 //\r
278 InitializeBrowserStrings ();\r
279\r
280 gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
0a1147ed 281 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
7936fb6a 282\r
283 //\r
284 // Ensure we are in Text mode\r
285 //\r
ebe43565 286 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
519f076a 287\r
7936fb6a 288 for (Index = 0; Index < HandleCount; Index++) {\r
289 Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
290 ASSERT (Selection != NULL);\r
291\r
292 Selection->Handle = Handles[Index];\r
293 if (FormSetGuid != NULL) {\r
294 CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
295 Selection->FormId = FormId;\r
296 }\r
297\r
ce6d12cc 298 gOldFormSet = NULL;\r
d66e6c16 299 gNvUpdateRequired = FALSE;\r
300\r
7936fb6a 301 do {\r
302 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
303 ASSERT (FormSet != NULL);\r
304\r
305 //\r
306 // Initialize internal data structures of FormSet\r
307 //\r
308 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
e8e36190 309 if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
7936fb6a 310 DestroyFormSet (FormSet);\r
311 break;\r
312 }\r
313 Selection->FormSet = FormSet;\r
314\r
7936fb6a 315 //\r
316 // Display this formset\r
317 //\r
318 gCurrentSelection = Selection;\r
319\r
320 Status = SetupBrowser (Selection);\r
321\r
322 gCurrentSelection = NULL;\r
7936fb6a 323\r
324 if (EFI_ERROR (Status)) {\r
325 break;\r
326 }\r
327\r
328 } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
329\r
d66e6c16 330 if (gOldFormSet != NULL) {\r
331 DestroyFormSet (gOldFormSet);\r
332 gOldFormSet = NULL;\r
333 }\r
334\r
f4113e1f 335 FreePool (Selection);\r
7936fb6a 336 }\r
337\r
338 if (ActionRequest != NULL) {\r
339 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
340 if (gResetRequired) {\r
341 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
342 }\r
343 }\r
344\r
345 FreeBrowserStrings ();\r
346\r
347 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
348 gST->ConOut->ClearScreen (gST->ConOut);\r
349\r
ce6d12cc 350Done:\r
351 //\r
352 // Restore globals used by SendForm()\r
353 //\r
354 RestoreBrowserContext ();\r
355\r
7936fb6a 356 return Status;\r
357}\r
358\r
359\r
360/**\r
361 This function is called by a callback handler to retrieve uncommitted state\r
362 data from the browser.\r
363\r
364 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
365 instance.\r
366 @param ResultsDataSize A pointer to the size of the buffer associated\r
367 with ResultsData.\r
368 @param ResultsData A string returned from an IFR browser or\r
369 equivalent. The results string will have no\r
370 routing information in them.\r
371 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
372 (if RetrieveData = TRUE) data from the uncommitted\r
373 browser state information or set (if RetrieveData\r
374 = FALSE) data in the uncommitted browser state\r
375 information.\r
376 @param VariableGuid An optional field to indicate the target variable\r
377 GUID name to use.\r
378 @param VariableName An optional field to indicate the target\r
379 human-readable variable name.\r
380\r
381 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
382 distribution.\r
383 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
384 contain the results data.\r
385\r
386**/\r
387EFI_STATUS\r
388EFIAPI\r
389BrowserCallback (\r
390 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
391 IN OUT UINTN *ResultsDataSize,\r
392 IN OUT EFI_STRING ResultsData,\r
393 IN BOOLEAN RetrieveData,\r
394 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
395 IN CONST CHAR16 *VariableName OPTIONAL\r
396 )\r
397{\r
398 EFI_STATUS Status;\r
399 LIST_ENTRY *Link;\r
400 FORMSET_STORAGE *Storage;\r
401 FORM_BROWSER_FORMSET *FormSet;\r
402 BOOLEAN Found;\r
403 CHAR16 *ConfigResp;\r
404 CHAR16 *StrPtr;\r
405 UINTN BufferSize;\r
406 UINTN TmpSize;\r
407\r
408 if (ResultsDataSize == NULL || ResultsData == NULL) {\r
409 return EFI_INVALID_PARAMETER;\r
410 }\r
411\r
412 if (gCurrentSelection == NULL) {\r
413 return EFI_NOT_READY;\r
414 }\r
415\r
416 Storage = NULL;\r
417 ConfigResp = NULL;\r
418 FormSet = gCurrentSelection->FormSet;\r
419\r
420 //\r
421 // Find target storage\r
422 //\r
423 Link = GetFirstNode (&FormSet->StorageListHead);\r
424 if (IsNull (&FormSet->StorageListHead, Link)) {\r
425 return EFI_UNSUPPORTED;\r
426 }\r
427\r
428 if (VariableGuid != NULL) {\r
429 //\r
430 // Try to find target storage\r
431 //\r
432 Found = FALSE;\r
433 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
434 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
435 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
436\r
437 if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
438 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
439 //\r
440 // Buffer storage require both GUID and Name\r
441 //\r
442 if (VariableName == NULL) {\r
443 return EFI_NOT_FOUND;\r
444 }\r
445\r
446 if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
447 continue;\r
448 }\r
449 }\r
450 Found = TRUE;\r
451 break;\r
452 }\r
453 }\r
454\r
455 if (!Found) {\r
456 return EFI_NOT_FOUND;\r
457 }\r
458 } else {\r
459 //\r
460 // GUID/Name is not specified, take the first storage in FormSet\r
461 //\r
462 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
463 }\r
464\r
465 if (RetrieveData) {\r
466 //\r
467 // Skip if there is no RequestElement\r
468 //\r
469 if (Storage->ElementCount == 0) {\r
470 return EFI_SUCCESS;\r
471 }\r
472\r
473 //\r
474 // Generate <ConfigResp>\r
475 //\r
476 Status = StorageToConfigResp (Storage, &ConfigResp);\r
477 if (EFI_ERROR (Status)) {\r
478 return Status;\r
479 }\r
480\r
481 //\r
482 // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
483 //\r
484 StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
485\r
486 BufferSize = StrSize (StrPtr);\r
487 if (*ResultsDataSize < BufferSize) {\r
488 *ResultsDataSize = BufferSize;\r
489\r
f4113e1f 490 FreePool (ConfigResp);\r
7936fb6a 491 return EFI_BUFFER_TOO_SMALL;\r
492 }\r
493\r
494 *ResultsDataSize = BufferSize;\r
495 CopyMem (ResultsData, StrPtr, BufferSize);\r
496\r
f4113e1f 497 FreePool (ConfigResp);\r
7936fb6a 498 } else {\r
499 //\r
500 // Prepare <ConfigResp>\r
501 //\r
502 TmpSize = StrLen (ResultsData);\r
503 BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
504 ConfigResp = AllocateZeroPool (BufferSize);\r
505 ASSERT (ConfigResp != NULL);\r
506\r
507 StrCpy (ConfigResp, Storage->ConfigHdr);\r
508 StrCat (ConfigResp, L"&");\r
509 StrCat (ConfigResp, ResultsData);\r
510\r
511 //\r
512 // Update Browser uncommited data\r
513 //\r
514 Status = ConfigRespToStorage (Storage, ConfigResp);\r
515 if (EFI_ERROR (Status)) {\r
516 return Status;\r
517 }\r
518 }\r
519\r
520 return EFI_SUCCESS;\r
521}\r
522\r
523\r
524/**\r
525 Initialize Setup Browser driver.\r
526\r
527 @param ImageHandle The image handle.\r
528 @param SystemTable The system table.\r
529\r
530 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
531 @return Other value if failed to initialize the Setup Browser module.\r
532\r
533**/\r
534EFI_STATUS\r
535EFIAPI\r
536InitializeSetup (\r
537 IN EFI_HANDLE ImageHandle,\r
538 IN EFI_SYSTEM_TABLE *SystemTable\r
539 )\r
540{\r
541 EFI_STATUS Status;\r
7936fb6a 542\r
543 //\r
544 // Locate required Hii relative protocols\r
545 //\r
546 Status = gBS->LocateProtocol (\r
547 &gEfiHiiDatabaseProtocolGuid,\r
548 NULL,\r
549 (VOID **) &mHiiDatabase\r
550 );\r
551 ASSERT_EFI_ERROR (Status);\r
552\r
553 Status = gBS->LocateProtocol (\r
554 &gEfiHiiStringProtocolGuid,\r
555 NULL,\r
556 (VOID **) &mHiiString\r
557 );\r
558 ASSERT_EFI_ERROR (Status);\r
559\r
560 Status = gBS->LocateProtocol (\r
561 &gEfiHiiConfigRoutingProtocolGuid,\r
562 NULL,\r
563 (VOID **) &mHiiConfigRouting\r
564 );\r
565 ASSERT_EFI_ERROR (Status);\r
566\r
567 //\r
568 // Publish our HII data\r
569 //\r
cb7d01c0 570 gHiiHandle = HiiAddPackages (\r
571 &gSetupBrowserGuid,\r
572 ImageHandle,\r
573 SetupBrowserStrings,\r
574 NULL\r
575 );\r
576 ASSERT (gHiiHandle != NULL);\r
7936fb6a 577\r
578 //\r
579 // Initialize Driver private data\r
580 //\r
0a1147ed
LG
581 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
582 ASSERT (gBannerData != NULL);\r
7936fb6a 583\r
584 //\r
585 // Install FormBrowser2 protocol\r
586 //\r
587 mPrivateData.Handle = NULL;\r
588 Status = gBS->InstallProtocolInterface (\r
589 &mPrivateData.Handle,\r
590 &gEfiFormBrowser2ProtocolGuid,\r
591 EFI_NATIVE_INTERFACE,\r
592 &mPrivateData.FormBrowser2\r
593 );\r
594 ASSERT_EFI_ERROR (Status);\r
595\r
7936fb6a 596 return Status;\r
597}\r
598\r
599\r
600/**\r
601 Create a new string in HII Package List.\r
602\r
603 @param String The String to be added\r
604 @param HiiHandle The package list in the HII database to insert the\r
605 specified string.\r
606\r
607 @return The output string.\r
608\r
609**/\r
610EFI_STRING_ID\r
611NewString (\r
612 IN CHAR16 *String,\r
613 IN EFI_HII_HANDLE HiiHandle\r
614 )\r
615{\r
616 EFI_STRING_ID StringId;\r
7936fb6a 617\r
cb7d01c0 618 StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
619 ASSERT (StringId != 0);\r
7936fb6a 620\r
621 return StringId;\r
622}\r
623\r
624\r
625/**\r
626 Delete a string from HII Package List.\r
627\r
628 @param StringId Id of the string in HII database.\r
629 @param HiiHandle The HII package list handle.\r
630\r
631 @retval EFI_SUCCESS The string was deleted successfully.\r
632\r
633**/\r
634EFI_STATUS\r
635DeleteString (\r
636 IN EFI_STRING_ID StringId,\r
637 IN EFI_HII_HANDLE HiiHandle\r
638 )\r
639{\r
640 CHAR16 NullChar;\r
641\r
642 NullChar = CHAR_NULL;\r
cb7d01c0 643 HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
644 return EFI_SUCCESS;\r
7936fb6a 645}\r
646\r
647\r
648/**\r
649 Get the string based on the StringId and HII Package List Handle.\r
650\r
651 @param Token The String's ID.\r
652 @param HiiHandle The package list in the HII database to search for\r
653 the specified string.\r
654\r
655 @return The output string.\r
656\r
657**/\r
658CHAR16 *\r
659GetToken (\r
660 IN EFI_STRING_ID Token,\r
661 IN EFI_HII_HANDLE HiiHandle\r
662 )\r
663{\r
cb7d01c0 664 EFI_STRING String;\r
7936fb6a 665\r
cb7d01c0 666 String = HiiGetString (HiiHandle, Token, NULL);\r
0e8e994d 667 if (String == NULL) {\r
668 String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
669 ASSERT (String != NULL);\r
670 }\r
cb7d01c0 671 return (CHAR16 *) String;\r
7936fb6a 672}\r
673\r
674\r
675/**\r
676 Allocate new memory and then copy the Unicode string Source to Destination.\r
677\r
678 @param Dest Location to copy string\r
679 @param Src String to copy\r
680\r
681**/\r
682VOID\r
683NewStringCpy (\r
684 IN OUT CHAR16 **Dest,\r
685 IN CHAR16 *Src\r
686 )\r
687{\r
676df92c 688 if (*Dest != NULL) {\r
689 FreePool (*Dest);\r
690 }\r
7936fb6a 691 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
692 ASSERT (*Dest != NULL);\r
693}\r
694\r
695\r
696/**\r
697 Allocate new memory and concatinate Source on the end of Destination.\r
698\r
699 @param Dest String to added to the end of.\r
700 @param Src String to concatinate.\r
701\r
702**/\r
703VOID\r
704NewStringCat (\r
705 IN OUT CHAR16 **Dest,\r
706 IN CHAR16 *Src\r
707 )\r
708{\r
709 CHAR16 *NewString;\r
710 UINTN TmpSize;\r
711\r
712 if (*Dest == NULL) {\r
713 NewStringCpy (Dest, Src);\r
714 return;\r
715 }\r
716\r
717 TmpSize = StrSize (*Dest);\r
718 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
719 ASSERT (NewString != NULL);\r
720\r
721 StrCpy (NewString, *Dest);\r
722 StrCat (NewString, Src);\r
723\r
f4113e1f 724 FreePool (*Dest);\r
7936fb6a 725 *Dest = NewString;\r
726}\r
727\r
728\r
729/**\r
730 Synchronize Storage's Edit copy to Shadow copy.\r
731\r
732 @param Storage The Storage to be synchronized.\r
733\r
734**/\r
735VOID\r
736SynchronizeStorage (\r
737 IN FORMSET_STORAGE *Storage\r
738 )\r
739{\r
740 LIST_ENTRY *Link;\r
741 NAME_VALUE_NODE *Node;\r
742\r
743 switch (Storage->Type) {\r
744 case EFI_HII_VARSTORE_BUFFER:\r
745 CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
746 break;\r
747\r
748 case EFI_HII_VARSTORE_NAME_VALUE:\r
749 Link = GetFirstNode (&Storage->NameValueListHead);\r
750 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
751 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
752\r
753 NewStringCpy (&Node->Value, Node->EditValue);\r
754\r
755 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
756 }\r
757 break;\r
758\r
759 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
760 default:\r
761 break;\r
762 }\r
763}\r
764\r
765\r
766/**\r
767 Get Value for given Name from a NameValue Storage.\r
768\r
769 @param Storage The NameValue Storage.\r
770 @param Name The Name.\r
771 @param Value The retured Value.\r
772\r
773 @retval EFI_SUCCESS Value found for given Name.\r
774 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
775\r
776**/\r
777EFI_STATUS\r
778GetValueByName (\r
779 IN FORMSET_STORAGE *Storage,\r
780 IN CHAR16 *Name,\r
781 IN OUT CHAR16 **Value\r
782 )\r
783{\r
784 LIST_ENTRY *Link;\r
785 NAME_VALUE_NODE *Node;\r
786\r
787 *Value = NULL;\r
788\r
789 Link = GetFirstNode (&Storage->NameValueListHead);\r
790 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
791 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
792\r
793 if (StrCmp (Name, Node->Name) == 0) {\r
794 NewStringCpy (Value, Node->EditValue);\r
795 return EFI_SUCCESS;\r
796 }\r
797\r
798 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
799 }\r
800\r
801 return EFI_NOT_FOUND;\r
802}\r
803\r
804\r
805/**\r
806 Set Value of given Name in a NameValue Storage.\r
807\r
808 @param Storage The NameValue Storage.\r
809 @param Name The Name.\r
810 @param Value The Value to set.\r
811\r
812 @retval EFI_SUCCESS Value found for given Name.\r
813 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
814\r
815**/\r
816EFI_STATUS\r
817SetValueByName (\r
818 IN FORMSET_STORAGE *Storage,\r
819 IN CHAR16 *Name,\r
820 IN CHAR16 *Value\r
821 )\r
822{\r
823 LIST_ENTRY *Link;\r
824 NAME_VALUE_NODE *Node;\r
825\r
826 Link = GetFirstNode (&Storage->NameValueListHead);\r
827 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
828 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
829\r
830 if (StrCmp (Name, Node->Name) == 0) {\r
676df92c 831 if (Node->EditValue != NULL) {\r
832 FreePool (Node->EditValue);\r
833 }\r
7936fb6a 834 Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
835 ASSERT (Node->EditValue != NULL);\r
836 return EFI_SUCCESS;\r
837 }\r
838\r
839 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
840 }\r
841\r
842 return EFI_NOT_FOUND;\r
843}\r
844\r
845\r
846/**\r
847 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
848\r
849 @param Storage The Storage to be conveted.\r
850 @param ConfigResp The returned <ConfigResp>.\r
851\r
852 @retval EFI_SUCCESS Convert success.\r
853 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
854\r
855**/\r
856EFI_STATUS\r
857StorageToConfigResp (\r
858 IN FORMSET_STORAGE *Storage,\r
859 IN CHAR16 **ConfigResp\r
860 )\r
861{\r
862 EFI_STATUS Status;\r
863 EFI_STRING Progress;\r
864 LIST_ENTRY *Link;\r
865 NAME_VALUE_NODE *Node;\r
866\r
867 Status = EFI_SUCCESS;\r
868\r
869 switch (Storage->Type) {\r
870 case EFI_HII_VARSTORE_BUFFER:\r
871 Status = mHiiConfigRouting->BlockToConfig (\r
872 mHiiConfigRouting,\r
873 Storage->ConfigRequest,\r
874 Storage->EditBuffer,\r
875 Storage->Size,\r
876 ConfigResp,\r
877 &Progress\r
878 );\r
879 break;\r
880\r
881 case EFI_HII_VARSTORE_NAME_VALUE:\r
882 *ConfigResp = NULL;\r
883 NewStringCat (ConfigResp, Storage->ConfigHdr);\r
884\r
885 Link = GetFirstNode (&Storage->NameValueListHead);\r
886 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
887 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
888\r
889 NewStringCat (ConfigResp, L"&");\r
890 NewStringCat (ConfigResp, Node->Name);\r
891 NewStringCat (ConfigResp, L"=");\r
892 NewStringCat (ConfigResp, Node->EditValue);\r
893\r
894 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
895 }\r
896 break;\r
897\r
898 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
899 default:\r
900 Status = EFI_INVALID_PARAMETER;\r
901 break;\r
902 }\r
903\r
904 return Status;\r
905}\r
906\r
907\r
908/**\r
909 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
910\r
911 @param Storage The Storage to receive the settings.\r
912 @param ConfigResp The <ConfigResp> to be converted.\r
913\r
914 @retval EFI_SUCCESS Convert success.\r
915 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
916\r
917**/\r
918EFI_STATUS\r
919ConfigRespToStorage (\r
920 IN FORMSET_STORAGE *Storage,\r
921 IN CHAR16 *ConfigResp\r
922 )\r
923{\r
924 EFI_STATUS Status;\r
925 EFI_STRING Progress;\r
926 UINTN BufferSize;\r
927 CHAR16 *StrPtr;\r
928 CHAR16 *Name;\r
929 CHAR16 *Value;\r
930\r
931 Status = EFI_SUCCESS;\r
932\r
933 switch (Storage->Type) {\r
934 case EFI_HII_VARSTORE_BUFFER:\r
935 BufferSize = Storage->Size;\r
936 Status = mHiiConfigRouting->ConfigToBlock (\r
937 mHiiConfigRouting,\r
938 ConfigResp,\r
939 Storage->EditBuffer,\r
940 &BufferSize,\r
941 &Progress\r
942 );\r
943 break;\r
944\r
945 case EFI_HII_VARSTORE_NAME_VALUE:\r
946 StrPtr = StrStr (ConfigResp, L"&");\r
947 while (StrPtr != NULL) {\r
948 //\r
949 // Skip '&'\r
950 //\r
951 StrPtr = StrPtr + 1;\r
952 Name = StrPtr;\r
953 StrPtr = StrStr (StrPtr, L"=");\r
954 if (StrPtr == NULL) {\r
955 break;\r
956 }\r
957 *StrPtr = 0;\r
958\r
959 //\r
960 // Skip '='\r
961 //\r
962 StrPtr = StrPtr + 1;\r
963 Value = StrPtr;\r
964 StrPtr = StrStr (StrPtr, L"&");\r
965 if (StrPtr != NULL) {\r
966 *StrPtr = 0;\r
967 }\r
968 SetValueByName (Storage, Name, Value);\r
969 }\r
970 break;\r
971\r
972 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
973 default:\r
974 Status = EFI_INVALID_PARAMETER;\r
975 break;\r
976 }\r
977\r
978 return Status;\r
979}\r
980\r
981\r
982/**\r
983 Get Question's current Value.\r
984\r
985 @param FormSet FormSet data structure.\r
986 @param Form Form data structure.\r
987 @param Question Question to be initialized.\r
988 @param Cached TRUE: get from Edit copy FALSE: get from original\r
989 Storage\r
990\r
991 @retval EFI_SUCCESS The function completed successfully.\r
992\r
993**/\r
994EFI_STATUS\r
995GetQuestionValue (\r
996 IN FORM_BROWSER_FORMSET *FormSet,\r
997 IN FORM_BROWSER_FORM *Form,\r
998 IN OUT FORM_BROWSER_STATEMENT *Question,\r
999 IN BOOLEAN Cached\r
1000 )\r
1001{\r
1002 EFI_STATUS Status;\r
1003 BOOLEAN Enabled;\r
1004 BOOLEAN Pending;\r
1005 UINT8 *Dst;\r
1006 UINTN StorageWidth;\r
1007 EFI_TIME EfiTime;\r
1008 FORMSET_STORAGE *Storage;\r
1009 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1010 CHAR16 *ConfigRequest;\r
1011 CHAR16 *Progress;\r
1012 CHAR16 *Result;\r
1013 CHAR16 *Value;\r
8d00a0f1 1014 CHAR16 *StringPtr;\r
7936fb6a 1015 UINTN Length;\r
63d55bb9
LG
1016 UINTN Index;\r
1017 UINTN LengthStr;\r
7936fb6a 1018 BOOLEAN IsBufferStorage;\r
1019 BOOLEAN IsString;\r
63d55bb9
LG
1020 CHAR16 TemStr[5];\r
1021 UINT8 DigitUint8;\r
7936fb6a 1022\r
1023 Status = EFI_SUCCESS;\r
1024\r
1025 //\r
1026 // Statement don't have storage, skip them\r
1027 //\r
1028 if (Question->QuestionId == 0) {\r
1029 return Status;\r
1030 }\r
1031\r
1032 //\r
1033 // Question value is provided by an Expression, evaluate it\r
1034 //\r
1035 if (Question->ValueExpression != NULL) {\r
1036 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1037 if (!EFI_ERROR (Status)) {\r
1038 CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1039 }\r
1040 return Status;\r
1041 }\r
1042\r
1043 //\r
1044 // Question value is provided by RTC\r
1045 //\r
1046 Storage = Question->Storage;\r
1047 QuestionValue = &Question->HiiValue.Value;\r
1048 if (Storage == NULL) {\r
1049 //\r
1050 // It's a Question without storage, or RTC date/time\r
1051 //\r
1052 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1053 //\r
1054 // Date and time define the same Flags bit\r
1055 //\r
1056 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1057 case QF_DATE_STORAGE_TIME:\r
1058 Status = gRT->GetTime (&EfiTime, NULL);\r
1059 break;\r
1060\r
1061 case QF_DATE_STORAGE_WAKEUP:\r
1062 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1063 break;\r
1064\r
1065 case QF_DATE_STORAGE_NORMAL:\r
1066 default:\r
1067 //\r
1068 // For date/time without storage\r
1069 //\r
1070 return EFI_SUCCESS;\r
1071 }\r
1072\r
1073 if (EFI_ERROR (Status)) {\r
1074 return Status;\r
1075 }\r
1076\r
1077 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1078 QuestionValue->date.Year = EfiTime.Year;\r
1079 QuestionValue->date.Month = EfiTime.Month;\r
1080 QuestionValue->date.Day = EfiTime.Day;\r
1081 } else {\r
1082 QuestionValue->time.Hour = EfiTime.Hour;\r
1083 QuestionValue->time.Minute = EfiTime.Minute;\r
1084 QuestionValue->time.Second = EfiTime.Second;\r
1085 }\r
1086 }\r
1087\r
1088 return EFI_SUCCESS;\r
1089 }\r
1090\r
1091 //\r
1092 // Question value is provided by EFI variable\r
1093 //\r
1094 StorageWidth = Question->StorageWidth;\r
1095 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1096 if (Question->BufferValue != NULL) {\r
1097 Dst = Question->BufferValue;\r
1098 } else {\r
1099 Dst = (UINT8 *) QuestionValue;\r
1100 }\r
1101\r
1102 Status = gRT->GetVariable (\r
1103 Question->VariableName,\r
1104 &Storage->Guid,\r
1105 NULL,\r
1106 &StorageWidth,\r
1107 Dst\r
1108 );\r
1109 //\r
1110 // Always return success, even this EFI variable doesn't exist\r
1111 //\r
1112 return EFI_SUCCESS;\r
1113 }\r
1114\r
1115 //\r
1116 // Question Value is provided by Buffer Storage or NameValue Storage\r
1117 //\r
1118 if (Question->BufferValue != NULL) {\r
1119 //\r
1120 // This Question is password or orderedlist\r
1121 //\r
1122 Dst = Question->BufferValue;\r
1123 } else {\r
1124 //\r
1125 // Other type of Questions\r
1126 //\r
1127 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1128 }\r
1129\r
1130 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1131 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1132 if (Cached) {\r
1133 if (IsBufferStorage) {\r
1134 //\r
1135 // Copy from storage Edit buffer\r
1136 //\r
1137 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1138 } else {\r
1139 Status = GetValueByName (Storage, Question->VariableName, &Value);\r
1140 if (EFI_ERROR (Status)) {\r
1141 return Status;\r
1142 }\r
d66e6c16 1143\r
63d55bb9
LG
1144 LengthStr = StrLen (Value);\r
1145 Status = EFI_SUCCESS;\r
7936fb6a 1146 if (IsString) {\r
1147 //\r
1148 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1149 // Add string tail char L'\0' into Length\r
7936fb6a 1150 //\r
63d55bb9
LG
1151 Length = StorageWidth + sizeof (CHAR16);\r
1152 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1153 Status = EFI_BUFFER_TOO_SMALL;\r
1154 } else {\r
1155 StringPtr = (CHAR16 *) Dst;\r
1156 ZeroMem (TemStr, sizeof (TemStr));\r
1157 for (Index = 0; Index < LengthStr; Index += 4) {\r
1158 StrnCpy (TemStr, Value + Index, 4);\r
1159 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1160 }\r
1161 //\r
1162 // Add tailing L'\0' character\r
1163 //\r
1164 StringPtr[Index/4] = L'\0';\r
1165 }\r
7936fb6a 1166 } else {\r
63d55bb9
LG
1167 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1168 Status = EFI_BUFFER_TOO_SMALL;\r
1169 } else {\r
1170 ZeroMem (TemStr, sizeof (TemStr));\r
1171 for (Index = 0; Index < LengthStr; Index ++) {\r
1172 TemStr[0] = Value[LengthStr - Index - 1];\r
1173 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1174 if ((Index & 1) == 0) {\r
1175 Dst [Index/2] = DigitUint8;\r
1176 } else {\r
634303c9 1177 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1178 }\r
1179 }\r
1180 }\r
7936fb6a 1181 }\r
1182\r
f4113e1f 1183 FreePool (Value);\r
7936fb6a 1184 }\r
1185 } else {\r
1186 //\r
1187 // Request current settings from Configuration Driver\r
1188 //\r
1189 if (FormSet->ConfigAccess == NULL) {\r
1190 return EFI_NOT_FOUND;\r
1191 }\r
1192\r
1193 //\r
1194 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1195 // <ConfigHdr> + "&" + <VariableName>\r
1196 //\r
1197 if (IsBufferStorage) {\r
1198 Length = StrLen (Storage->ConfigHdr);\r
1199 Length += StrLen (Question->BlockName);\r
1200 } else {\r
1201 Length = StrLen (Storage->ConfigHdr);\r
1202 Length += StrLen (Question->VariableName) + 1;\r
1203 }\r
1204 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1205 ASSERT (ConfigRequest != NULL);\r
1206\r
1207 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1208 if (IsBufferStorage) {\r
1209 StrCat (ConfigRequest, Question->BlockName);\r
1210 } else {\r
1211 StrCat (ConfigRequest, L"&");\r
1212 StrCat (ConfigRequest, Question->VariableName);\r
1213 }\r
1214\r
1215 Status = FormSet->ConfigAccess->ExtractConfig (\r
1216 FormSet->ConfigAccess,\r
1217 ConfigRequest,\r
1218 &Progress,\r
1219 &Result\r
1220 );\r
1221 if (EFI_ERROR (Status)) {\r
1222 return Status;\r
1223 }\r
1224\r
1225 //\r
1226 // Skip <ConfigRequest>\r
1227 //\r
1228 Value = Result + Length;\r
1229 if (IsBufferStorage) {\r
1230 //\r
1231 // Skip "&VALUE"\r
1232 //\r
1233 Value = Value + 6;\r
1234 }\r
1235 if (*Value != '=') {\r
f4113e1f 1236 FreePool (Result);\r
7936fb6a 1237 return EFI_NOT_FOUND;\r
1238 }\r
1239 //\r
1240 // Skip '=', point to value\r
1241 //\r
1242 Value = Value + 1;\r
8d00a0f1 1243\r
1244 //\r
1245 // Suppress <AltResp> if any\r
1246 //\r
1247 StringPtr = Value;\r
1248 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1249 StringPtr++;\r
1250 }\r
1251 *StringPtr = L'\0';\r
1252\r
63d55bb9
LG
1253 LengthStr = StrLen (Value);\r
1254 Status = EFI_SUCCESS;\r
7936fb6a 1255 if (!IsBufferStorage && IsString) {\r
1256 //\r
1257 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1258 // Add string tail char L'\0' into Length\r
7936fb6a 1259 //\r
63d55bb9
LG
1260 Length = StorageWidth + sizeof (CHAR16);\r
1261 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1262 Status = EFI_BUFFER_TOO_SMALL;\r
1263 } else {\r
1264 StringPtr = (CHAR16 *) Dst;\r
1265 ZeroMem (TemStr, sizeof (TemStr));\r
1266 for (Index = 0; Index < LengthStr; Index += 4) {\r
1267 StrnCpy (TemStr, Value + Index, 4);\r
1268 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1269 }\r
1270 //\r
1271 // Add tailing L'\0' character\r
1272 //\r
1273 StringPtr[Index/4] = L'\0';\r
1274 }\r
7936fb6a 1275 } else {\r
63d55bb9
LG
1276 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1277 Status = EFI_BUFFER_TOO_SMALL;\r
1278 } else {\r
1279 ZeroMem (TemStr, sizeof (TemStr));\r
1280 for (Index = 0; Index < LengthStr; Index ++) {\r
1281 TemStr[0] = Value[LengthStr - Index - 1];\r
1282 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1283 if ((Index & 1) == 0) {\r
1284 Dst [Index/2] = DigitUint8;\r
1285 } else {\r
634303c9 1286 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1287 }\r
1288 }\r
7936fb6a 1289 }\r
1290 }\r
1291\r
63d55bb9
LG
1292 if (EFI_ERROR (Status)) {\r
1293 FreePool (Result);\r
1294 return Status;\r
1295 }\r
1296\r
7936fb6a 1297 //\r
1298 // Synchronize Edit Buffer\r
1299 //\r
1300 if (IsBufferStorage) {\r
1301 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1302 } else {\r
1303 SetValueByName (Storage, Question->VariableName, Value);\r
1304 }\r
63d55bb9 1305\r
f4113e1f 1306 FreePool (Result);\r
7936fb6a 1307 }\r
1308\r
1309 return Status;\r
1310}\r
1311\r
1312\r
1313/**\r
1314 Save Question Value to edit copy(cached) or Storage(uncached).\r
1315\r
1316 @param FormSet FormSet data structure.\r
1317 @param Form Form data structure.\r
1318 @param Question Pointer to the Question.\r
1319 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1320 Storage\r
1321\r
1322 @retval EFI_SUCCESS The function completed successfully.\r
1323\r
1324**/\r
1325EFI_STATUS\r
1326SetQuestionValue (\r
1327 IN FORM_BROWSER_FORMSET *FormSet,\r
1328 IN FORM_BROWSER_FORM *Form,\r
1329 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1330 IN BOOLEAN Cached\r
1331 )\r
1332{\r
1333 EFI_STATUS Status;\r
1334 BOOLEAN Enabled;\r
1335 BOOLEAN Pending;\r
1336 UINT8 *Src;\r
1337 EFI_TIME EfiTime;\r
1338 UINTN BufferLen;\r
1339 UINTN StorageWidth;\r
1340 FORMSET_STORAGE *Storage;\r
1341 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1342 CHAR16 *ConfigResp;\r
1343 CHAR16 *Progress;\r
1344 CHAR16 *Value;\r
1345 UINTN Length;\r
1346 BOOLEAN IsBufferStorage;\r
1347 BOOLEAN IsString;\r
63d55bb9
LG
1348 UINT8 *TemBuffer;\r
1349 CHAR16 *TemName;\r
1350 CHAR16 *TemString;\r
1351 UINTN Index;\r
7936fb6a 1352\r
1353 Status = EFI_SUCCESS;\r
1354\r
1355 //\r
1356 // Statement don't have storage, skip them\r
1357 //\r
1358 if (Question->QuestionId == 0) {\r
1359 return Status;\r
1360 }\r
1361\r
1362 //\r
1363 // If Question value is provided by an Expression, then it is read only\r
1364 //\r
1365 if (Question->ValueExpression != NULL) {\r
1366 return Status;\r
1367 }\r
1368\r
1369 //\r
1370 // Question value is provided by RTC\r
1371 //\r
1372 Storage = Question->Storage;\r
1373 QuestionValue = &Question->HiiValue.Value;\r
1374 if (Storage == NULL) {\r
1375 //\r
1376 // It's a Question without storage, or RTC date/time\r
1377 //\r
1378 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1379 //\r
1380 // Date and time define the same Flags bit\r
1381 //\r
1382 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1383 case QF_DATE_STORAGE_TIME:\r
1384 Status = gRT->GetTime (&EfiTime, NULL);\r
1385 break;\r
1386\r
1387 case QF_DATE_STORAGE_WAKEUP:\r
1388 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1389 break;\r
1390\r
1391 case QF_DATE_STORAGE_NORMAL:\r
1392 default:\r
1393 //\r
1394 // For date/time without storage\r
1395 //\r
1396 return EFI_SUCCESS;\r
1397 }\r
1398\r
1399 if (EFI_ERROR (Status)) {\r
1400 return Status;\r
1401 }\r
1402\r
1403 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1404 EfiTime.Year = QuestionValue->date.Year;\r
1405 EfiTime.Month = QuestionValue->date.Month;\r
1406 EfiTime.Day = QuestionValue->date.Day;\r
1407 } else {\r
1408 EfiTime.Hour = QuestionValue->time.Hour;\r
1409 EfiTime.Minute = QuestionValue->time.Minute;\r
1410 EfiTime.Second = QuestionValue->time.Second;\r
1411 }\r
1412\r
1413 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1414 Status = gRT->SetTime (&EfiTime);\r
1415 } else {\r
1416 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1417 }\r
1418 }\r
1419\r
1420 return Status;\r
1421 }\r
1422\r
1423 //\r
1424 // Question value is provided by EFI variable\r
1425 //\r
1426 StorageWidth = Question->StorageWidth;\r
1427 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1428 if (Question->BufferValue != NULL) {\r
1429 Src = Question->BufferValue;\r
1430 } else {\r
1431 Src = (UINT8 *) QuestionValue;\r
1432 }\r
1433\r
1434 Status = gRT->SetVariable (\r
1435 Question->VariableName,\r
1436 &Storage->Guid,\r
1437 Storage->Attributes,\r
1438 StorageWidth,\r
1439 Src\r
1440 );\r
1441 return Status;\r
1442 }\r
1443\r
1444 //\r
1445 // Question Value is provided by Buffer Storage or NameValue Storage\r
1446 //\r
1447 if (Question->BufferValue != NULL) {\r
1448 Src = Question->BufferValue;\r
1449 } else {\r
1450 Src = (UINT8 *) &Question->HiiValue.Value;\r
1451 }\r
1452\r
1453 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1454 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1455 if (IsBufferStorage) {\r
1456 //\r
1457 // Copy to storage edit buffer\r
1458 //\r
1459 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1460 } else {\r
1461 if (IsString) {\r
1462 //\r
63d55bb9 1463 // Allocate enough string buffer.\r
7936fb6a 1464 //\r
1465 Value = NULL;\r
1466 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1467 Value = AllocateZeroPool (BufferLen);\r
1468 ASSERT (Value != NULL);\r
63d55bb9
LG
1469 //\r
1470 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1471 //\r
1472 TemName = (CHAR16 *) Src;\r
1473 TemString = Value;\r
1474 for (; *TemName != L'\0'; TemName++) {\r
1475 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1476 }\r
7936fb6a 1477 } else {\r
1478 BufferLen = StorageWidth * 2 + 1;\r
1479 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1480 ASSERT (Value != NULL);\r
63d55bb9
LG
1481 //\r
1482 // Convert Buffer to Hex String\r
1483 //\r
1484 TemBuffer = Src + StorageWidth - 1;\r
1485 TemString = Value;\r
1486 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1487 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1488 }\r
7936fb6a 1489 }\r
1490\r
1491 Status = SetValueByName (Storage, Question->VariableName, Value);\r
f4113e1f 1492 FreePool (Value);\r
7936fb6a 1493 }\r
1494\r
1495 if (!Cached) {\r
1496 //\r
1497 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1498 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1499 //\r
1500 if (IsBufferStorage) {\r
1501 Length = StrLen (Question->BlockName) + 7;\r
1502 } else {\r
1503 Length = StrLen (Question->VariableName) + 2;\r
1504 }\r
1505 if (!IsBufferStorage && IsString) {\r
1506 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1507 } else {\r
1508 Length += (StorageWidth * 2);\r
1509 }\r
1510 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1511 ASSERT (ConfigResp != NULL);\r
1512\r
1513 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1514 if (IsBufferStorage) {\r
1515 StrCat (ConfigResp, Question->BlockName);\r
1516 StrCat (ConfigResp, L"&VALUE=");\r
1517 } else {\r
1518 StrCat (ConfigResp, L"&");\r
1519 StrCat (ConfigResp, Question->VariableName);\r
1520 StrCat (ConfigResp, L"=");\r
1521 }\r
1522\r
1523 Value = ConfigResp + StrLen (ConfigResp);\r
63d55bb9 1524\r
7936fb6a 1525 if (!IsBufferStorage && IsString) {\r
1526 //\r
1527 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1528 //\r
63d55bb9
LG
1529 TemName = (CHAR16 *) Src;\r
1530 TemString = Value;\r
1531 for (; *TemName != L'\0'; TemName++) {\r
1532 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1533 }\r
7936fb6a 1534 } else {\r
63d55bb9
LG
1535 //\r
1536 // Convert Buffer to Hex String\r
1537 //\r
1538 TemBuffer = Src + StorageWidth - 1;\r
1539 TemString = Value;\r
1540 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1541 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1542 }\r
1543 }\r
d66e6c16 1544\r
63d55bb9
LG
1545 //\r
1546 // Convert to lower char.\r
1547 //\r
1548 for (TemString = Value; *Value != L'\0'; Value++) {\r
1549 if (*Value >= L'A' && *Value <= L'Z') {\r
1550 *Value = (CHAR16) (*Value - L'A' + L'a');\r
1551 }\r
7936fb6a 1552 }\r
1553\r
1554 //\r
1555 // Submit Question Value to Configuration Driver\r
1556 //\r
1557 if (FormSet->ConfigAccess != NULL) {\r
1558 Status = FormSet->ConfigAccess->RouteConfig (\r
1559 FormSet->ConfigAccess,\r
1560 ConfigResp,\r
1561 &Progress\r
1562 );\r
1563 if (EFI_ERROR (Status)) {\r
f4113e1f 1564 FreePool (ConfigResp);\r
7936fb6a 1565 return Status;\r
1566 }\r
1567 }\r
f4113e1f 1568 FreePool (ConfigResp);\r
7936fb6a 1569\r
1570 //\r
1571 // Synchronize shadow Buffer\r
1572 //\r
1573 SynchronizeStorage (Storage);\r
1574 }\r
1575\r
1576 return Status;\r
1577}\r
1578\r
1579\r
1580/**\r
1581 Perform inconsistent check for a Form.\r
1582\r
1583 @param FormSet FormSet data structure.\r
1584 @param Form Form data structure.\r
1585 @param Question The Question to be validated.\r
1586 @param Type Validation type: InConsistent or NoSubmit\r
1587\r
1588 @retval EFI_SUCCESS Form validation pass.\r
1589 @retval other Form validation failed.\r
1590\r
1591**/\r
1592EFI_STATUS\r
1593ValidateQuestion (\r
1594 IN FORM_BROWSER_FORMSET *FormSet,\r
1595 IN FORM_BROWSER_FORM *Form,\r
1596 IN FORM_BROWSER_STATEMENT *Question,\r
1597 IN UINTN Type\r
1598 )\r
1599{\r
1600 EFI_STATUS Status;\r
1601 LIST_ENTRY *Link;\r
1602 LIST_ENTRY *ListHead;\r
1603 EFI_STRING PopUp;\r
1604 EFI_INPUT_KEY Key;\r
1605 FORM_EXPRESSION *Expression;\r
1606\r
1607 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1608 ListHead = &Question->InconsistentListHead;\r
1609 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1610 ListHead = &Question->NoSubmitListHead;\r
1611 } else {\r
1612 return EFI_UNSUPPORTED;\r
1613 }\r
1614\r
1615 Link = GetFirstNode (ListHead);\r
1616 while (!IsNull (ListHead, Link)) {\r
1617 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1618\r
1619 //\r
1620 // Evaluate the expression\r
1621 //\r
1622 Status = EvaluateExpression (FormSet, Form, Expression);\r
1623 if (EFI_ERROR (Status)) {\r
1624 return Status;\r
1625 }\r
1626\r
1627 if (Expression->Result.Value.b) {\r
1628 //\r
1629 // Condition meet, show up error message\r
1630 //\r
1631 if (Expression->Error != 0) {\r
1632 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1633 do {\r
1634 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1635 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
f4113e1f 1636 FreePool (PopUp);\r
7936fb6a 1637 }\r
1638\r
1639 return EFI_NOT_READY;\r
1640 }\r
1641\r
1642 Link = GetNextNode (ListHead, Link);\r
1643 }\r
1644\r
1645 return EFI_SUCCESS;\r
1646}\r
1647\r
1648\r
1649/**\r
1650 Perform NoSubmit check for a Form.\r
1651\r
1652 @param FormSet FormSet data structure.\r
1653 @param Form Form data structure.\r
1654\r
1655 @retval EFI_SUCCESS Form validation pass.\r
1656 @retval other Form validation failed.\r
1657\r
1658**/\r
1659EFI_STATUS\r
1660NoSubmitCheck (\r
1661 IN FORM_BROWSER_FORMSET *FormSet,\r
1662 IN FORM_BROWSER_FORM *Form\r
1663 )\r
1664{\r
1665 EFI_STATUS Status;\r
1666 LIST_ENTRY *Link;\r
1667 FORM_BROWSER_STATEMENT *Question;\r
1668\r
1669 Link = GetFirstNode (&Form->StatementListHead);\r
1670 while (!IsNull (&Form->StatementListHead, Link)) {\r
1671 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1672\r
1673 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
1674 if (EFI_ERROR (Status)) {\r
1675 return Status;\r
1676 }\r
1677\r
1678 Link = GetNextNode (&Form->StatementListHead, Link);\r
1679 }\r
1680\r
1681 return EFI_SUCCESS;\r
1682}\r
1683\r
1684\r
1685/**\r
1686 Submit a Form.\r
1687\r
1688 @param FormSet FormSet data structure.\r
1689 @param Form Form data structure.\r
1690\r
1691 @retval EFI_SUCCESS The function completed successfully.\r
1692\r
1693**/\r
1694EFI_STATUS\r
1695SubmitForm (\r
1696 IN FORM_BROWSER_FORMSET *FormSet,\r
1697 IN FORM_BROWSER_FORM *Form\r
1698 )\r
1699{\r
1700 EFI_STATUS Status;\r
1701 LIST_ENTRY *Link;\r
1702 EFI_STRING ConfigResp;\r
1703 EFI_STRING Progress;\r
1704 FORMSET_STORAGE *Storage;\r
1705\r
1706 //\r
1707 // Validate the Form by NoSubmit check\r
1708 //\r
1709 Status = NoSubmitCheck (FormSet, Form);\r
1710 if (EFI_ERROR (Status)) {\r
1711 return Status;\r
1712 }\r
1713\r
1714 //\r
1715 // Submit Buffer storage or Name/Value storage\r
1716 //\r
1717 Link = GetFirstNode (&FormSet->StorageListHead);\r
1718 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
1719 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
1720 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
1721\r
1722 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1723 continue;\r
1724 }\r
1725\r
1726 //\r
1727 // Skip if there is no RequestElement\r
1728 //\r
1729 if (Storage->ElementCount == 0) {\r
1730 continue;\r
1731 }\r
1732\r
1733 //\r
1734 // Prepare <ConfigResp>\r
1735 //\r
1736 Status = StorageToConfigResp (Storage, &ConfigResp);\r
1737 if (EFI_ERROR (Status)) {\r
1738 return Status;\r
1739 }\r
1740\r
1741 //\r
1742 // Send <ConfigResp> to Configuration Driver\r
1743 //\r
1744 if (FormSet->ConfigAccess != NULL) {\r
1745 Status = FormSet->ConfigAccess->RouteConfig (\r
1746 FormSet->ConfigAccess,\r
1747 ConfigResp,\r
1748 &Progress\r
1749 );\r
1750 if (EFI_ERROR (Status)) {\r
f4113e1f 1751 FreePool (ConfigResp);\r
7936fb6a 1752 return Status;\r
1753 }\r
1754 }\r
f4113e1f 1755 FreePool (ConfigResp);\r
7936fb6a 1756\r
1757 //\r
1758 // Config success, update storage shadow Buffer\r
1759 //\r
1760 SynchronizeStorage (Storage);\r
1761 }\r
1762\r
1763 gNvUpdateRequired = FALSE;\r
1764\r
1765 return EFI_SUCCESS;\r
1766}\r
1767\r
1768\r
1769/**\r
1770 Reset Question to its default value.\r
1771\r
1772 @param FormSet The form set.\r
1773 @param Form The form.\r
1774 @param Question The question.\r
1775 @param DefaultId The Class of the default.\r
1776\r
1777 @retval EFI_SUCCESS Question is reset to default value.\r
1778\r
1779**/\r
1780EFI_STATUS\r
1781GetQuestionDefault (\r
1782 IN FORM_BROWSER_FORMSET *FormSet,\r
1783 IN FORM_BROWSER_FORM *Form,\r
1784 IN FORM_BROWSER_STATEMENT *Question,\r
1785 IN UINT16 DefaultId\r
1786 )\r
1787{\r
1788 EFI_STATUS Status;\r
1789 LIST_ENTRY *Link;\r
1790 QUESTION_DEFAULT *Default;\r
1791 QUESTION_OPTION *Option;\r
1792 EFI_HII_VALUE *HiiValue;\r
1793 UINT8 Index;\r
086cd2c8 1794 EFI_STRING StrValue;\r
7936fb6a 1795\r
086cd2c8
LG
1796 Status = EFI_SUCCESS;\r
1797 StrValue = NULL;\r
7936fb6a 1798\r
1799 //\r
1800 // Statement don't have storage, skip them\r
1801 //\r
1802 if (Question->QuestionId == 0) {\r
1803 return Status;\r
1804 }\r
1805\r
1806 //\r
1807 // There are three ways to specify default value for a Question:\r
1808 // 1, use nested EFI_IFR_DEFAULT (highest priority)\r
1809 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
1810 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
1811 //\r
1812 HiiValue = &Question->HiiValue;\r
1813\r
1814 //\r
1815 // EFI_IFR_DEFAULT has highest priority\r
1816 //\r
1817 if (!IsListEmpty (&Question->DefaultListHead)) {\r
1818 Link = GetFirstNode (&Question->DefaultListHead);\r
1819 while (!IsNull (&Question->DefaultListHead, Link)) {\r
1820 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
1821\r
1822 if (Default->DefaultId == DefaultId) {\r
1823 if (Default->ValueExpression != NULL) {\r
1824 //\r
1825 // Default is provided by an Expression, evaluate it\r
1826 //\r
1827 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
1828 if (EFI_ERROR (Status)) {\r
1829 return Status;\r
1830 }\r
1831\r
1832 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1833 } else {\r
1834 //\r
1835 // Default value is embedded in EFI_IFR_DEFAULT\r
1836 //\r
1837 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
1838 }\r
1839\r
086cd2c8
LG
1840 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
1841 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
1842 if (StrValue == NULL) {\r
1843 return EFI_NOT_FOUND;\r
1844 }\r
1845 Question->BufferValue = AllocateCopyPool (StrSize (StrValue), StrValue);\r
1846 }\r
1847\r
7936fb6a 1848 return EFI_SUCCESS;\r
1849 }\r
1850\r
1851 Link = GetNextNode (&Question->DefaultListHead, Link);\r
1852 }\r
1853 }\r
1854\r
1855 //\r
1856 // EFI_ONE_OF_OPTION\r
1857 //\r
1858 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
1859 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1860 //\r
1861 // OneOfOption could only provide Standard and Manufacturing default\r
1862 //\r
1863 Link = GetFirstNode (&Question->OptionListHead);\r
1864 while (!IsNull (&Question->OptionListHead, Link)) {\r
1865 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1866\r
1867 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
1868 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
1869 ) {\r
1870 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1871\r
1872 return EFI_SUCCESS;\r
1873 }\r
1874\r
1875 Link = GetNextNode (&Question->OptionListHead, Link);\r
1876 }\r
1877 }\r
1878 }\r
1879\r
1880 //\r
1881 // EFI_IFR_CHECKBOX - lowest priority\r
1882 //\r
1883 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
1884 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1885 //\r
1886 // Checkbox could only provide Standard and Manufacturing default\r
1887 //\r
1888 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
1889 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
1890 ) {\r
1891 HiiValue->Value.b = TRUE;\r
1892 } else {\r
1893 HiiValue->Value.b = FALSE;\r
1894 }\r
1895\r
1896 return EFI_SUCCESS;\r
1897 }\r
1898 }\r
1899\r
1900 //\r
1901 // For Questions without default\r
1902 //\r
1903 switch (Question->Operand) {\r
7936fb6a 1904 case EFI_IFR_ONE_OF_OP:\r
1905 //\r
1906 // Take first oneof option as oneof's default value\r
1907 //\r
d66e6c16 1908 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed
LG
1909 Link = GetFirstNode (&Question->OptionListHead);\r
1910 if (!IsNull (&Question->OptionListHead, Link)) {\r
1911 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1912 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1913 }\r
7936fb6a 1914 }\r
1915 break;\r
1916\r
1917 case EFI_IFR_ORDERED_LIST_OP:\r
1918 //\r
1919 // Take option sequence in IFR as ordered list's default value\r
1920 //\r
1921 Index = 0;\r
1922 Link = GetFirstNode (&Question->OptionListHead);\r
1923 while (!IsNull (&Question->OptionListHead, Link)) {\r
1924 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1925\r
d02847d3 1926 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 1927\r
1928 Index++;\r
1929 if (Index >= Question->MaxContainers) {\r
1930 break;\r
1931 }\r
1932\r
1933 Link = GetNextNode (&Question->OptionListHead, Link);\r
1934 }\r
1935 break;\r
1936\r
1937 default:\r
1938 Status = EFI_NOT_FOUND;\r
1939 break;\r
1940 }\r
1941\r
1942 return Status;\r
1943}\r
1944\r
1945\r
1946/**\r
1947 Reset Questions in a Form to their default value.\r
1948\r
1949 @param FormSet FormSet data structure.\r
1950 @param Form The Form which to be reset.\r
1951 @param DefaultId The Class of the default.\r
1952\r
1953 @retval EFI_SUCCESS The function completed successfully.\r
1954\r
1955**/\r
1956EFI_STATUS\r
1957ExtractFormDefault (\r
1958 IN FORM_BROWSER_FORMSET *FormSet,\r
1959 IN FORM_BROWSER_FORM *Form,\r
1960 IN UINT16 DefaultId\r
1961 )\r
1962{\r
1963 EFI_STATUS Status;\r
1964 LIST_ENTRY *Link;\r
1965 FORM_BROWSER_STATEMENT *Question;\r
1966\r
1967 Link = GetFirstNode (&Form->StatementListHead);\r
1968 while (!IsNull (&Form->StatementListHead, Link)) {\r
1969 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1970 Link = GetNextNode (&Form->StatementListHead, Link);\r
1971\r
8d00a0f1 1972 //\r
0a1147ed 1973 // If Question is disabled, don't reset it to default\r
8d00a0f1 1974 //\r
0a1147ed
LG
1975 if (Question->DisableExpression != NULL) {\r
1976 Status = EvaluateExpression (FormSet, Form, Question->DisableExpression);\r
1977 if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b) {\r
8d00a0f1 1978 continue;\r
1979 }\r
1980 }\r
1981\r
7936fb6a 1982 //\r
1983 // Reset Question to its default value\r
1984 //\r
1985 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
1986 if (EFI_ERROR (Status)) {\r
1987 continue;\r
1988 }\r
1989\r
1990 //\r
1991 // Synchronize Buffer storage's Edit buffer\r
1992 //\r
1993 if ((Question->Storage != NULL) &&\r
1994 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
1995 SetQuestionValue (FormSet, Form, Question, TRUE);\r
1996 }\r
1997 }\r
1998\r
1999 return EFI_SUCCESS;\r
2000}\r
2001\r
2002\r
2003/**\r
2004 Initialize Question's Edit copy from Storage.\r
2005\r
2006 @param FormSet FormSet data structure.\r
2007 @param Form Form data structure.\r
2008\r
2009 @retval EFI_SUCCESS The function completed successfully.\r
2010\r
2011**/\r
2012EFI_STATUS\r
2013LoadFormConfig (\r
2014 IN FORM_BROWSER_FORMSET *FormSet,\r
2015 IN FORM_BROWSER_FORM *Form\r
2016 )\r
2017{\r
2018 EFI_STATUS Status;\r
2019 LIST_ENTRY *Link;\r
2020 FORM_BROWSER_STATEMENT *Question;\r
2021\r
2022 Link = GetFirstNode (&Form->StatementListHead);\r
2023 while (!IsNull (&Form->StatementListHead, Link)) {\r
2024 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2025\r
2026 //\r
2027 // Initialize local copy of Value for each Question\r
2028 //\r
2029 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
2030 if (EFI_ERROR (Status)) {\r
2031 return Status;\r
2032 }\r
2033\r
2034 Link = GetNextNode (&Form->StatementListHead, Link);\r
2035 }\r
2036\r
2037 return EFI_SUCCESS;\r
2038}\r
2039\r
2040\r
d66e6c16 2041/**\r
2042 Initialize Question's Edit copy from Storage for the whole Formset.\r
2043\r
2044 @param FormSet FormSet data structure.\r
2045\r
2046 @retval EFI_SUCCESS The function completed successfully.\r
2047\r
2048**/\r
2049EFI_STATUS\r
2050LoadFormSetConfig (\r
2051 IN FORM_BROWSER_FORMSET *FormSet\r
2052 )\r
2053{\r
2054 EFI_STATUS Status;\r
2055 LIST_ENTRY *Link;\r
2056 FORM_BROWSER_FORM *Form;\r
2057\r
2058 Link = GetFirstNode (&FormSet->FormListHead);\r
2059 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2060 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2061\r
2062 //\r
2063 // Initialize local copy of Value for each Form\r
2064 //\r
2065 Status = LoadFormConfig (FormSet, Form);\r
2066 if (EFI_ERROR (Status)) {\r
2067 return Status;\r
2068 }\r
2069\r
2070 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2071 }\r
2072\r
2073 return EFI_SUCCESS;\r
2074}\r
2075\r
2076\r
7936fb6a 2077/**\r
2078 Fill storage's edit copy with settings requested from Configuration Driver.\r
2079\r
2080 @param FormSet FormSet data structure.\r
2081 @param Storage Buffer Storage.\r
2082\r
2083 @retval EFI_SUCCESS The function completed successfully.\r
2084\r
2085**/\r
2086EFI_STATUS\r
2087LoadStorage (\r
2088 IN FORM_BROWSER_FORMSET *FormSet,\r
2089 IN FORMSET_STORAGE *Storage\r
2090 )\r
2091{\r
2092 EFI_STATUS Status;\r
2093 EFI_STRING Progress;\r
2094 EFI_STRING Result;\r
2095 CHAR16 *StrPtr;\r
2096\r
2097 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2098 return EFI_SUCCESS;\r
2099 }\r
2100\r
2101 if (FormSet->ConfigAccess == NULL) {\r
2102 return EFI_NOT_FOUND;\r
2103 }\r
2104\r
2105 if (Storage->ElementCount == 0) {\r
2106 //\r
2107 // Skip if there is no RequestElement\r
2108 //\r
2109 return EFI_SUCCESS;\r
2110 }\r
2111\r
2112 //\r
2113 // Request current settings from Configuration Driver\r
2114 //\r
2115 Status = FormSet->ConfigAccess->ExtractConfig (\r
2116 FormSet->ConfigAccess,\r
2117 Storage->ConfigRequest,\r
2118 &Progress,\r
2119 &Result\r
2120 );\r
2121 if (EFI_ERROR (Status)) {\r
2122 return Status;\r
2123 }\r
2124\r
2125 //\r
2126 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
2127 //\r
2128 StrPtr = StrStr (Result, L"ALTCFG");\r
2129 if (StrPtr != NULL) {\r
2130 *StrPtr = L'\0';\r
2131 }\r
2132\r
2133 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 2134 FreePool (Result);\r
7936fb6a 2135 return Status;\r
2136}\r
2137\r
2138\r
d66e6c16 2139/**\r
2140 Copy uncommitted data from source Storage to destination Storage.\r
2141\r
2142 @param Dst Target Storage for uncommitted data.\r
2143 @param Src Source Storage for uncommitted data.\r
2144\r
2145 @retval EFI_SUCCESS The function completed successfully.\r
2146 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
2147\r
2148**/\r
2149EFI_STATUS\r
2150CopyStorage (\r
2151 IN OUT FORMSET_STORAGE *Dst,\r
2152 IN FORMSET_STORAGE *Src\r
2153 )\r
2154{\r
2155 LIST_ENTRY *Link;\r
2156 NAME_VALUE_NODE *Node;\r
2157\r
2158 if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
2159 return EFI_INVALID_PARAMETER;\r
2160 }\r
2161\r
2162 switch (Src->Type) {\r
2163 case EFI_HII_VARSTORE_BUFFER:\r
2164 CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
2165 break;\r
2166\r
2167 case EFI_HII_VARSTORE_NAME_VALUE:\r
2168 Link = GetFirstNode (&Src->NameValueListHead);\r
2169 while (!IsNull (&Src->NameValueListHead, Link)) {\r
2170 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2171\r
2172 SetValueByName (Dst, Node->Name, Node->EditValue);\r
2173\r
2174 Link = GetNextNode (&Src->NameValueListHead, Link);\r
2175 }\r
2176 break;\r
2177\r
2178 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2179 default:\r
2180 break;\r
2181 }\r
2182\r
2183 return EFI_SUCCESS;\r
2184}\r
2185\r
2186\r
7936fb6a 2187/**\r
2188 Get current setting of Questions.\r
2189\r
2190 @param FormSet FormSet data structure.\r
2191\r
2192 @retval EFI_SUCCESS The function completed successfully.\r
2193\r
2194**/\r
2195EFI_STATUS\r
2196InitializeCurrentSetting (\r
2197 IN OUT FORM_BROWSER_FORMSET *FormSet\r
2198 )\r
2199{\r
2200 LIST_ENTRY *Link;\r
d66e6c16 2201 LIST_ENTRY *Link2;\r
7936fb6a 2202 FORMSET_STORAGE *Storage;\r
d66e6c16 2203 FORMSET_STORAGE *StorageSrc;\r
2204 FORMSET_STORAGE *OldStorage;\r
7936fb6a 2205 FORM_BROWSER_FORM *Form;\r
2206 EFI_STATUS Status;\r
2207\r
2208 //\r
2209 // Extract default from IFR binary\r
2210 //\r
2211 Link = GetFirstNode (&FormSet->FormListHead);\r
2212 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2213 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2214\r
2215 Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
2216\r
2217 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2218 }\r
2219\r
2220 //\r
2221 // Request current settings from Configuration Driver\r
2222 //\r
2223 Link = GetFirstNode (&FormSet->StorageListHead);\r
2224 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2225 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2226\r
d66e6c16 2227 OldStorage = NULL;\r
2228 if (gOldFormSet != NULL) {\r
2229 //\r
2230 // Try to find the Storage in backup formset gOldFormSet\r
2231 //\r
2232 Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
2233 while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
2234 StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
2235\r
2236 if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
2237 OldStorage = StorageSrc;\r
2238 break;\r
2239 }\r
2240\r
2241 Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
2242 }\r
2243 }\r
2244\r
2245 if (OldStorage == NULL) {\r
2246 //\r
2247 // Storage is not found in backup formset, request it from ConfigDriver\r
2248 //\r
2249 Status = LoadStorage (FormSet, Storage);\r
2250 } else {\r
2251 //\r
2252 // Storage found in backup formset, use it\r
2253 //\r
2254 Status = CopyStorage (Storage, OldStorage);\r
2255 }\r
7936fb6a 2256\r
2257 //\r
2258 // Now Edit Buffer is filled with default values(lower priority) and current\r
2259 // settings(higher priority), sychronize it to shadow Buffer\r
2260 //\r
2261 if (!EFI_ERROR (Status)) {\r
2262 SynchronizeStorage (Storage);\r
2263 }\r
2264\r
2265 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2266 }\r
2267\r
2268 return EFI_SUCCESS;\r
2269}\r
2270\r
2271\r
2272/**\r
2273 Fetch the Ifr binary data of a FormSet.\r
2274\r
2275 @param Handle PackageList Handle\r
2276 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2277 GUID), take the first FormSet found in package\r
2278 list.\r
2279 @param BinaryLength The length of the FormSet IFR binary.\r
2280 @param BinaryData The buffer designed to receive the FormSet.\r
2281\r
2282 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
2283 BufferLength was updated.\r
2284 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
2285 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
2286 be found with the requested FormId.\r
2287\r
2288**/\r
2289EFI_STATUS\r
2290GetIfrBinaryData (\r
2291 IN EFI_HII_HANDLE Handle,\r
2292 IN OUT EFI_GUID *FormSetGuid,\r
2293 OUT UINTN *BinaryLength,\r
2294 OUT UINT8 **BinaryData\r
2295 )\r
2296{\r
2297 EFI_STATUS Status;\r
2298 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2299 UINTN BufferSize;\r
2300 UINT8 *Package;\r
2301 UINT8 *OpCodeData;\r
2302 UINT32 Offset;\r
2303 UINT32 Offset2;\r
2304 BOOLEAN ReturnDefault;\r
2305 UINT32 PackageListLength;\r
2306 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
2307 UINT8 Index;\r
2308 UINT8 NumberOfClassGuid;\r
2309 BOOLEAN IsSetupClassGuid;\r
2310 EFI_GUID *ClassGuid;\r
7936fb6a 2311\r
2312 OpCodeData = NULL;\r
2313 Package = NULL;\r
2314 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
2315\r
2316 //\r
2317 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
2318 //\r
2319 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
2320 ReturnDefault = TRUE;\r
2321 } else {\r
2322 ReturnDefault = FALSE;\r
2323 }\r
2324\r
2325 //\r
2326 // Get HII PackageList\r
2327 //\r
2328 BufferSize = 0;\r
2329 HiiPackageList = NULL;\r
2330 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2331 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2332 HiiPackageList = AllocatePool (BufferSize);\r
2333 ASSERT (HiiPackageList != NULL);\r
2334\r
2335 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2336 }\r
2337 if (EFI_ERROR (Status)) {\r
2338 return Status;\r
2339 }\r
db0bd81c 2340 ASSERT (HiiPackageList != NULL);\r
d66e6c16 2341\r
7936fb6a 2342 //\r
2343 // Get Form package from this HII package List\r
2344 //\r
2345 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2346 Offset2 = 0;\r
2347 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
2348\r
2349 while (Offset < PackageListLength) {\r
2350 Package = ((UINT8 *) HiiPackageList) + Offset;\r
2351 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2352\r
8d00a0f1 2353 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 2354 //\r
2355 // Search FormSet in this Form Package\r
2356 //\r
2357 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
2358 while (Offset2 < PackageHeader.Length) {\r
2359 OpCodeData = Package + Offset2;\r
2360\r
2361 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
2362 //\r
2363 // Check whether return default FormSet\r
2364 //\r
2365 if (ReturnDefault) {\r
0a1147ed
LG
2366 //\r
2367 // Check ClassGuid of formset OpCode\r
2368 //\r
2369 IsSetupClassGuid = FALSE;\r
7da73676 2370 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
0a1147ed
LG
2371 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
2372 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
2373 if (CompareGuid (ClassGuid + Index, &gEfiHiiPlatformSetupFormsetGuid)) {\r
2374 IsSetupClassGuid = TRUE;\r
2375 break;\r
2376 }\r
2377 }\r
2378 if (IsSetupClassGuid) {\r
2379 break;\r
2380 }\r
7936fb6a 2381 }\r
2382\r
2383 //\r
2384 // FormSet GUID is specified, check it\r
2385 //\r
2386 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
2387 break;\r
2388 }\r
2389 }\r
2390\r
2391 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
2392 }\r
2393\r
2394 if (Offset2 < PackageHeader.Length) {\r
2395 //\r
2396 // Target formset found\r
2397 //\r
2398 break;\r
2399 }\r
2400 }\r
2401\r
2402 Offset += PackageHeader.Length;\r
2403 }\r
2404\r
2405 if (Offset >= PackageListLength) {\r
2406 //\r
2407 // Form package not found in this Package List\r
2408 //\r
f4113e1f 2409 FreePool (HiiPackageList);\r
7936fb6a 2410 return EFI_NOT_FOUND;\r
2411 }\r
2412\r
2413 if (ReturnDefault && FormSetGuid != NULL) {\r
2414 //\r
2415 // Return the default FormSet GUID\r
2416 //\r
2417 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
2418 }\r
2419\r
2420 //\r
2421 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
2422 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
2423 // of the Form Package.\r
2424 //\r
2425 *BinaryLength = PackageHeader.Length - Offset2;\r
2426 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
2427\r
f4113e1f 2428 FreePool (HiiPackageList);\r
7936fb6a 2429\r
2430 if (*BinaryData == NULL) {\r
2431 return EFI_OUT_OF_RESOURCES;\r
2432 }\r
2433\r
2434 return EFI_SUCCESS;\r
2435}\r
2436\r
2437\r
2438/**\r
2439 Initialize the internal data structure of a FormSet.\r
2440\r
2441 @param Handle PackageList Handle\r
2442 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2443 GUID), take the first FormSet found in package\r
2444 list.\r
2445 @param FormSet FormSet data structure.\r
2446\r
2447 @retval EFI_SUCCESS The function completed successfully.\r
2448 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
2449\r
2450**/\r
2451EFI_STATUS\r
2452InitializeFormSet (\r
2453 IN EFI_HII_HANDLE Handle,\r
2454 IN OUT EFI_GUID *FormSetGuid,\r
2455 OUT FORM_BROWSER_FORMSET *FormSet\r
2456 )\r
2457{\r
2458 EFI_STATUS Status;\r
2459 EFI_HANDLE DriverHandle;\r
2460 UINT16 Index;\r
2461\r
2462 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
2463 if (EFI_ERROR (Status)) {\r
2464 return Status;\r
2465 }\r
2466\r
2467 FormSet->HiiHandle = Handle;\r
2468 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
2469\r
2470 //\r
2471 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
2472 //\r
2473 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
2474 if (EFI_ERROR (Status)) {\r
2475 return Status;\r
2476 }\r
2477 FormSet->DriverHandle = DriverHandle;\r
2478 Status = gBS->HandleProtocol (\r
2479 DriverHandle,\r
2480 &gEfiHiiConfigAccessProtocolGuid,\r
2481 (VOID **) &FormSet->ConfigAccess\r
2482 );\r
2483 if (EFI_ERROR (Status)) {\r
2484 //\r
2485 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
2486 // list, then there will be no configuration action required\r
2487 //\r
2488 FormSet->ConfigAccess = NULL;\r
2489 }\r
2490\r
2491 //\r
2492 // Parse the IFR binary OpCodes\r
2493 //\r
2494 Status = ParseOpCodes (FormSet);\r
2495 if (EFI_ERROR (Status)) {\r
2496 return Status;\r
2497 }\r
2498\r
0a1147ed
LG
2499 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
2500 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
2501 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
2502 gFrontPageHandle = FormSet->HiiHandle;\r
7936fb6a 2503 }\r
2504\r
2505 //\r
2506 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
2507 //\r
2508 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
2509 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
2510 //\r
2511 // Update the function key setting.\r
2512 //\r
2513 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
2514 //\r
2515 // Function key prompt can not be displayed if the function key has been disabled.\r
2516 //\r
7936fb6a 2517 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
2518 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2519 }\r
2520\r
2521 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
2522 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2523 }\r
2524 }\r
2525 }\r
2526\r
2527 return Status;\r
2528}\r
ce6d12cc 2529\r
2530\r
2531/**\r
2532 Save globals used by previous call to SendForm(). SendForm() may be called from \r
2533 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
2534 So, save globals of previous call to SendForm() and restore them upon exit.\r
2535\r
2536**/\r
2537VOID\r
2538SaveBrowserContext (\r
2539 VOID\r
2540 )\r
2541{\r
2542 BROWSER_CONTEXT *Context;\r
2543\r
2544 gBrowserContextCount++;\r
2545 if (gBrowserContextCount == 1) {\r
2546 //\r
2547 // This is not reentry of SendForm(), no context to save\r
2548 //\r
2549 return;\r
2550 }\r
2551\r
2552 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
2553 ASSERT (Context != NULL);\r
2554\r
2555 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
2556\r
2557 //\r
2558 // Save FormBrowser context\r
2559 //\r
2560 Context->BannerData = gBannerData;\r
2561 Context->ClassOfVfr = gClassOfVfr;\r
2562 Context->FunctionKeySetting = gFunctionKeySetting;\r
2563 Context->ResetRequired = gResetRequired;\r
2564 Context->NvUpdateRequired = gNvUpdateRequired;\r
2565 Context->Direction = gDirection;\r
2566 Context->FunctionNineString = gFunctionNineString;\r
2567 Context->FunctionTenString = gFunctionTenString;\r
2568 Context->EnterString = gEnterString;\r
2569 Context->EnterCommitString = gEnterCommitString;\r
2570 Context->EnterEscapeString = gEnterEscapeString;\r
2571 Context->EscapeString = gEscapeString;\r
2572 Context->SaveFailed = gSaveFailed;\r
2573 Context->MoveHighlight = gMoveHighlight;\r
2574 Context->MakeSelection = gMakeSelection;\r
2575 Context->DecNumericInput = gDecNumericInput;\r
2576 Context->HexNumericInput = gHexNumericInput;\r
2577 Context->ToggleCheckBox = gToggleCheckBox;\r
2578 Context->PromptForData = gPromptForData;\r
2579 Context->PromptForPassword = gPromptForPassword;\r
2580 Context->PromptForNewPassword = gPromptForNewPassword;\r
2581 Context->ConfirmPassword = gConfirmPassword;\r
2582 Context->ConfirmError = gConfirmError;\r
2583 Context->PassowordInvalid = gPassowordInvalid;\r
2584 Context->PressEnter = gPressEnter;\r
2585 Context->EmptyString = gEmptyString;\r
2586 Context->AreYouSure = gAreYouSure;\r
2587 Context->YesResponse = gYesResponse;\r
2588 Context->NoResponse = gNoResponse;\r
2589 Context->MiniString = gMiniString;\r
2590 Context->PlusString = gPlusString;\r
2591 Context->MinusString = gMinusString;\r
2592 Context->AdjustNumber = gAdjustNumber;\r
2593 Context->SaveChanges = gSaveChanges;\r
2594 Context->OptionMismatch = gOptionMismatch;\r
2595 Context->PromptBlockWidth = gPromptBlockWidth;\r
2596 Context->OptionBlockWidth = gOptionBlockWidth;\r
2597 Context->HelpBlockWidth = gHelpBlockWidth;\r
2598 Context->OldFormSet = gOldFormSet;\r
2599 Context->MenuRefreshHead = gMenuRefreshHead;\r
2600\r
2601 CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
2602 CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
2603\r
2604 //\r
2605 // Insert to FormBrowser context list\r
2606 //\r
2607 InsertHeadList (&gBrowserContextList, &Context->Link);\r
2608}\r
2609\r
2610\r
2611/**\r
2612 Restore globals used by previous call to SendForm().\r
2613\r
2614**/\r
2615VOID\r
2616RestoreBrowserContext (\r
2617 VOID\r
2618 )\r
2619{\r
2620 LIST_ENTRY *Link;\r
2621 BROWSER_CONTEXT *Context;\r
2622\r
2623 ASSERT (gBrowserContextCount != 0);\r
2624 gBrowserContextCount--;\r
2625 if (gBrowserContextCount == 0) {\r
2626 //\r
2627 // This is not reentry of SendForm(), no context to restore\r
2628 //\r
2629 return;\r
2630 }\r
2631\r
2632 ASSERT (!IsListEmpty (&gBrowserContextList));\r
2633\r
2634 Link = GetFirstNode (&gBrowserContextList);\r
2635 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
2636\r
2637 //\r
2638 // Restore FormBrowser context\r
2639 //\r
2640 gBannerData = Context->BannerData;\r
2641 gClassOfVfr = Context->ClassOfVfr;\r
2642 gFunctionKeySetting = Context->FunctionKeySetting;\r
2643 gResetRequired = Context->ResetRequired;\r
2644 gNvUpdateRequired = Context->NvUpdateRequired;\r
2645 gDirection = Context->Direction;\r
2646 gFunctionNineString = Context->FunctionNineString;\r
2647 gFunctionTenString = Context->FunctionTenString;\r
2648 gEnterString = Context->EnterString;\r
2649 gEnterCommitString = Context->EnterCommitString;\r
2650 gEnterEscapeString = Context->EnterEscapeString;\r
2651 gEscapeString = Context->EscapeString;\r
2652 gSaveFailed = Context->SaveFailed;\r
2653 gMoveHighlight = Context->MoveHighlight;\r
2654 gMakeSelection = Context->MakeSelection;\r
2655 gDecNumericInput = Context->DecNumericInput;\r
2656 gHexNumericInput = Context->HexNumericInput;\r
2657 gToggleCheckBox = Context->ToggleCheckBox;\r
2658 gPromptForData = Context->PromptForData;\r
2659 gPromptForPassword = Context->PromptForPassword;\r
2660 gPromptForNewPassword = Context->PromptForNewPassword;\r
2661 gConfirmPassword = Context->ConfirmPassword;\r
2662 gConfirmError = Context->ConfirmError;\r
2663 gPassowordInvalid = Context->PassowordInvalid;\r
2664 gPressEnter = Context->PressEnter;\r
2665 gEmptyString = Context->EmptyString;\r
2666 gAreYouSure = Context->AreYouSure;\r
2667 gYesResponse = Context->YesResponse;\r
2668 gNoResponse = Context->NoResponse;\r
2669 gMiniString = Context->MiniString;\r
2670 gPlusString = Context->PlusString;\r
2671 gMinusString = Context->MinusString;\r
2672 gAdjustNumber = Context->AdjustNumber;\r
2673 gSaveChanges = Context->SaveChanges;\r
2674 gOptionMismatch = Context->OptionMismatch;\r
2675 gPromptBlockWidth = Context->PromptBlockWidth;\r
2676 gOptionBlockWidth = Context->OptionBlockWidth;\r
2677 gHelpBlockWidth = Context->HelpBlockWidth;\r
2678 gOldFormSet = Context->OldFormSet;\r
2679 gMenuRefreshHead = Context->MenuRefreshHead;\r
2680\r
2681 CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
2682 CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
2683\r
2684 //\r
2685 // Remove from FormBrowser context list\r
2686 //\r
2687 RemoveEntryList (&Context->Link);\r
2688 gBS->FreePool (Context);\r
2689}\r