]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Merged in the following trackers from EDK:
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
93e3992d 1/** @file
813acf3a 2Copyright (c) 2007 - 2008, Intel Corporation
93e3992d 3All rights reserved. This program and the accompanying materials
4are licensed and made available under the terms and conditions of the BSD License
5which accompanies this distribution. The full text of the license may be found at
6http://opensource.org/licenses/bsd-license.php
7
8THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11Module Name:
12
13 Setup.c
14
15Abstract:
16
17 Entry and initialization module for the browser.
18
19
20**/
21
22#include "Setup.h"
23#include "Ui.h"
24
25
26SETUP_DRIVER_PRIVATE_DATA mPrivateData = {
27 SETUP_DRIVER_SIGNATURE,
28 NULL,
29 {
30 SendForm,
31 BrowserCallback
32 },
33 {
34 UnicodeVSPrint
35 }
36};
37
38EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
39EFI_HII_STRING_PROTOCOL *mHiiString;
40EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
41
42BANNER_DATA *BannerData;
43EFI_HII_HANDLE FrontPageHandle;
44UINTN gClassOfVfr;
45UINTN gFunctionKeySetting;
46BOOLEAN gResetRequired;
47BOOLEAN gNvUpdateRequired;
48EFI_HII_HANDLE gHiiHandle;
49BOOLEAN gFirstIn;
50UINT16 gDirection;
51EFI_SCREEN_DESCRIPTOR gScreenDimensions;
52BOOLEAN gUpArrow;
53BOOLEAN gDownArrow;
54
55//
56// Browser Global Strings
57//
58CHAR16 *gFunctionOneString;
59CHAR16 *gFunctionTwoString;
60CHAR16 *gFunctionNineString;
61CHAR16 *gFunctionTenString;
62CHAR16 *gEnterString;
63CHAR16 *gEnterCommitString;
64CHAR16 *gEscapeString;
65CHAR16 *gSaveFailed;
66CHAR16 *gMoveHighlight;
67CHAR16 *gMakeSelection;
68CHAR16 *gDecNumericInput;
69CHAR16 *gHexNumericInput;
70CHAR16 *gToggleCheckBox;
71CHAR16 *gPromptForData;
72CHAR16 *gPromptForPassword;
73CHAR16 *gPromptForNewPassword;
74CHAR16 *gConfirmPassword;
75CHAR16 *gConfirmError;
76CHAR16 *gPassowordInvalid;
77CHAR16 *gPressEnter;
78CHAR16 *gEmptyString;
79CHAR16 *gAreYouSure;
80CHAR16 *gYesResponse;
81CHAR16 *gNoResponse;
82CHAR16 *gMiniString;
83CHAR16 *gPlusString;
84CHAR16 *gMinusString;
85CHAR16 *gAdjustNumber;
86
87CHAR16 gPromptBlockWidth;
88CHAR16 gOptionBlockWidth;
89CHAR16 gHelpBlockWidth;
90
36fe40c2 91EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
93e3992d 92EFI_GUID gSetupBrowserGuid = {
36fe40c2 93 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
93e3992d 94};
95
96FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
97 //
98 // Boot Manager
99 //
100 {
101 {
102 0x847bc3fe,
103 0xb974,
104 0x446d,
36fe40c2 105 {
106 0x94,
107 0x49,
108 0x5a,
109 0xd5,
110 0x41,
111 0x2e,
112 0x99,
113 0x3b
114 }
93e3992d 115 },
116 NONE_FUNCTION_KEY_SETTING
117 },
118 //
119 // Device Manager
120 //
121 {
122 {
123 0x3ebfa8e6,
124 0x511d,
125 0x4b5b,
36fe40c2 126 {
127 0xa9,
128 0x5f,
129 0xfb,
130 0x38,
131 0x26,
132 0xf,
133 0x1c,
134 0x27
135 }
93e3992d 136 },
137 NONE_FUNCTION_KEY_SETTING
138 },
139 //
140 // BMM FormSet.
141 //
142 {
143 {
144 0x642237c7,
145 0x35d4,
146 0x472d,
36fe40c2 147 {
148 0x83,
149 0x65,
150 0x12,
151 0xe0,
152 0xcc,
153 0xf2,
154 0x7a,
155 0x22
156 }
93e3992d 157 },
158 NONE_FUNCTION_KEY_SETTING
159 },
160 //
161 // BMM File Explorer FormSet.
162 //
163 {
164 {
165 0x1f2d63e1,
166 0xfebd,
167 0x4dc7,
36fe40c2 168 {
169 0x9c,
170 0xc5,
171 0xba,
172 0x2b,
173 0x1c,
174 0xef,
175 0x9c,
176 0x5b
177 }
93e3992d 178 },
179 NONE_FUNCTION_KEY_SETTING
180 },
181};
182
93e3992d 183EFI_STATUS
184EFIAPI
185SendForm (
186 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
187 IN EFI_HII_HANDLE *Handles,
188 IN UINTN HandleCount,
189 IN EFI_GUID *FormSetGuid, OPTIONAL
190 IN UINT16 FormId, OPTIONAL
191 IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
192 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
193 )
194/*++
195
196Routine Description:
197 This is the routine which an external caller uses to direct the browser
198 where to obtain it's information.
199
200Arguments:
201 This - The Form Browser protocol instanse.
202 Handles - A pointer to an array of Handles. If HandleCount > 1 we
203 display a list of the formsets for the handles specified.
204 HandleCount - The number of Handles specified in Handle.
205 FormSetGuid - This field points to the EFI_GUID which must match the Guid
206 field in the EFI_IFR_FORM_SET op-code for the specified
207 forms-based package. If FormSetGuid is NULL, then this
208 function will display the first found forms package.
209 FormId - This field specifies which EFI_IFR_FORM to render as the first
210 displayable page. If this field has a value of 0x0000, then
211 the forms browser will render the specified forms in their encoded order.
212 ScreenDimenions - This allows the browser to be called so that it occupies a
213 portion of the physical screen instead of dynamically determining the screen dimensions.
214 ActionRequest - Points to the action recommended by the form.
215
216Returns:
217 EFI_SUCCESS - The function completed successfully.
218 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
219 EFI_NOT_FOUND - No valid forms could be found to display.
220
221--*/
222{
223 EFI_STATUS Status;
224 UI_MENU_SELECTION *Selection;
225 UINTN Index;
226 FORM_BROWSER_FORMSET *FormSet;
227
228 Status = EFI_SUCCESS;
229 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
230
231 //
232 // Seed the dimensions in the global
233 //
234 gST->ConOut->QueryMode (
235 gST->ConOut,
236 gST->ConOut->Mode->Mode,
237 &gScreenDimensions.RightColumn,
238 &gScreenDimensions.BottomRow
239 );
240
241 if (ScreenDimensions != NULL) {
242 //
243 // Check local dimension vs. global dimension.
244 //
245 if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
246 (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
247 ) {
248 return EFI_INVALID_PARAMETER;
249 } else {
250 //
251 // Local dimension validation.
252 //
253 if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
254 (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
255 ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
256 (
257 (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
258 SCROLL_ARROW_HEIGHT *
259 2 +
260 FRONT_PAGE_HEADER_HEIGHT +
261 FOOTER_HEIGHT +
262 1
263 )
264 ) {
265 CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
266 } else {
267 return EFI_INVALID_PARAMETER;
268 }
269 }
270 }
271
272 gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
273 gHelpBlockWidth = gOptionBlockWidth;
274 gPromptBlockWidth = gOptionBlockWidth;
275
276 //
277 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
278 //
279 InitializeBrowserStrings ();
280
281 gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
282 gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;
283
284 //
285 // Ensure we are in Text mode
286 //
287 if (gFirstIn) {
288 gFirstIn = FALSE;
289 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
290 DisableQuietBoot ();
291 }
292
293 for (Index = 0; Index < HandleCount; Index++) {
294 Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
295 ASSERT (Selection != NULL);
296
297 Selection->Handle = Handles[Index];
298 if (FormSetGuid != NULL) {
299 CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
300 Selection->FormId = FormId;
301 }
302
303 do {
304 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
305 ASSERT (FormSet != NULL);
306
307 //
308 // Initialize internal data structures of FormSet
309 //
310 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
311 if (EFI_ERROR (Status)) {
312 DestroyFormSet (FormSet);
313 break;
314 }
315 Selection->FormSet = FormSet;
316
317 //
318 // Initialize current settings of Questions in this FormSet
319 //
320 Status = InitializeCurrentSetting (FormSet);
321 if (EFI_ERROR (Status)) {
322 DestroyFormSet (FormSet);
323 break;
324 }
325
326 //
327 // Display this formset
328 //
329 gCurrentSelection = Selection;
330
331 Status = SetupBrowser (Selection);
332
333 gCurrentSelection = NULL;
334 DestroyFormSet (FormSet);
335
336 if (EFI_ERROR (Status)) {
337 break;
338 }
339
340 } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
341
342 gBS->FreePool (Selection);
343 }
344
345 if (ActionRequest != NULL) {
346 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
347 if (gResetRequired) {
348 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
349 }
350 }
351
352 FreeBrowserStrings ();
353
354 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
355 gST->ConOut->ClearScreen (gST->ConOut);
356
357 return Status;
358}
359
360
361/**
362 This function is called by a callback handler to retrieve uncommitted state
363 data from the browser.
364
365 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
366 instance.
367 @param ResultsDataSize A pointer to the size of the buffer associated
368 with ResultsData.
369 @param ResultsData A string returned from an IFR browser or
370 equivalent. The results string will have no
371 routing information in them.
372 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
373 (if RetrieveData = TRUE) data from the uncommitted
374 browser state information or set (if RetrieveData
375 = FALSE) data in the uncommitted browser state
376 information.
377 @param VariableGuid An optional field to indicate the target variable
378 GUID name to use.
379 @param VariableName An optional field to indicate the target
380 human-readable variable name.
381
382 @retval EFI_SUCCESS The results have been distributed or are awaiting
383 distribution.
384 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
385 contain the results data.
386
387**/
388EFI_STATUS
389EFIAPI
390BrowserCallback (
391 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
392 IN OUT UINTN *ResultsDataSize,
393 IN OUT EFI_STRING ResultsData,
394 IN BOOLEAN RetrieveData,
395 IN CONST EFI_GUID *VariableGuid, OPTIONAL
396 IN CONST CHAR16 *VariableName OPTIONAL
397 )
398{
399 EFI_STATUS Status;
400 LIST_ENTRY *Link;
401 FORMSET_STORAGE *Storage;
402 FORM_BROWSER_FORMSET *FormSet;
403 BOOLEAN Found;
404 CHAR16 *ConfigResp;
405 CHAR16 *StrPtr;
406 UINTN BufferSize;
407 UINTN TmpSize;
408
409 if (ResultsDataSize == NULL || ResultsData == NULL) {
410 return EFI_INVALID_PARAMETER;
411 }
412
413 if (gCurrentSelection == NULL) {
414 return EFI_NOT_READY;
415 }
416
417 Storage = NULL;
418 ConfigResp = NULL;
419 FormSet = gCurrentSelection->FormSet;
420
421 //
422 // Find target storage
423 //
424 Link = GetFirstNode (&FormSet->StorageListHead);
425 if (IsNull (&FormSet->StorageListHead, Link)) {
426 return EFI_UNSUPPORTED;
427 }
428
429 if (VariableGuid != NULL) {
430 //
431 // Try to find target storage
432 //
433 Found = FALSE;
434 while (!IsNull (&FormSet->StorageListHead, Link)) {
435 Storage = FORMSET_STORAGE_FROM_LINK (Link);
436 Link = GetNextNode (&FormSet->StorageListHead, Link);
437
438 if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
439 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
440 //
441 // Buffer storage require both GUID and Name
442 //
443 if (VariableName == NULL) {
444 return EFI_NOT_FOUND;
445 }
446
447 if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
448 continue;
449 }
450 }
451 Found = TRUE;
452 break;
453 }
454 }
455
456 if (!Found) {
457 return EFI_NOT_FOUND;
458 }
459 } else {
460 //
461 // GUID/Name is not specified, take the first storage in FormSet
462 //
463 Storage = FORMSET_STORAGE_FROM_LINK (Link);
464 }
465
466 if (RetrieveData) {
467 //
468 // Skip if there is no RequestElement
469 //
470 if (Storage->ElementCount == 0) {
471 return EFI_SUCCESS;
472 }
473
474 //
475 // Generate <ConfigResp>
476 //
477 Status = StorageToConfigResp (Storage, &ConfigResp);
478 if (EFI_ERROR (Status)) {
479 return Status;
480 }
481
482 //
483 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
484 //
485 StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
486
487 BufferSize = StrSize (StrPtr);
488 if (*ResultsDataSize < BufferSize) {
489 *ResultsDataSize = BufferSize;
490
491 gBS->FreePool (ConfigResp);
492 return EFI_BUFFER_TOO_SMALL;
493 }
494
495 *ResultsDataSize = BufferSize;
496 CopyMem (ResultsData, StrPtr, BufferSize);
497
498 gBS->FreePool (ConfigResp);
499 } else {
500 //
501 // Prepare <ConfigResp>
502 //
503 TmpSize = StrLen (ResultsData);
504 BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
505 ConfigResp = AllocateZeroPool (BufferSize);
506 ASSERT (ConfigResp != NULL);
507
508 StrCpy (ConfigResp, Storage->ConfigHdr);
509 StrCat (ConfigResp, L"&");
510 StrCat (ConfigResp, ResultsData);
511
512 //
513 // Update Browser uncommited data
514 //
515 Status = ConfigRespToStorage (Storage, ConfigResp);
516 if (EFI_ERROR (Status)) {
517 return Status;
518 }
519 }
520
521 return EFI_SUCCESS;
522}
523
524
525/**
526 Initialize Setup
527
528 @param entry EFI_IMAGE_ENTRY_POINT)
529
530 @retval EFI_SUCCESS Setup loaded.
531 @retval other Setup Error
532
533**/
534EFI_STATUS
535EFIAPI
536InitializeSetup (
537 IN EFI_HANDLE ImageHandle,
538 IN EFI_SYSTEM_TABLE *SystemTable
539 )
540{
541 EFI_STATUS Status;
542 EFI_HANDLE HiiDriverHandle;
543 EFI_HII_PACKAGE_LIST_HEADER *PackageList;
544
93e3992d 545 //
546 // Locate required Hii relative protocols
547 //
548 Status = gBS->LocateProtocol (
549 &gEfiHiiDatabaseProtocolGuid,
550 NULL,
551 (VOID **) &mHiiDatabase
552 );
553 ASSERT_EFI_ERROR (Status);
554
555 Status = gBS->LocateProtocol (
556 &gEfiHiiStringProtocolGuid,
557 NULL,
558 (VOID **) &mHiiString
559 );
560 ASSERT_EFI_ERROR (Status);
561
562 Status = gBS->LocateProtocol (
563 &gEfiHiiConfigRoutingProtocolGuid,
564 NULL,
565 (VOID **) &mHiiConfigRouting
566 );
567 ASSERT_EFI_ERROR (Status);
568
569 //
570 // Publish our HII data
571 //
572 Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);
573 ASSERT_EFI_ERROR (Status);
574
9226efe5 575 PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
93e3992d 576 ASSERT (PackageList != NULL);
577 Status = mHiiDatabase->NewPackageList (
578 mHiiDatabase,
579 PackageList,
580 HiiDriverHandle,
581 &gHiiHandle
582 );
583 ASSERT_EFI_ERROR (Status);
584
585 //
586 // Initialize Driver private data
587 //
588 gFirstIn = TRUE;
589 BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
590 ASSERT (BannerData != NULL);
591
592 //
593 // Install FormBrowser2 protocol
594 //
595 mPrivateData.Handle = NULL;
596 Status = gBS->InstallProtocolInterface (
597 &mPrivateData.Handle,
598 &gEfiFormBrowser2ProtocolGuid,
599 EFI_NATIVE_INTERFACE,
600 &mPrivateData.FormBrowser2
601 );
602 ASSERT_EFI_ERROR (Status);
603
604 //
605 // Install Print protocol
606 //
607 Status = gBS->InstallProtocolInterface (
608 &mPrivateData.Handle,
609 &gEfiPrintProtocolGuid,
610 EFI_NATIVE_INTERFACE,
611 &mPrivateData.Print
612 );
613
614 return Status;
615}
616
617
618/**
619 Create a new string in HII Package List.
620
621 @param String The String to be added
622 @param HiiHandle The package list in the HII database to insert the
623 specified string.
624
625 @return The output string.
626
627**/
628EFI_STRING_ID
629NewString (
630 IN CHAR16 *String,
631 IN EFI_HII_HANDLE HiiHandle
632 )
633{
634 EFI_STRING_ID StringId;
635 EFI_STATUS Status;
636
637 StringId = 0;
9226efe5 638 Status = HiiLibNewString (HiiHandle, &StringId, String);
93e3992d 639 ASSERT_EFI_ERROR (Status);
640
641 return StringId;
642}
643
644
645/**
646 Delete a string from HII Package List.
647
648 @param StringId Id of the string in HII database.
649 @param HiiHandle The HII package list handle.
650
651 @retval EFI_SUCCESS The string was deleted successfully.
652
653**/
654EFI_STATUS
655DeleteString (
656 IN EFI_STRING_ID StringId,
657 IN EFI_HII_HANDLE HiiHandle
658 )
659{
660 CHAR16 NullChar;
661
662 NullChar = CHAR_NULL;
9226efe5 663 return HiiLibSetString (HiiHandle, StringId, &NullChar);
93e3992d 664}
665
666
667/**
668 Get the string based on the StringId and HII Package List Handle.
669
670 @param Token The String's ID.
671 @param HiiHandle The package list in the HII database to search for
672 the specified string.
673
674 @return The output string.
675
676**/
677CHAR16 *
678GetToken (
679 IN EFI_STRING_ID Token,
680 IN EFI_HII_HANDLE HiiHandle
681 )
682{
683 EFI_STATUS Status;
684 CHAR16 *String;
685 UINTN BufferLength;
686
687 //
688 // Set default string size assumption at no more than 256 bytes
689 //
690 BufferLength = 0x100;
691 String = AllocateZeroPool (BufferLength);
692 ASSERT (String != NULL);
693
9226efe5 694 Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
93e3992d 695
696 if (Status == EFI_BUFFER_TOO_SMALL) {
697 gBS->FreePool (String);
698 String = AllocateZeroPool (BufferLength);
699 ASSERT (String != NULL);
700
9226efe5 701 Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
93e3992d 702 }
703 ASSERT_EFI_ERROR (Status);
704
705 return String;
706}
707
708
709/**
710 Allocate new memory and then copy the Unicode string Source to Destination.
711
712 @param Dest Location to copy string
713 @param Src String to copy
714
715 @return NONE
716
717**/
718VOID
719NewStringCpy (
720 IN OUT CHAR16 **Dest,
721 IN CHAR16 *Src
722 )
723{
724 SafeFreePool (*Dest);
725 *Dest = AllocateCopyPool (StrSize (Src), Src);
726 ASSERT (*Dest != NULL);
727}
728
729
730/**
731 Allocate new memory and concatinate Source on the end of Destination.
732
733 @param Dest String to added to the end of.
734 @param Src String to concatinate.
735
736 @return NONE
737
738**/
739VOID
740NewStringCat (
741 IN OUT CHAR16 **Dest,
742 IN CHAR16 *Src
743 )
744{
745 CHAR16 *NewString;
746 UINTN TmpSize;
747
748 if (*Dest == NULL) {
749 NewStringCpy (Dest, Src);
750 return;
751 }
752
753 TmpSize = StrSize (*Dest);
754 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
755 ASSERT (NewString != NULL);
756
757 StrCpy (NewString, *Dest);
758 StrCat (NewString, Src);
759
760 gBS->FreePool (*Dest);
761 *Dest = NewString;
762}
763
764
765/**
766 Synchronize Storage's Edit copy to Shadow copy.
767
768 @param Storage The Storage to be synchronized.
769
770 @return NONE
771
772**/
773VOID
774SynchronizeStorage (
775 IN FORMSET_STORAGE *Storage
776 )
777{
778 LIST_ENTRY *Link;
779 NAME_VALUE_NODE *Node;
780
781 switch (Storage->Type) {
782 case EFI_HII_VARSTORE_BUFFER:
783 CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
784 break;
785
786 case EFI_HII_VARSTORE_NAME_VALUE:
787 Link = GetFirstNode (&Storage->NameValueListHead);
788 while (!IsNull (&Storage->NameValueListHead, Link)) {
789 Node = NAME_VALUE_NODE_FROM_LINK (Link);
790
791 NewStringCpy (&Node->Value, Node->EditValue);
792
793 Link = GetNextNode (&Storage->NameValueListHead, Link);
794 }
795 break;
796
797 case EFI_HII_VARSTORE_EFI_VARIABLE:
798 default:
799 break;
800 }
801}
802
803
804/**
805 Get Value for given Name from a NameValue Storage.
806
807 @param Storage The NameValue Storage.
808 @param Name The Name.
809 @param Value The retured Value.
810
811 @retval EFI_SUCCESS Value found for given Name.
812 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
813
814**/
815EFI_STATUS
816GetValueByName (
817 IN FORMSET_STORAGE *Storage,
818 IN CHAR16 *Name,
819 IN OUT CHAR16 **Value
820 )
821{
822 LIST_ENTRY *Link;
823 NAME_VALUE_NODE *Node;
824
825 *Value = NULL;
826
827 Link = GetFirstNode (&Storage->NameValueListHead);
828 while (!IsNull (&Storage->NameValueListHead, Link)) {
829 Node = NAME_VALUE_NODE_FROM_LINK (Link);
830
831 if (StrCmp (Name, Node->Name) == 0) {
832 NewStringCpy (Value, Node->EditValue);
833 return EFI_SUCCESS;
834 }
835
836 Link = GetNextNode (&Storage->NameValueListHead, Link);
837 }
838
839 return EFI_NOT_FOUND;
840}
841
842
843/**
844 Set Value of given Name in a NameValue Storage.
845
846 @param Storage The NameValue Storage.
847 @param Name The Name.
848 @param Value The Value to set.
849
850 @retval EFI_SUCCESS Value found for given Name.
851 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
852
853**/
854EFI_STATUS
855SetValueByName (
856 IN FORMSET_STORAGE *Storage,
857 IN CHAR16 *Name,
858 IN CHAR16 *Value
859 )
860{
861 LIST_ENTRY *Link;
862 NAME_VALUE_NODE *Node;
863
864 Link = GetFirstNode (&Storage->NameValueListHead);
865 while (!IsNull (&Storage->NameValueListHead, Link)) {
866 Node = NAME_VALUE_NODE_FROM_LINK (Link);
867
868 if (StrCmp (Name, Node->Name) == 0) {
869 SafeFreePool (Node->EditValue);
870 Node->EditValue = AllocateCopyPool (StrSize (Value), Value);
871 ASSERT (Node->EditValue != NULL);
872 return EFI_SUCCESS;
873 }
874
875 Link = GetNextNode (&Storage->NameValueListHead, Link);
876 }
877
878 return EFI_NOT_FOUND;
879}
880
881
882/**
883 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
884
885 @param Storage The Storage to be conveted.
886 @param ConfigResp The returned <ConfigResp>.
887
888 @retval EFI_SUCCESS Convert success.
889 @retval EFI_INVALID_PARAMETER Incorrect storage type.
890
891**/
892EFI_STATUS
893StorageToConfigResp (
894 IN FORMSET_STORAGE *Storage,
895 IN CHAR16 **ConfigResp
896 )
897{
898 EFI_STATUS Status;
899 EFI_STRING Progress;
900 LIST_ENTRY *Link;
901 NAME_VALUE_NODE *Node;
902
903 Status = EFI_SUCCESS;
904
905 switch (Storage->Type) {
906 case EFI_HII_VARSTORE_BUFFER:
907 Status = mHiiConfigRouting->BlockToConfig (
908 mHiiConfigRouting,
909 Storage->ConfigRequest,
910 Storage->EditBuffer,
911 Storage->Size,
912 ConfigResp,
913 &Progress
914 );
915 break;
916
917 case EFI_HII_VARSTORE_NAME_VALUE:
918 *ConfigResp = NULL;
919 NewStringCat (ConfigResp, Storage->ConfigHdr);
920
921 Link = GetFirstNode (&Storage->NameValueListHead);
922 while (!IsNull (&Storage->NameValueListHead, Link)) {
923 Node = NAME_VALUE_NODE_FROM_LINK (Link);
924
925 NewStringCat (ConfigResp, L"&");
926 NewStringCat (ConfigResp, Node->Name);
927 NewStringCat (ConfigResp, L"=");
928 NewStringCat (ConfigResp, Node->EditValue);
929
930 Link = GetNextNode (&Storage->NameValueListHead, Link);
931 }
932 break;
933
934 case EFI_HII_VARSTORE_EFI_VARIABLE:
935 default:
936 Status = EFI_INVALID_PARAMETER;
937 break;
938 }
939
940 return Status;
941}
942
943
944/**
945 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
946
947 @param Storage The Storage to receive the settings.
948 @param ConfigResp The <ConfigResp> to be converted.
949
950 @retval EFI_SUCCESS Convert success.
951 @retval EFI_INVALID_PARAMETER Incorrect storage type.
952
953**/
954EFI_STATUS
955ConfigRespToStorage (
956 IN FORMSET_STORAGE *Storage,
957 IN CHAR16 *ConfigResp
958 )
959{
960 EFI_STATUS Status;
961 EFI_STRING Progress;
962 UINTN BufferSize;
963 CHAR16 *StrPtr;
964 CHAR16 *Name;
965 CHAR16 *Value;
966
967 Status = EFI_SUCCESS;
968
969 switch (Storage->Type) {
970 case EFI_HII_VARSTORE_BUFFER:
971 BufferSize = Storage->Size;
972 Status = mHiiConfigRouting->ConfigToBlock (
973 mHiiConfigRouting,
974 ConfigResp,
975 Storage->EditBuffer,
976 &BufferSize,
977 &Progress
978 );
979 break;
980
981 case EFI_HII_VARSTORE_NAME_VALUE:
982 StrPtr = StrStr (ConfigResp, L"&");
983 while (StrPtr != NULL) {
984 //
985 // Skip '&'
986 //
987 StrPtr = StrPtr + 1;
988 Name = StrPtr;
989 StrPtr = StrStr (StrPtr, L"=");
990 if (StrPtr == NULL) {
991 break;
992 }
993 *StrPtr = 0;
994
995 //
996 // Skip '='
997 //
998 StrPtr = StrPtr + 1;
999 Value = StrPtr;
1000 StrPtr = StrStr (StrPtr, L"&");
1001 if (StrPtr != NULL) {
1002 *StrPtr = 0;
1003 }
1004 SetValueByName (Storage, Name, Value);
1005 }
1006 break;
1007
1008 case EFI_HII_VARSTORE_EFI_VARIABLE:
1009 default:
1010 Status = EFI_INVALID_PARAMETER;
1011 break;
1012 }
1013
1014 return Status;
1015}
1016
1017
1018/**
1019 Get Question's current Value.
1020
1021 @param FormSet FormSet data structure.
1022 @param Form Form data structure.
1023 @param Question Question to be initialized.
1024 @param Cached TRUE: get from Edit copy FALSE: get from original
1025 Storage
1026
1027 @retval EFI_SUCCESS The function completed successfully.
1028
1029**/
1030EFI_STATUS
1031GetQuestionValue (
1032 IN FORM_BROWSER_FORMSET *FormSet,
1033 IN FORM_BROWSER_FORM *Form,
1034 IN OUT FORM_BROWSER_STATEMENT *Question,
1035 IN BOOLEAN Cached
1036 )
1037{
1038 EFI_STATUS Status;
1039 BOOLEAN Enabled;
1040 BOOLEAN Pending;
1041 UINT8 *Dst;
1042 UINTN StorageWidth;
1043 EFI_TIME EfiTime;
1044 FORMSET_STORAGE *Storage;
1045 EFI_IFR_TYPE_VALUE *QuestionValue;
1046 CHAR16 *ConfigRequest;
1047 CHAR16 *Progress;
1048 CHAR16 *Result;
1049 CHAR16 *Value;
1050 UINTN Length;
1051 BOOLEAN IsBufferStorage;
1052 BOOLEAN IsString;
1053
1054 Status = EFI_SUCCESS;
1055
1056 //
1057 // Statement don't have storage, skip them
1058 //
1059 if (Question->QuestionId == 0) {
1060 return Status;
1061 }
1062
1063 //
1064 // Question value is provided by an Expression, evaluate it
1065 //
1066 if (Question->ValueExpression != NULL) {
1067 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
1068 if (!EFI_ERROR (Status)) {
1069 CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));
1070 }
1071 return Status;
1072 }
1073
1074 //
1075 // Question value is provided by RTC
1076 //
1077 Storage = Question->Storage;
1078 QuestionValue = &Question->HiiValue.Value;
1079 if (Storage == NULL) {
1080 //
1081 // It's a Question without storage, or RTC date/time
1082 //
1083 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
1084 //
1085 // Date and time define the same Flags bit
1086 //
1087 switch (Question->Flags & EFI_QF_DATE_STORAGE) {
1088 case QF_DATE_STORAGE_TIME:
1089 Status = gRT->GetTime (&EfiTime, NULL);
1090 break;
1091
1092 case QF_DATE_STORAGE_WAKEUP:
1093 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
1094 break;
1095
1096 case QF_DATE_STORAGE_NORMAL:
1097 default:
1098 //
1099 // For date/time without storage
1100 //
1101 return EFI_SUCCESS;
1102 }
1103
1104 if (EFI_ERROR (Status)) {
1105 return Status;
1106 }
1107
1108 if (Question->Operand == EFI_IFR_DATE_OP) {
1109 QuestionValue->date.Year = EfiTime.Year;
1110 QuestionValue->date.Month = EfiTime.Month;
1111 QuestionValue->date.Day = EfiTime.Day;
1112 } else {
1113 QuestionValue->time.Hour = EfiTime.Hour;
1114 QuestionValue->time.Minute = EfiTime.Minute;
1115 QuestionValue->time.Second = EfiTime.Second;
1116 }
1117 }
1118
1119 return EFI_SUCCESS;
1120 }
1121
1122 //
1123 // Question value is provided by EFI variable
1124 //
1125 StorageWidth = Question->StorageWidth;
1126 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
1127 if (Question->BufferValue != NULL) {
1128 Dst = Question->BufferValue;
1129 } else {
1130 Dst = (UINT8 *) QuestionValue;
1131 }
1132
1133 Status = gRT->GetVariable (
1134 Question->VariableName,
1135 &Storage->Guid,
1136 NULL,
1137 &StorageWidth,
1138 Dst
1139 );
1140 //
1141 // Always return success, even this EFI variable doesn't exist
1142 //
1143 return EFI_SUCCESS;
1144 }
1145
1146 //
1147 // Question Value is provided by Buffer Storage or NameValue Storage
1148 //
1149 if (Question->BufferValue != NULL) {
1150 //
1151 // This Question is password or orderedlist
1152 //
1153 Dst = Question->BufferValue;
1154 } else {
1155 //
1156 // Other type of Questions
1157 //
1158 Dst = (UINT8 *) &Question->HiiValue.Value;
1159 }
1160
1161 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
1162 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
1163 if (Cached) {
1164 if (IsBufferStorage) {
1165 //
1166 // Copy from storage Edit buffer
1167 //
1168 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
1169 } else {
1170 Status = GetValueByName (Storage, Question->VariableName, &Value);
1171 if (EFI_ERROR (Status)) {
1172 return Status;
1173 }
1174
1175 if (IsString) {
813acf3a 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);
93e3992d 1181 } else {
36fe40c2 1182 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
93e3992d 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) {
813acf3a 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);
93e3992d 1251 } else {
36fe40c2 1252 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
93e3992d 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**/
1286EFI_STATUS
1287SetQuestionValue (
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) {
813acf3a 1419 //
1420 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1421 //
93e3992d 1422 Value = NULL;
813acf3a 1423 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
93e3992d 1424 Value = AllocateZeroPool (BufferLen);
1425 ASSERT (Value != NULL);
813acf3a 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);
36fe40c2 1432 BufToHexString (Value, &BufferLen, Src, StorageWidth);
813acf3a 1433 ToLower (Value);
93e3992d 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" ||
813acf3a 1443 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
93e3992d 1444 //
1445 if (IsBufferStorage) {
1446 Length = StrLen (Question->BlockName) + 7;
1447 } else {
1448 Length = StrLen (Question->VariableName) + 2;
1449 }
1450 if (!IsBufferStorage && IsString) {
813acf3a 1451 Length += (StrLen ((CHAR16 *) Src) * 4);
93e3992d 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) {
813acf3a 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);
93e3992d 1476 } else {
813acf3a 1477 BufferLen = StorageWidth * 2 + 1;
36fe40c2 1478 BufToHexString (Value, &BufferLen, Src, StorageWidth);
813acf3a 1479 ToLower (Value);
93e3992d 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**/
1520EFI_STATUS
1521ValidateQuestion (
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**/
1587EFI_STATUS
1588NoSubmitCheck (
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**/
1622EFI_STATUS
1623SubmitForm (
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**/
1706EFI_STATUS
1707GetQuestionDefault (
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**/
1877EFI_STATUS
1878ExtractFormDefault (
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**/
1923EFI_STATUS
1924LoadFormConfig (
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**/
1961EFI_STATUS
1962LoadStorage (
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**/
2022EFI_STATUS
2023InitializeCurrentSetting (
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**/
2085EFI_STATUS
2086GetIfrBinaryData (
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**/
2228EFI_STATUS
2229InitializeFormSet (
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}