]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
1) Add BufToHexString, HexStringToBuf and IsHexDigit to BaseLib.
[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 {
106 0x94,
107 0x49,
108 0x5a,
109 0xd5,
110 0x41,
111 0x2e,
112 0x99,
113 0x3b
114 }
115 },
116 NONE_FUNCTION_KEY_SETTING
117 },
118 //
119 // Device Manager
120 //
121 {
122 {
123 0x3ebfa8e6,
124 0x511d,
125 0x4b5b,
126 {
127 0xa9,
128 0x5f,
129 0xfb,
130 0x38,
131 0x26,
132 0xf,
133 0x1c,
134 0x27
135 }
136 },
137 NONE_FUNCTION_KEY_SETTING
138 },
139 //
140 // BMM FormSet.
141 //
142 {
143 {
144 0x642237c7,
145 0x35d4,
146 0x472d,
147 {
148 0x83,
149 0x65,
150 0x12,
151 0xe0,
152 0xcc,
153 0xf2,
154 0x7a,
155 0x22
156 }
157 },
158 NONE_FUNCTION_KEY_SETTING
159 },
160 //
161 // BMM File Explorer FormSet.
162 //
163 {
164 {
165 0x1f2d63e1,
166 0xfebd,
167 0x4dc7,
168 {
169 0x9c,
170 0xc5,
171 0xba,
172 0x2b,
173 0x1c,
174 0xef,
175 0x9c,
176 0x5b
177 }
178 },
179 NONE_FUNCTION_KEY_SETTING
180 },
181 };
182
183 EFI_STATUS
184 EFIAPI
185 SendForm (
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
196 Routine Description:
197 This is the routine which an external caller uses to direct the browser
198 where to obtain it's information.
199
200 Arguments:
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
216 Returns:
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 **/
388 EFI_STATUS
389 EFIAPI
390 BrowserCallback (
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 **/
534 EFI_STATUS
535 EFIAPI
536 InitializeSetup (
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
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
575 PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
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 **/
628 EFI_STRING_ID
629 NewString (
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;
638 Status = HiiLibNewString (HiiHandle, &StringId, String);
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 **/
654 EFI_STATUS
655 DeleteString (
656 IN EFI_STRING_ID StringId,
657 IN EFI_HII_HANDLE HiiHandle
658 )
659 {
660 CHAR16 NullChar;
661
662 NullChar = CHAR_NULL;
663 return HiiLibSetString (HiiHandle, StringId, &NullChar);
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 **/
677 CHAR16 *
678 GetToken (
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
694 Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
695
696 if (Status == EFI_BUFFER_TOO_SMALL) {
697 gBS->FreePool (String);
698 String = AllocateZeroPool (BufferLength);
699 ASSERT (String != NULL);
700
701 Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
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 **/
718 VOID
719 NewStringCpy (
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 **/
739 VOID
740 NewStringCat (
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 **/
773 VOID
774 SynchronizeStorage (
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 **/
815 EFI_STATUS
816 GetValueByName (
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 **/
854 EFI_STATUS
855 SetValueByName (
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 **/
892 EFI_STATUS
893 StorageToConfigResp (
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 **/
954 EFI_STATUS
955 ConfigRespToStorage (
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 **/
1030 EFI_STATUS
1031 GetQuestionValue (
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 {
1178 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
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 {
1244 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
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 **/
1278 EFI_STATUS
1279 SetQuestionValue (
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);
1417 BufToHexString (Value, &BufferLen, Src, StorageWidth);
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);
1457 BufToHexString (Value, &BufferLen, Src, StorageWidth);
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 **/
1498 EFI_STATUS
1499 ValidateQuestion (
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 **/
1565 EFI_STATUS
1566 NoSubmitCheck (
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 **/
1600 EFI_STATUS
1601 SubmitForm (
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 **/
1684 EFI_STATUS
1685 GetQuestionDefault (
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 **/
1855 EFI_STATUS
1856 ExtractFormDefault (
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 **/
1901 EFI_STATUS
1902 LoadFormConfig (
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 **/
1939 EFI_STATUS
1940 LoadStorage (
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 **/
2000 EFI_STATUS
2001 InitializeCurrentSetting (
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 **/
2063 EFI_STATUS
2064 GetIfrBinaryData (
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 **/
2206 EFI_STATUS
2207 InitializeFormSet (
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 }