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