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