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