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