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