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