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