]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Merged in the following trackers from EDK:
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
1 /** @file
2 Copyright (c) 2007 - 2008, 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 //
1177 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1178 //
1179 Length = StorageWidth + sizeof (CHAR16);
1180 Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
1181 } else {
1182 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
1183 }
1184
1185 gBS->FreePool (Value);
1186 }
1187 } else {
1188 //
1189 // Request current settings from Configuration Driver
1190 //
1191 if (FormSet->ConfigAccess == NULL) {
1192 return EFI_NOT_FOUND;
1193 }
1194
1195 //
1196 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1197 // <ConfigHdr> + "&" + <VariableName>
1198 //
1199 if (IsBufferStorage) {
1200 Length = StrLen (Storage->ConfigHdr);
1201 Length += StrLen (Question->BlockName);
1202 } else {
1203 Length = StrLen (Storage->ConfigHdr);
1204 Length += StrLen (Question->VariableName) + 1;
1205 }
1206 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
1207 ASSERT (ConfigRequest != NULL);
1208
1209 StrCpy (ConfigRequest, Storage->ConfigHdr);
1210 if (IsBufferStorage) {
1211 StrCat (ConfigRequest, Question->BlockName);
1212 } else {
1213 StrCat (ConfigRequest, L"&");
1214 StrCat (ConfigRequest, Question->VariableName);
1215 }
1216
1217 Status = FormSet->ConfigAccess->ExtractConfig (
1218 FormSet->ConfigAccess,
1219 ConfigRequest,
1220 &Progress,
1221 &Result
1222 );
1223 if (EFI_ERROR (Status)) {
1224 return Status;
1225 }
1226
1227 //
1228 // Skip <ConfigRequest>
1229 //
1230 Value = Result + Length;
1231 if (IsBufferStorage) {
1232 //
1233 // Skip "&VALUE"
1234 //
1235 Value = Value + 6;
1236 }
1237 if (*Value != '=') {
1238 gBS->FreePool (Result);
1239 return EFI_NOT_FOUND;
1240 }
1241 //
1242 // Skip '=', point to value
1243 //
1244 Value = Value + 1;
1245 if (!IsBufferStorage && IsString) {
1246 //
1247 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1248 //
1249 Length = StorageWidth + sizeof (CHAR16);
1250 Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
1251 } else {
1252 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
1253 if (EFI_ERROR (Status)) {
1254 gBS->FreePool (Result);
1255 return Status;
1256 }
1257 }
1258
1259 //
1260 // Synchronize Edit Buffer
1261 //
1262 if (IsBufferStorage) {
1263 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
1264 } else {
1265 SetValueByName (Storage, Question->VariableName, Value);
1266 }
1267 gBS->FreePool (Result);
1268 }
1269
1270 return Status;
1271 }
1272
1273
1274 /**
1275 Save Question Value to edit copy(cached) or Storage(uncached).
1276
1277 @param FormSet FormSet data structure.
1278 @param Form Form data structure.
1279 @param Question Pointer to the Question.
1280 @param Cached TRUE: set to Edit copy FALSE: set to original
1281 Storage
1282
1283 @retval EFI_SUCCESS The function completed successfully.
1284
1285 **/
1286 EFI_STATUS
1287 SetQuestionValue (
1288 IN FORM_BROWSER_FORMSET *FormSet,
1289 IN FORM_BROWSER_FORM *Form,
1290 IN OUT FORM_BROWSER_STATEMENT *Question,
1291 IN BOOLEAN Cached
1292 )
1293 {
1294 EFI_STATUS Status;
1295 BOOLEAN Enabled;
1296 BOOLEAN Pending;
1297 UINT8 *Src;
1298 EFI_TIME EfiTime;
1299 UINTN BufferLen;
1300 UINTN StorageWidth;
1301 FORMSET_STORAGE *Storage;
1302 EFI_IFR_TYPE_VALUE *QuestionValue;
1303 CHAR16 *ConfigResp;
1304 CHAR16 *Progress;
1305 CHAR16 *Value;
1306 UINTN Length;
1307 BOOLEAN IsBufferStorage;
1308 BOOLEAN IsString;
1309
1310 Status = EFI_SUCCESS;
1311
1312 //
1313 // Statement don't have storage, skip them
1314 //
1315 if (Question->QuestionId == 0) {
1316 return Status;
1317 }
1318
1319 //
1320 // If Question value is provided by an Expression, then it is read only
1321 //
1322 if (Question->ValueExpression != NULL) {
1323 return Status;
1324 }
1325
1326 //
1327 // Question value is provided by RTC
1328 //
1329 Storage = Question->Storage;
1330 QuestionValue = &Question->HiiValue.Value;
1331 if (Storage == NULL) {
1332 //
1333 // It's a Question without storage, or RTC date/time
1334 //
1335 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
1336 //
1337 // Date and time define the same Flags bit
1338 //
1339 switch (Question->Flags & EFI_QF_DATE_STORAGE) {
1340 case QF_DATE_STORAGE_TIME:
1341 Status = gRT->GetTime (&EfiTime, NULL);
1342 break;
1343
1344 case QF_DATE_STORAGE_WAKEUP:
1345 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
1346 break;
1347
1348 case QF_DATE_STORAGE_NORMAL:
1349 default:
1350 //
1351 // For date/time without storage
1352 //
1353 return EFI_SUCCESS;
1354 }
1355
1356 if (EFI_ERROR (Status)) {
1357 return Status;
1358 }
1359
1360 if (Question->Operand == EFI_IFR_DATE_OP) {
1361 EfiTime.Year = QuestionValue->date.Year;
1362 EfiTime.Month = QuestionValue->date.Month;
1363 EfiTime.Day = QuestionValue->date.Day;
1364 } else {
1365 EfiTime.Hour = QuestionValue->time.Hour;
1366 EfiTime.Minute = QuestionValue->time.Minute;
1367 EfiTime.Second = QuestionValue->time.Second;
1368 }
1369
1370 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
1371 Status = gRT->SetTime (&EfiTime);
1372 } else {
1373 Status = gRT->SetWakeupTime (TRUE, &EfiTime);
1374 }
1375 }
1376
1377 return Status;
1378 }
1379
1380 //
1381 // Question value is provided by EFI variable
1382 //
1383 StorageWidth = Question->StorageWidth;
1384 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
1385 if (Question->BufferValue != NULL) {
1386 Src = Question->BufferValue;
1387 } else {
1388 Src = (UINT8 *) QuestionValue;
1389 }
1390
1391 Status = gRT->SetVariable (
1392 Question->VariableName,
1393 &Storage->Guid,
1394 Storage->Attributes,
1395 StorageWidth,
1396 Src
1397 );
1398 return Status;
1399 }
1400
1401 //
1402 // Question Value is provided by Buffer Storage or NameValue Storage
1403 //
1404 if (Question->BufferValue != NULL) {
1405 Src = Question->BufferValue;
1406 } else {
1407 Src = (UINT8 *) &Question->HiiValue.Value;
1408 }
1409
1410 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
1411 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
1412 if (IsBufferStorage) {
1413 //
1414 // Copy to storage edit buffer
1415 //
1416 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
1417 } else {
1418 if (IsString) {
1419 //
1420 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1421 //
1422 Value = NULL;
1423 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
1424 Value = AllocateZeroPool (BufferLen);
1425 ASSERT (Value != NULL);
1426 Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
1427 ASSERT_EFI_ERROR (Status);
1428 } else {
1429 BufferLen = StorageWidth * 2 + 1;
1430 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));
1431 ASSERT (Value != NULL);
1432 BufToHexString (Value, &BufferLen, Src, StorageWidth);
1433 ToLower (Value);
1434 }
1435
1436 Status = SetValueByName (Storage, Question->VariableName, Value);
1437 gBS->FreePool (Value);
1438 }
1439
1440 if (!Cached) {
1441 //
1442 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1443 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1444 //
1445 if (IsBufferStorage) {
1446 Length = StrLen (Question->BlockName) + 7;
1447 } else {
1448 Length = StrLen (Question->VariableName) + 2;
1449 }
1450 if (!IsBufferStorage && IsString) {
1451 Length += (StrLen ((CHAR16 *) Src) * 4);
1452 } else {
1453 Length += (StorageWidth * 2);
1454 }
1455 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
1456 ASSERT (ConfigResp != NULL);
1457
1458 StrCpy (ConfigResp, Storage->ConfigHdr);
1459 if (IsBufferStorage) {
1460 StrCat (ConfigResp, Question->BlockName);
1461 StrCat (ConfigResp, L"&VALUE=");
1462 } else {
1463 StrCat (ConfigResp, L"&");
1464 StrCat (ConfigResp, Question->VariableName);
1465 StrCat (ConfigResp, L"=");
1466 }
1467
1468 Value = ConfigResp + StrLen (ConfigResp);
1469 if (!IsBufferStorage && IsString) {
1470 //
1471 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1472 //
1473 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
1474 Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
1475 ASSERT_EFI_ERROR (Status);
1476 } else {
1477 BufferLen = StorageWidth * 2 + 1;
1478 BufToHexString (Value, &BufferLen, Src, StorageWidth);
1479 ToLower (Value);
1480 }
1481
1482 //
1483 // Submit Question Value to Configuration Driver
1484 //
1485 if (FormSet->ConfigAccess != NULL) {
1486 Status = FormSet->ConfigAccess->RouteConfig (
1487 FormSet->ConfigAccess,
1488 ConfigResp,
1489 &Progress
1490 );
1491 if (EFI_ERROR (Status)) {
1492 gBS->FreePool (ConfigResp);
1493 return Status;
1494 }
1495 }
1496 gBS->FreePool (ConfigResp);
1497
1498 //
1499 // Synchronize shadow Buffer
1500 //
1501 SynchronizeStorage (Storage);
1502 }
1503
1504 return Status;
1505 }
1506
1507
1508 /**
1509 Perform inconsistent check for a Form.
1510
1511 @param FormSet FormSet data structure.
1512 @param Form Form data structure.
1513 @param Question The Question to be validated.
1514 @param Type Validation type: InConsistent or NoSubmit
1515
1516 @retval EFI_SUCCESS Form validation pass.
1517 @retval other Form validation failed.
1518
1519 **/
1520 EFI_STATUS
1521 ValidateQuestion (
1522 IN FORM_BROWSER_FORMSET *FormSet,
1523 IN FORM_BROWSER_FORM *Form,
1524 IN FORM_BROWSER_STATEMENT *Question,
1525 IN UINTN Type
1526 )
1527 {
1528 EFI_STATUS Status;
1529 LIST_ENTRY *Link;
1530 LIST_ENTRY *ListHead;
1531 EFI_STRING PopUp;
1532 EFI_INPUT_KEY Key;
1533 FORM_EXPRESSION *Expression;
1534
1535 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
1536 ListHead = &Question->InconsistentListHead;
1537 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
1538 ListHead = &Question->NoSubmitListHead;
1539 } else {
1540 return EFI_UNSUPPORTED;
1541 }
1542
1543 Link = GetFirstNode (ListHead);
1544 while (!IsNull (ListHead, Link)) {
1545 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1546
1547 //
1548 // Evaluate the expression
1549 //
1550 Status = EvaluateExpression (FormSet, Form, Expression);
1551 if (EFI_ERROR (Status)) {
1552 return Status;
1553 }
1554
1555 if (Expression->Result.Value.b) {
1556 //
1557 // Condition meet, show up error message
1558 //
1559 if (Expression->Error != 0) {
1560 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
1561 do {
1562 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
1563 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1564 gBS->FreePool (PopUp);
1565 }
1566
1567 return EFI_NOT_READY;
1568 }
1569
1570 Link = GetNextNode (ListHead, Link);
1571 }
1572
1573 return EFI_SUCCESS;
1574 }
1575
1576
1577 /**
1578 Perform NoSubmit check for a Form.
1579
1580 @param FormSet FormSet data structure.
1581 @param Form Form data structure.
1582
1583 @retval EFI_SUCCESS Form validation pass.
1584 @retval other Form validation failed.
1585
1586 **/
1587 EFI_STATUS
1588 NoSubmitCheck (
1589 IN FORM_BROWSER_FORMSET *FormSet,
1590 IN FORM_BROWSER_FORM *Form
1591 )
1592 {
1593 EFI_STATUS Status;
1594 LIST_ENTRY *Link;
1595 FORM_BROWSER_STATEMENT *Question;
1596
1597 Link = GetFirstNode (&Form->StatementListHead);
1598 while (!IsNull (&Form->StatementListHead, Link)) {
1599 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
1600
1601 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
1602 if (EFI_ERROR (Status)) {
1603 return Status;
1604 }
1605
1606 Link = GetNextNode (&Form->StatementListHead, Link);
1607 }
1608
1609 return EFI_SUCCESS;
1610 }
1611
1612
1613 /**
1614 Submit a Form.
1615
1616 @param FormSet FormSet data structure.
1617 @param Form Form data structure.
1618
1619 @retval EFI_SUCCESS The function completed successfully.
1620
1621 **/
1622 EFI_STATUS
1623 SubmitForm (
1624 IN FORM_BROWSER_FORMSET *FormSet,
1625 IN FORM_BROWSER_FORM *Form
1626 )
1627 {
1628 EFI_STATUS Status;
1629 LIST_ENTRY *Link;
1630 EFI_STRING ConfigResp;
1631 EFI_STRING Progress;
1632 FORMSET_STORAGE *Storage;
1633
1634 //
1635 // Validate the Form by NoSubmit check
1636 //
1637 Status = NoSubmitCheck (FormSet, Form);
1638 if (EFI_ERROR (Status)) {
1639 return Status;
1640 }
1641
1642 //
1643 // Submit Buffer storage or Name/Value storage
1644 //
1645 Link = GetFirstNode (&FormSet->StorageListHead);
1646 while (!IsNull (&FormSet->StorageListHead, Link)) {
1647 Storage = FORMSET_STORAGE_FROM_LINK (Link);
1648 Link = GetNextNode (&FormSet->StorageListHead, Link);
1649
1650 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
1651 continue;
1652 }
1653
1654 //
1655 // Skip if there is no RequestElement
1656 //
1657 if (Storage->ElementCount == 0) {
1658 continue;
1659 }
1660
1661 //
1662 // Prepare <ConfigResp>
1663 //
1664 Status = StorageToConfigResp (Storage, &ConfigResp);
1665 if (EFI_ERROR (Status)) {
1666 return Status;
1667 }
1668
1669 //
1670 // Send <ConfigResp> to Configuration Driver
1671 //
1672 if (FormSet->ConfigAccess != NULL) {
1673 Status = FormSet->ConfigAccess->RouteConfig (
1674 FormSet->ConfigAccess,
1675 ConfigResp,
1676 &Progress
1677 );
1678 if (EFI_ERROR (Status)) {
1679 gBS->FreePool (ConfigResp);
1680 return Status;
1681 }
1682 }
1683 gBS->FreePool (ConfigResp);
1684
1685 //
1686 // Config success, update storage shadow Buffer
1687 //
1688 SynchronizeStorage (Storage);
1689 }
1690
1691 gNvUpdateRequired = FALSE;
1692
1693 return EFI_SUCCESS;
1694 }
1695
1696
1697 /**
1698 Reset Question to its default value.
1699
1700 @param FormSet FormSet data structure.
1701 @param DefaultId The Class of the default.
1702
1703 @retval EFI_SUCCESS Question is reset to default value.
1704
1705 **/
1706 EFI_STATUS
1707 GetQuestionDefault (
1708 IN FORM_BROWSER_FORMSET *FormSet,
1709 IN FORM_BROWSER_FORM *Form,
1710 IN FORM_BROWSER_STATEMENT *Question,
1711 IN UINT16 DefaultId
1712 )
1713 {
1714 EFI_STATUS Status;
1715 LIST_ENTRY *Link;
1716 QUESTION_DEFAULT *Default;
1717 QUESTION_OPTION *Option;
1718 EFI_HII_VALUE *HiiValue;
1719 UINT8 Index;
1720
1721 Status = EFI_SUCCESS;
1722
1723 //
1724 // Statement don't have storage, skip them
1725 //
1726 if (Question->QuestionId == 0) {
1727 return Status;
1728 }
1729
1730 //
1731 // There are three ways to specify default value for a Question:
1732 // 1, use nested EFI_IFR_DEFAULT (highest priority)
1733 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
1734 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
1735 //
1736 HiiValue = &Question->HiiValue;
1737
1738 //
1739 // EFI_IFR_DEFAULT has highest priority
1740 //
1741 if (!IsListEmpty (&Question->DefaultListHead)) {
1742 Link = GetFirstNode (&Question->DefaultListHead);
1743 while (!IsNull (&Question->DefaultListHead, Link)) {
1744 Default = QUESTION_DEFAULT_FROM_LINK (Link);
1745
1746 if (Default->DefaultId == DefaultId) {
1747 if (Default->ValueExpression != NULL) {
1748 //
1749 // Default is provided by an Expression, evaluate it
1750 //
1751 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
1752 if (EFI_ERROR (Status)) {
1753 return Status;
1754 }
1755
1756 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
1757 } else {
1758 //
1759 // Default value is embedded in EFI_IFR_DEFAULT
1760 //
1761 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
1762 }
1763
1764 return EFI_SUCCESS;
1765 }
1766
1767 Link = GetNextNode (&Question->DefaultListHead, Link);
1768 }
1769 }
1770
1771 //
1772 // EFI_ONE_OF_OPTION
1773 //
1774 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
1775 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
1776 //
1777 // OneOfOption could only provide Standard and Manufacturing default
1778 //
1779 Link = GetFirstNode (&Question->OptionListHead);
1780 while (!IsNull (&Question->OptionListHead, Link)) {
1781 Option = QUESTION_OPTION_FROM_LINK (Link);
1782
1783 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
1784 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
1785 ) {
1786 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
1787
1788 return EFI_SUCCESS;
1789 }
1790
1791 Link = GetNextNode (&Question->OptionListHead, Link);
1792 }
1793 }
1794 }
1795
1796 //
1797 // EFI_IFR_CHECKBOX - lowest priority
1798 //
1799 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
1800 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
1801 //
1802 // Checkbox could only provide Standard and Manufacturing default
1803 //
1804 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
1805 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
1806 ) {
1807 HiiValue->Value.b = TRUE;
1808 } else {
1809 HiiValue->Value.b = FALSE;
1810 }
1811
1812 return EFI_SUCCESS;
1813 }
1814 }
1815
1816 //
1817 // For Questions without default
1818 //
1819 switch (Question->Operand) {
1820 case EFI_IFR_NUMERIC_OP:
1821 //
1822 // Take minimal value as numeric's default value
1823 //
1824 HiiValue->Value.u64 = Question->Minimum;
1825 break;
1826
1827 case EFI_IFR_ONE_OF_OP:
1828 //
1829 // Take first oneof option as oneof's default value
1830 //
1831 Link = GetFirstNode (&Question->OptionListHead);
1832 if (!IsNull (&Question->OptionListHead, Link)) {
1833 Option = QUESTION_OPTION_FROM_LINK (Link);
1834 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
1835 }
1836 break;
1837
1838 case EFI_IFR_ORDERED_LIST_OP:
1839 //
1840 // Take option sequence in IFR as ordered list's default value
1841 //
1842 Index = 0;
1843 Link = GetFirstNode (&Question->OptionListHead);
1844 while (!IsNull (&Question->OptionListHead, Link)) {
1845 Option = QUESTION_OPTION_FROM_LINK (Link);
1846
1847 Question->BufferValue[Index] = Option->Value.Value.u8;
1848
1849 Index++;
1850 if (Index >= Question->MaxContainers) {
1851 break;
1852 }
1853
1854 Link = GetNextNode (&Question->OptionListHead, Link);
1855 }
1856 break;
1857
1858 default:
1859 Status = EFI_NOT_FOUND;
1860 break;
1861 }
1862
1863 return Status;
1864 }
1865
1866
1867 /**
1868 Reset Questions in a Form to their default value.
1869
1870 @param FormSet FormSet data structure.
1871 @param Form The Form which to be reset.
1872 @param DefaultId The Class of the default.
1873
1874 @retval EFI_SUCCESS The function completed successfully.
1875
1876 **/
1877 EFI_STATUS
1878 ExtractFormDefault (
1879 IN FORM_BROWSER_FORMSET *FormSet,
1880 IN FORM_BROWSER_FORM *Form,
1881 IN UINT16 DefaultId
1882 )
1883 {
1884 EFI_STATUS Status;
1885 LIST_ENTRY *Link;
1886 FORM_BROWSER_STATEMENT *Question;
1887
1888 Link = GetFirstNode (&Form->StatementListHead);
1889 while (!IsNull (&Form->StatementListHead, Link)) {
1890 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
1891 Link = GetNextNode (&Form->StatementListHead, Link);
1892
1893 //
1894 // Reset Question to its default value
1895 //
1896 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
1897 if (EFI_ERROR (Status)) {
1898 continue;
1899 }
1900
1901 //
1902 // Synchronize Buffer storage's Edit buffer
1903 //
1904 if ((Question->Storage != NULL) &&
1905 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
1906 SetQuestionValue (FormSet, Form, Question, TRUE);
1907 }
1908 }
1909
1910 return EFI_SUCCESS;
1911 }
1912
1913
1914 /**
1915 Initialize Question's Edit copy from Storage.
1916
1917 @param FormSet FormSet data structure.
1918 @param Form Form data structure.
1919
1920 @retval EFI_SUCCESS The function completed successfully.
1921
1922 **/
1923 EFI_STATUS
1924 LoadFormConfig (
1925 IN FORM_BROWSER_FORMSET *FormSet,
1926 IN FORM_BROWSER_FORM *Form
1927 )
1928 {
1929 EFI_STATUS Status;
1930 LIST_ENTRY *Link;
1931 FORM_BROWSER_STATEMENT *Question;
1932
1933 Link = GetFirstNode (&Form->StatementListHead);
1934 while (!IsNull (&Form->StatementListHead, Link)) {
1935 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
1936
1937 //
1938 // Initialize local copy of Value for each Question
1939 //
1940 Status = GetQuestionValue (FormSet, Form, Question, TRUE);
1941 if (EFI_ERROR (Status)) {
1942 return Status;
1943 }
1944
1945 Link = GetNextNode (&Form->StatementListHead, Link);
1946 }
1947
1948 return EFI_SUCCESS;
1949 }
1950
1951
1952 /**
1953 Fill storage's edit copy with settings requested from Configuration Driver.
1954
1955 @param FormSet FormSet data structure.
1956 @param Storage Buffer Storage.
1957
1958 @retval EFI_SUCCESS The function completed successfully.
1959
1960 **/
1961 EFI_STATUS
1962 LoadStorage (
1963 IN FORM_BROWSER_FORMSET *FormSet,
1964 IN FORMSET_STORAGE *Storage
1965 )
1966 {
1967 EFI_STATUS Status;
1968 EFI_STRING Progress;
1969 EFI_STRING Result;
1970 CHAR16 *StrPtr;
1971
1972 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
1973 return EFI_SUCCESS;
1974 }
1975
1976 if (FormSet->ConfigAccess == NULL) {
1977 return EFI_NOT_FOUND;
1978 }
1979
1980 if (Storage->ElementCount == 0) {
1981 //
1982 // Skip if there is no RequestElement
1983 //
1984 return EFI_SUCCESS;
1985 }
1986
1987 //
1988 // Request current settings from Configuration Driver
1989 //
1990 Status = FormSet->ConfigAccess->ExtractConfig (
1991 FormSet->ConfigAccess,
1992 Storage->ConfigRequest,
1993 &Progress,
1994 &Result
1995 );
1996 if (EFI_ERROR (Status)) {
1997 return Status;
1998 }
1999
2000 //
2001 // Convert Result from <ConfigAltResp> to <ConfigResp>
2002 //
2003 StrPtr = StrStr (Result, L"ALTCFG");
2004 if (StrPtr != NULL) {
2005 *StrPtr = L'\0';
2006 }
2007
2008 Status = ConfigRespToStorage (Storage, Result);
2009 gBS->FreePool (Result);
2010 return Status;
2011 }
2012
2013
2014 /**
2015 Get current setting of Questions.
2016
2017 @param FormSet FormSet data structure.
2018
2019 @retval EFI_SUCCESS The function completed successfully.
2020
2021 **/
2022 EFI_STATUS
2023 InitializeCurrentSetting (
2024 IN OUT FORM_BROWSER_FORMSET *FormSet
2025 )
2026 {
2027 LIST_ENTRY *Link;
2028 FORMSET_STORAGE *Storage;
2029 FORM_BROWSER_FORM *Form;
2030 EFI_STATUS Status;
2031
2032 //
2033 // Extract default from IFR binary
2034 //
2035 Link = GetFirstNode (&FormSet->FormListHead);
2036 while (!IsNull (&FormSet->FormListHead, Link)) {
2037 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
2038
2039 Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);
2040
2041 Link = GetNextNode (&FormSet->FormListHead, Link);
2042 }
2043
2044 //
2045 // Request current settings from Configuration Driver
2046 //
2047 Link = GetFirstNode (&FormSet->StorageListHead);
2048 while (!IsNull (&FormSet->StorageListHead, Link)) {
2049 Storage = FORMSET_STORAGE_FROM_LINK (Link);
2050
2051 Status = LoadStorage (FormSet, Storage);
2052
2053 //
2054 // Now Edit Buffer is filled with default values(lower priority) and current
2055 // settings(higher priority), sychronize it to shadow Buffer
2056 //
2057 if (!EFI_ERROR (Status)) {
2058 SynchronizeStorage (Storage);
2059 }
2060
2061 Link = GetNextNode (&FormSet->StorageListHead, Link);
2062 }
2063
2064 return EFI_SUCCESS;
2065 }
2066
2067
2068 /**
2069 Fetch the Ifr binary data of a FormSet.
2070
2071 @param Handle PackageList Handle
2072 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
2073 GUID), take the first FormSet found in package
2074 list.
2075 @param BinaryLength The length of the FormSet IFR binary.
2076 @param BinaryData The buffer designed to receive the FormSet.
2077
2078 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
2079 BufferLength was updated.
2080 @retval EFI_INVALID_PARAMETER The handle is unknown.
2081 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
2082 be found with the requested FormId.
2083
2084 **/
2085 EFI_STATUS
2086 GetIfrBinaryData (
2087 IN EFI_HII_HANDLE Handle,
2088 IN OUT EFI_GUID *FormSetGuid,
2089 OUT UINTN *BinaryLength,
2090 OUT UINT8 **BinaryData
2091 )
2092 {
2093 EFI_STATUS Status;
2094 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
2095 UINTN BufferSize;
2096 UINT8 *Package;
2097 UINT8 *OpCodeData;
2098 UINT32 Offset;
2099 UINT32 Offset2;
2100 BOOLEAN ReturnDefault;
2101 UINT32 PackageListLength;
2102 EFI_HII_PACKAGE_HEADER PackageHeader;
2103
2104 OpCodeData = NULL;
2105 Package = NULL;
2106 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
2107
2108 //
2109 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
2110 //
2111 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
2112 ReturnDefault = TRUE;
2113 } else {
2114 ReturnDefault = FALSE;
2115 }
2116
2117 //
2118 // Get HII PackageList
2119 //
2120 BufferSize = 0;
2121 HiiPackageList = NULL;
2122 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
2123 if (Status == EFI_BUFFER_TOO_SMALL) {
2124 HiiPackageList = AllocatePool (BufferSize);
2125 ASSERT (HiiPackageList != NULL);
2126
2127 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
2128 }
2129 if (EFI_ERROR (Status)) {
2130 return Status;
2131 }
2132
2133 //
2134 // Get Form package from this HII package List
2135 //
2136 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
2137 Offset2 = 0;
2138 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
2139
2140 while (Offset < PackageListLength) {
2141 Package = ((UINT8 *) HiiPackageList) + Offset;
2142 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2143
2144 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
2145 //
2146 // Search FormSet in this Form Package
2147 //
2148 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
2149 while (Offset2 < PackageHeader.Length) {
2150 OpCodeData = Package + Offset2;
2151
2152 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
2153 //
2154 // Check whether return default FormSet
2155 //
2156 if (ReturnDefault) {
2157 break;
2158 }
2159
2160 //
2161 // FormSet GUID is specified, check it
2162 //
2163 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
2164 break;
2165 }
2166 }
2167
2168 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
2169 }
2170
2171 if (Offset2 < PackageHeader.Length) {
2172 //
2173 // Target formset found
2174 //
2175 break;
2176 }
2177 }
2178
2179 Offset += PackageHeader.Length;
2180 }
2181
2182 if (Offset >= PackageListLength) {
2183 //
2184 // Form package not found in this Package List
2185 //
2186 gBS->FreePool (HiiPackageList);
2187 return EFI_NOT_FOUND;
2188 }
2189
2190 if (ReturnDefault && FormSetGuid != NULL) {
2191 //
2192 // Return the default FormSet GUID
2193 //
2194 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
2195 }
2196
2197 //
2198 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
2199 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
2200 // of the Form Package.
2201 //
2202 *BinaryLength = PackageHeader.Length - Offset2;
2203 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
2204
2205 gBS->FreePool (HiiPackageList);
2206
2207 if (*BinaryData == NULL) {
2208 return EFI_OUT_OF_RESOURCES;
2209 }
2210
2211 return EFI_SUCCESS;
2212 }
2213
2214
2215 /**
2216 Initialize the internal data structure of a FormSet.
2217
2218 @param Handle PackageList Handle
2219 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
2220 GUID), take the first FormSet found in package
2221 list.
2222 @param FormSet FormSet data structure.
2223
2224 @retval EFI_SUCCESS The function completed successfully.
2225 @retval EFI_NOT_FOUND The specified FormSet could not be found.
2226
2227 **/
2228 EFI_STATUS
2229 InitializeFormSet (
2230 IN EFI_HII_HANDLE Handle,
2231 IN OUT EFI_GUID *FormSetGuid,
2232 OUT FORM_BROWSER_FORMSET *FormSet
2233 )
2234 {
2235 EFI_STATUS Status;
2236 EFI_HANDLE DriverHandle;
2237 UINT16 Index;
2238
2239 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
2240 if (EFI_ERROR (Status)) {
2241 return Status;
2242 }
2243
2244 FormSet->HiiHandle = Handle;
2245 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
2246
2247 //
2248 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
2249 //
2250 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);
2251 if (EFI_ERROR (Status)) {
2252 return Status;
2253 }
2254 FormSet->DriverHandle = DriverHandle;
2255 Status = gBS->HandleProtocol (
2256 DriverHandle,
2257 &gEfiHiiConfigAccessProtocolGuid,
2258 (VOID **) &FormSet->ConfigAccess
2259 );
2260 if (EFI_ERROR (Status)) {
2261 //
2262 // Configuration Driver don't attach ConfigAccess protocol to its HII package
2263 // list, then there will be no configuration action required
2264 //
2265 FormSet->ConfigAccess = NULL;
2266 }
2267
2268 //
2269 // Parse the IFR binary OpCodes
2270 //
2271 Status = ParseOpCodes (FormSet);
2272 if (EFI_ERROR (Status)) {
2273 return Status;
2274 }
2275
2276 gClassOfVfr = FormSet->SubClass;
2277 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
2278 FrontPageHandle = FormSet->HiiHandle;
2279 }
2280
2281 //
2282 // Match GUID to find out the function key setting. If match fail, use the default setting.
2283 //
2284 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
2285 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
2286 //
2287 // Update the function key setting.
2288 //
2289 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
2290 //
2291 // Function key prompt can not be displayed if the function key has been disabled.
2292 //
2293 if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
2294 gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2295 }
2296
2297 if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
2298 gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2299 }
2300
2301 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
2302 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2303 }
2304
2305 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
2306 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2307 }
2308 }
2309 }
2310
2311 return Status;
2312 }