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