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