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