2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
5 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
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.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
32 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
33 EFI_HII_STRING_PROTOCOL
*mHiiString
;
34 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
35 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
37 UINTN gBrowserContextCount
= 0;
38 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
39 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
40 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
42 BANNER_DATA
*gBannerData
;
43 EFI_HII_HANDLE gFrontPageHandle
;
45 UINTN gFunctionKeySetting
;
46 BOOLEAN gResetRequired
;
47 EFI_HII_HANDLE gHiiHandle
;
49 EFI_SCREEN_DESCRIPTOR gScreenDimensions
;
50 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
51 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
52 EXIT_HANDLER ExitHandlerFunction
= NULL
;
56 // Browser Global Strings
59 CHAR16
*gDiscardFailed
;
60 CHAR16
*gDefaultFailed
;
62 CHAR16
*gEnterCommitString
;
63 CHAR16
*gEnterEscapeString
;
64 CHAR16
*gEscapeString
;
65 CHAR16
*gMoveHighlight
;
66 CHAR16
*gMakeSelection
;
67 CHAR16
*gDecNumericInput
;
68 CHAR16
*gHexNumericInput
;
69 CHAR16
*gToggleCheckBox
;
70 CHAR16
*gPromptForData
;
71 CHAR16
*gPromptForPassword
;
72 CHAR16
*gPromptForNewPassword
;
73 CHAR16
*gConfirmPassword
;
74 CHAR16
*gConfirmError
;
75 CHAR16
*gPassowordInvalid
;
84 CHAR16
*gAdjustNumber
;
86 CHAR16
*gOptionMismatch
;
87 CHAR16
*gFormSuppress
;
88 CHAR16
*gProtocolNotFound
;
90 CHAR16
*mUnknownString
= L
"!";
92 CHAR16 gPromptBlockWidth
;
93 CHAR16 gOptionBlockWidth
;
94 CHAR16 gHelpBlockWidth
;
96 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
97 EFI_GUID gSetupBrowserGuid
= {
98 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
101 FORM_BROWSER_FORMSET
*gOldFormSet
= NULL
;
103 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
123 NONE_FUNCTION_KEY_SETTING
144 NONE_FUNCTION_KEY_SETTING
165 NONE_FUNCTION_KEY_SETTING
168 // BMM File Explorer FormSet.
186 NONE_FUNCTION_KEY_SETTING
191 This is the routine which an external caller uses to direct the browser
192 where to obtain it's information.
195 @param This The Form Browser protocol instanse.
196 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
197 display a list of the formsets for the handles specified.
198 @param HandleCount The number of Handles specified in Handle.
199 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
200 field in the EFI_IFR_FORM_SET op-code for the specified
201 forms-based package. If FormSetGuid is NULL, then this
202 function will display the first found forms package.
203 @param FormId This field specifies which EFI_IFR_FORM to render as the first
204 displayable page. If this field has a value of 0x0000, then
205 the forms browser will render the specified forms in their encoded order.
206 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
208 @param ActionRequest Points to the action recommended by the form.
210 @retval EFI_SUCCESS The function completed successfully.
211 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
212 @retval EFI_NOT_FOUND No valid forms could be found to display.
218 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
219 IN EFI_HII_HANDLE
*Handles
,
220 IN UINTN HandleCount
,
221 IN EFI_GUID
*FormSetGuid
, OPTIONAL
222 IN UINT16 FormId
, OPTIONAL
223 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
224 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
228 UI_MENU_SELECTION
*Selection
;
230 FORM_BROWSER_FORMSET
*FormSet
;
234 // Calculate total number of Register HotKeys.
237 Link
= GetFirstNode (&gBrowserHotKeyList
);
238 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
239 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
243 // Show three HotKeys help information on one ROW.
245 gFooterHeight
= FOOTER_HEIGHT
+ (Index
/ 3);
248 // Clean the history menu list.
250 InitializeListHead (&gMenuList
);
253 // Save globals used by SendForm()
255 SaveBrowserContext ();
257 gResetRequired
= FALSE
;
258 Status
= EFI_SUCCESS
;
259 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
262 // Seed the dimensions in the global
264 gST
->ConOut
->QueryMode (
266 gST
->ConOut
->Mode
->Mode
,
267 &gScreenDimensions
.RightColumn
,
268 &gScreenDimensions
.BottomRow
271 if (ScreenDimensions
!= NULL
) {
273 // Check local dimension vs. global dimension.
275 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
276 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
278 Status
= EFI_INVALID_PARAMETER
;
282 // Local dimension validation.
284 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
285 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
286 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
288 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
289 SCROLL_ARROW_HEIGHT
*
291 FRONT_PAGE_HEADER_HEIGHT
+
296 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
298 Status
= EFI_INVALID_PARAMETER
;
304 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
305 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
306 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
309 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
311 InitializeBrowserStrings ();
314 // Ensure we are in Text mode
316 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
318 for (Index
= 0; Index
< HandleCount
; Index
++) {
319 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
320 ASSERT (Selection
!= NULL
);
322 Selection
->Handle
= Handles
[Index
];
323 if (FormSetGuid
!= NULL
) {
324 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
325 Selection
->FormId
= FormId
;
327 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
331 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
332 ASSERT (FormSet
!= NULL
);
335 // Initialize internal data structures of FormSet
337 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
, TRUE
);
338 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
339 DestroyFormSet (FormSet
);
342 Selection
->FormSet
= FormSet
;
345 // Try to find pre FormSet in the maintain backup list.
347 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
350 // Display this formset
352 gCurrentSelection
= Selection
;
354 Status
= SetupBrowser (Selection
);
356 gCurrentSelection
= NULL
;
358 if (EFI_ERROR (Status
)) {
362 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
364 if (gOldFormSet
!= NULL
) {
366 // If no data is changed, don't need to save current FormSet into the maintain list.
368 if (!IsNvUpdateRequired (gOldFormSet
)) {
369 RemoveEntryList (&gOldFormSet
->Link
);
370 DestroyFormSet (gOldFormSet
);
375 FreePool (Selection
);
378 if (ActionRequest
!= NULL
) {
379 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
380 if (gResetRequired
) {
381 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
385 FreeBrowserStrings ();
386 UiFreeMenuList(&gMenuList
);
388 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
389 gST
->ConOut
->ClearScreen (gST
->ConOut
);
393 // Restore globals used by SendForm()
395 RestoreBrowserContext ();
402 This function is called by a callback handler to retrieve uncommitted state
403 data from the browser.
405 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
407 @param ResultsDataSize A pointer to the size of the buffer associated
409 @param ResultsData A string returned from an IFR browser or
410 equivalent. The results string will have no
411 routing information in them.
412 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
413 (if RetrieveData = TRUE) data from the uncommitted
414 browser state information or set (if RetrieveData
415 = FALSE) data in the uncommitted browser state
417 @param VariableGuid An optional field to indicate the target variable
419 @param VariableName An optional field to indicate the target
420 human-readable variable name.
422 @retval EFI_SUCCESS The results have been distributed or are awaiting
424 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
425 contain the results data.
431 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
432 IN OUT UINTN
*ResultsDataSize
,
433 IN OUT EFI_STRING ResultsData
,
434 IN BOOLEAN RetrieveData
,
435 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
436 IN CONST CHAR16
*VariableName OPTIONAL
441 FORMSET_STORAGE
*Storage
;
442 FORM_BROWSER_FORMSET
*FormSet
;
449 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
450 return EFI_INVALID_PARAMETER
;
453 if (gCurrentSelection
== NULL
) {
454 return EFI_NOT_READY
;
459 FormSet
= gCurrentSelection
->FormSet
;
462 // Find target storage
464 Link
= GetFirstNode (&FormSet
->StorageListHead
);
465 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
466 return EFI_UNSUPPORTED
;
469 if (VariableGuid
!= NULL
) {
471 // Try to find target storage
474 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
475 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
476 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
478 if (CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
479 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
480 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
482 // Buffer storage require both GUID and Name
484 if (VariableName
== NULL
) {
485 return EFI_NOT_FOUND
;
488 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
498 return EFI_NOT_FOUND
;
502 // GUID/Name is not specified, take the first storage in FormSet
504 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
509 // Skip if there is no RequestElement
511 if (Storage
->ElementCount
== 0) {
516 // Generate <ConfigResp>
518 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
519 if (EFI_ERROR (Status
)) {
524 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
526 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
528 BufferSize
= StrSize (StrPtr
);
529 if (*ResultsDataSize
< BufferSize
) {
530 *ResultsDataSize
= BufferSize
;
532 FreePool (ConfigResp
);
533 return EFI_BUFFER_TOO_SMALL
;
536 *ResultsDataSize
= BufferSize
;
537 CopyMem (ResultsData
, StrPtr
, BufferSize
);
539 FreePool (ConfigResp
);
542 // Prepare <ConfigResp>
544 TmpSize
= StrLen (ResultsData
);
545 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
546 ConfigResp
= AllocateZeroPool (BufferSize
);
547 ASSERT (ConfigResp
!= NULL
);
549 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
550 StrCat (ConfigResp
, L
"&");
551 StrCat (ConfigResp
, ResultsData
);
554 // Update Browser uncommited data
556 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
557 if (EFI_ERROR (Status
)) {
566 Initialize Setup Browser driver.
568 @param ImageHandle The image handle.
569 @param SystemTable The system table.
571 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
572 @return Other value if failed to initialize the Setup Browser module.
578 IN EFI_HANDLE ImageHandle
,
579 IN EFI_SYSTEM_TABLE
*SystemTable
583 EFI_INPUT_KEY DefaultHotKey
;
584 EFI_STRING HelpString
;
587 // Locate required Hii relative protocols
589 Status
= gBS
->LocateProtocol (
590 &gEfiHiiDatabaseProtocolGuid
,
592 (VOID
**) &mHiiDatabase
594 ASSERT_EFI_ERROR (Status
);
596 Status
= gBS
->LocateProtocol (
597 &gEfiHiiStringProtocolGuid
,
599 (VOID
**) &mHiiString
601 ASSERT_EFI_ERROR (Status
);
603 Status
= gBS
->LocateProtocol (
604 &gEfiHiiConfigRoutingProtocolGuid
,
606 (VOID
**) &mHiiConfigRouting
608 ASSERT_EFI_ERROR (Status
);
610 Status
= gBS
->LocateProtocol (
611 &gEfiDevicePathFromTextProtocolGuid
,
613 (VOID
**) &mPathFromText
617 // Publish our HII data
619 gHiiHandle
= HiiAddPackages (
625 ASSERT (gHiiHandle
!= NULL
);
628 // Initialize Driver private data
630 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
631 ASSERT (gBannerData
!= NULL
);
634 // Initialize generic help strings.
636 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
637 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
638 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
641 // Install FormBrowser2 protocol
643 mPrivateData
.Handle
= NULL
;
644 Status
= gBS
->InstallProtocolInterface (
645 &mPrivateData
.Handle
,
646 &gEfiFormBrowser2ProtocolGuid
,
647 EFI_NATIVE_INTERFACE
,
648 &mPrivateData
.FormBrowser2
650 ASSERT_EFI_ERROR (Status
);
653 // Install default HotKey F10 for Save
655 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
656 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
657 DefaultHotKey
.ScanCode
= SCAN_F10
;
658 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
659 FreePool (HelpString
);
661 // Install default HotKey F9 for Reset To Defaults
663 DefaultHotKey
.ScanCode
= SCAN_F9
;
664 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
665 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
666 FreePool (HelpString
);
669 // Install FormBrowserEx protocol
671 mPrivateData
.Handle
= NULL
;
672 Status
= gBS
->InstallProtocolInterface (
673 &mPrivateData
.Handle
,
674 &gEfiFormBrowserExProtocolGuid
,
675 EFI_NATIVE_INTERFACE
,
676 &mPrivateData
.FormBrowserEx
678 ASSERT_EFI_ERROR (Status
);
685 Create a new string in HII Package List.
687 @param String The String to be added
688 @param HiiHandle The package list in the HII database to insert the
691 @return The output string.
697 IN EFI_HII_HANDLE HiiHandle
700 EFI_STRING_ID StringId
;
702 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
703 ASSERT (StringId
!= 0);
710 Delete a string from HII Package List.
712 @param StringId Id of the string in HII database.
713 @param HiiHandle The HII package list handle.
715 @retval EFI_SUCCESS The string was deleted successfully.
720 IN EFI_STRING_ID StringId
,
721 IN EFI_HII_HANDLE HiiHandle
726 NullChar
= CHAR_NULL
;
727 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
733 Get the string based on the StringId and HII Package List Handle.
735 @param Token The String's ID.
736 @param HiiHandle The package list in the HII database to search for
737 the specified string.
739 @return The output string.
744 IN EFI_STRING_ID Token
,
745 IN EFI_HII_HANDLE HiiHandle
750 if (HiiHandle
== NULL
) {
754 String
= HiiGetString (HiiHandle
, Token
, NULL
);
755 if (String
== NULL
) {
756 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
757 ASSERT (String
!= NULL
);
759 return (CHAR16
*) String
;
764 Allocate new memory and then copy the Unicode string Source to Destination.
766 @param Dest Location to copy string
767 @param Src String to copy
772 IN OUT CHAR16
**Dest
,
779 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
780 ASSERT (*Dest
!= NULL
);
785 Allocate new memory and concatinate Source on the end of Destination.
787 @param Dest String to added to the end of.
788 @param Src String to concatinate.
793 IN OUT CHAR16
**Dest
,
801 NewStringCpy (Dest
, Src
);
805 TmpSize
= StrSize (*Dest
);
806 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
807 ASSERT (NewString
!= NULL
);
809 StrCpy (NewString
, *Dest
);
810 StrCat (NewString
, Src
);
818 Synchronize or restore Storage's Edit copy and Shadow copy.
820 @param Storage The Storage to be synchronized.
821 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
823 if TRUE, copy the editbuffer to the buffer.
824 if FALSE, copy the buffer to the editbuffer.
829 IN FORMSET_STORAGE
*Storage
,
830 IN BOOLEAN SyncOrRestore
834 NAME_VALUE_NODE
*Node
;
836 switch (Storage
->Type
) {
837 case EFI_HII_VARSTORE_BUFFER
:
838 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
840 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
842 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
846 case EFI_HII_VARSTORE_NAME_VALUE
:
847 Link
= GetFirstNode (&Storage
->NameValueListHead
);
848 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
849 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
852 NewStringCpy (&Node
->Value
, Node
->EditValue
);
854 NewStringCpy (&Node
->EditValue
, Node
->Value
);
857 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
861 case EFI_HII_VARSTORE_EFI_VARIABLE
:
869 Get Value for given Name from a NameValue Storage.
871 @param Storage The NameValue Storage.
872 @param Name The Name.
873 @param Value The retured Value.
874 @param GetValueFrom Where to get source value, from EditValue or Value.
876 @retval EFI_SUCCESS Value found for given Name.
877 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
882 IN FORMSET_STORAGE
*Storage
,
884 IN OUT CHAR16
**Value
,
885 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
889 NAME_VALUE_NODE
*Node
;
891 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
892 return EFI_INVALID_PARAMETER
;
897 Link
= GetFirstNode (&Storage
->NameValueListHead
);
898 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
899 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
901 if (StrCmp (Name
, Node
->Name
) == 0) {
902 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
903 NewStringCpy (Value
, Node
->EditValue
);
905 NewStringCpy (Value
, Node
->Value
);
910 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
913 return EFI_NOT_FOUND
;
918 Set Value of given Name in a NameValue Storage.
920 @param Storage The NameValue Storage.
921 @param Name The Name.
922 @param Value The Value to set.
923 @param SetValueTo Whether update editValue or Value.
925 @retval EFI_SUCCESS Value found for given Name.
926 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
931 IN FORMSET_STORAGE
*Storage
,
934 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
938 NAME_VALUE_NODE
*Node
;
941 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
942 return EFI_INVALID_PARAMETER
;
945 Link
= GetFirstNode (&Storage
->NameValueListHead
);
946 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
947 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
949 if (StrCmp (Name
, Node
->Name
) == 0) {
950 if (SetValueTo
== GetSetValueWithEditBuffer
) {
951 Buffer
= Node
->EditValue
;
953 Buffer
= Node
->Value
;
955 if (Buffer
!= NULL
) {
958 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
959 ASSERT (Buffer
!= NULL
);
960 if (SetValueTo
== GetSetValueWithEditBuffer
) {
961 Node
->EditValue
= Buffer
;
963 Node
->Value
= Buffer
;
968 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
971 return EFI_NOT_FOUND
;
976 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
978 @param Buffer The Storage to be conveted.
979 @param ConfigResp The returned <ConfigResp>.
980 @param SingleForm Whether update data for single form or formset level.
982 @retval EFI_SUCCESS Convert success.
983 @retval EFI_INVALID_PARAMETER Incorrect storage type.
987 StorageToConfigResp (
989 IN CHAR16
**ConfigResp
,
990 IN BOOLEAN SingleForm
996 NAME_VALUE_NODE
*Node
;
997 CHAR16
*ConfigRequest
;
998 FORMSET_STORAGE
*Storage
;
999 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
1001 Status
= EFI_SUCCESS
;
1003 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
1004 Storage
= ConfigInfo
->Storage
;
1005 ConfigRequest
= ConfigInfo
->ConfigRequest
;
1007 Storage
= (FORMSET_STORAGE
*) Buffer
;
1008 ConfigRequest
= Storage
->ConfigRequest
;
1011 switch (Storage
->Type
) {
1012 case EFI_HII_VARSTORE_BUFFER
:
1013 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1014 Status
= mHiiConfigRouting
->BlockToConfig (
1017 Storage
->EditBuffer
,
1024 case EFI_HII_VARSTORE_NAME_VALUE
:
1026 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1028 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1029 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1030 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1032 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1033 NewStringCat (ConfigResp
, L
"&");
1034 NewStringCat (ConfigResp
, Node
->Name
);
1035 NewStringCat (ConfigResp
, L
"=");
1036 NewStringCat (ConfigResp
, Node
->EditValue
);
1038 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1042 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1044 Status
= EFI_INVALID_PARAMETER
;
1053 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1055 @param Storage The Storage to receive the settings.
1056 @param ConfigResp The <ConfigResp> to be converted.
1058 @retval EFI_SUCCESS Convert success.
1059 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1063 ConfigRespToStorage (
1064 IN FORMSET_STORAGE
*Storage
,
1065 IN CHAR16
*ConfigResp
1069 EFI_STRING Progress
;
1075 Status
= EFI_SUCCESS
;
1077 switch (Storage
->Type
) {
1078 case EFI_HII_VARSTORE_BUFFER
:
1079 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1080 BufferSize
= Storage
->Size
;
1081 Status
= mHiiConfigRouting
->ConfigToBlock (
1084 Storage
->EditBuffer
,
1090 case EFI_HII_VARSTORE_NAME_VALUE
:
1091 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1092 if (StrPtr
== NULL
) {
1095 StrPtr
= StrStr (ConfigResp
, L
"&");
1096 while (StrPtr
!= NULL
) {
1100 StrPtr
= StrPtr
+ 1;
1102 StrPtr
= StrStr (StrPtr
, L
"=");
1103 if (StrPtr
== NULL
) {
1111 StrPtr
= StrPtr
+ 1;
1113 StrPtr
= StrStr (StrPtr
, L
"&");
1114 if (StrPtr
!= NULL
) {
1117 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
);
1121 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1123 Status
= EFI_INVALID_PARAMETER
;
1132 Get Question's current Value.
1134 @param FormSet FormSet data structure.
1135 @param Form Form data structure.
1136 @param Question Question to be initialized.
1137 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1139 @retval EFI_SUCCESS The function completed successfully.
1144 IN FORM_BROWSER_FORMSET
*FormSet
,
1145 IN FORM_BROWSER_FORM
*Form
,
1146 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1147 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1156 FORMSET_STORAGE
*Storage
;
1157 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1158 CHAR16
*ConfigRequest
;
1166 BOOLEAN IsBufferStorage
;
1172 Status
= EFI_SUCCESS
;
1176 if (GetValueFrom
>= GetSetValueWithMax
) {
1177 return EFI_INVALID_PARAMETER
;
1181 // Statement don't have storage, skip them
1183 if (Question
->QuestionId
== 0) {
1188 // Question value is provided by an Expression, evaluate it
1190 if (Question
->ValueExpression
!= NULL
) {
1191 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1192 if (!EFI_ERROR (Status
)) {
1193 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1194 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1195 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1196 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1197 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1199 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1200 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1202 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1204 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1205 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1211 // Get question value by read expression.
1213 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1214 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1215 if (!EFI_ERROR (Status
) &&
1216 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1218 // Only update question value to the valid result.
1220 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1221 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1222 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1223 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1224 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1226 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1227 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1229 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1231 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1232 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1238 // Question value is provided by RTC
1240 Storage
= Question
->Storage
;
1241 QuestionValue
= &Question
->HiiValue
.Value
;
1242 if (Storage
== NULL
) {
1244 // It's a Question without storage, or RTC date/time
1246 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1248 // Date and time define the same Flags bit
1250 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1251 case QF_DATE_STORAGE_TIME
:
1252 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1255 case QF_DATE_STORAGE_WAKEUP
:
1256 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1259 case QF_DATE_STORAGE_NORMAL
:
1262 // For date/time without storage
1267 if (EFI_ERROR (Status
)) {
1271 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1272 QuestionValue
->date
.Year
= EfiTime
.Year
;
1273 QuestionValue
->date
.Month
= EfiTime
.Month
;
1274 QuestionValue
->date
.Day
= EfiTime
.Day
;
1276 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1277 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1278 QuestionValue
->time
.Second
= EfiTime
.Second
;
1286 // Question value is provided by EFI variable
1288 StorageWidth
= Question
->StorageWidth
;
1289 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1290 if (Question
->BufferValue
!= NULL
) {
1291 Dst
= Question
->BufferValue
;
1293 Dst
= (UINT8
*) QuestionValue
;
1296 Status
= gRT
->GetVariable (
1297 Question
->VariableName
,
1304 // Always return success, even this EFI variable doesn't exist
1310 // Question Value is provided by Buffer Storage or NameValue Storage
1312 if (Question
->BufferValue
!= NULL
) {
1314 // This Question is password or orderedlist
1316 Dst
= Question
->BufferValue
;
1319 // Other type of Questions
1321 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1324 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1325 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1326 IsBufferStorage
= TRUE
;
1328 IsBufferStorage
= FALSE
;
1330 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1331 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1332 if (IsBufferStorage
) {
1333 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1335 // Copy from storage Edit buffer
1337 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1340 // Copy from storage Edit buffer
1342 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1346 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1347 if (EFI_ERROR (Status
)) {
1351 ASSERT (Value
!= NULL
);
1352 LengthStr
= StrLen (Value
);
1353 Status
= EFI_SUCCESS
;
1356 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1357 // Add string tail char L'\0' into Length
1359 Length
= StorageWidth
+ sizeof (CHAR16
);
1360 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1361 Status
= EFI_BUFFER_TOO_SMALL
;
1363 StringPtr
= (CHAR16
*) Dst
;
1364 ZeroMem (TemStr
, sizeof (TemStr
));
1365 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1366 StrnCpy (TemStr
, Value
+ Index
, 4);
1367 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1370 // Add tailing L'\0' character
1372 StringPtr
[Index
/4] = L
'\0';
1375 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1376 Status
= EFI_BUFFER_TOO_SMALL
;
1378 ZeroMem (TemStr
, sizeof (TemStr
));
1379 for (Index
= 0; Index
< LengthStr
; Index
++) {
1380 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1381 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1382 if ((Index
& 1) == 0) {
1383 Dst
[Index
/2] = DigitUint8
;
1385 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1394 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1396 // Request current settings from Configuration Driver
1398 if (FormSet
->ConfigAccess
== NULL
) {
1399 return EFI_NOT_FOUND
;
1403 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1404 // <ConfigHdr> + "&" + <VariableName>
1406 if (IsBufferStorage
) {
1407 Length
= StrLen (Storage
->ConfigHdr
);
1408 Length
+= StrLen (Question
->BlockName
);
1410 Length
= StrLen (Storage
->ConfigHdr
);
1411 Length
+= StrLen (Question
->VariableName
) + 1;
1413 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1414 ASSERT (ConfigRequest
!= NULL
);
1416 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1417 if (IsBufferStorage
) {
1418 StrCat (ConfigRequest
, Question
->BlockName
);
1420 StrCat (ConfigRequest
, L
"&");
1421 StrCat (ConfigRequest
, Question
->VariableName
);
1424 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1425 FormSet
->ConfigAccess
,
1430 FreePool (ConfigRequest
);
1431 if (EFI_ERROR (Status
)) {
1436 // Skip <ConfigRequest>
1438 if (IsBufferStorage
) {
1439 Value
= StrStr (Result
, L
"&VALUE");
1440 if (Value
== NULL
) {
1442 return EFI_NOT_FOUND
;
1449 Value
= Result
+ Length
;
1451 if (*Value
!= '=') {
1453 return EFI_NOT_FOUND
;
1456 // Skip '=', point to value
1461 // Suppress <AltResp> if any
1464 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1469 LengthStr
= StrLen (Value
);
1470 Status
= EFI_SUCCESS
;
1471 if (!IsBufferStorage
&& IsString
) {
1473 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1474 // Add string tail char L'\0' into Length
1476 Length
= StorageWidth
+ sizeof (CHAR16
);
1477 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1478 Status
= EFI_BUFFER_TOO_SMALL
;
1480 StringPtr
= (CHAR16
*) Dst
;
1481 ZeroMem (TemStr
, sizeof (TemStr
));
1482 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1483 StrnCpy (TemStr
, Value
+ Index
, 4);
1484 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1487 // Add tailing L'\0' character
1489 StringPtr
[Index
/4] = L
'\0';
1492 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1493 Status
= EFI_BUFFER_TOO_SMALL
;
1495 ZeroMem (TemStr
, sizeof (TemStr
));
1496 for (Index
= 0; Index
< LengthStr
; Index
++) {
1497 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1498 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1499 if ((Index
& 1) == 0) {
1500 Dst
[Index
/2] = DigitUint8
;
1502 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1508 if (EFI_ERROR (Status
)) {
1512 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1514 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1515 if (TemBuffer
== NULL
) {
1516 Status
= EFI_OUT_OF_RESOURCES
;
1519 Length
= Storage
->Size
;
1520 Status
= gRT
->GetVariable (
1527 if (EFI_ERROR (Status
)) {
1528 FreePool (TemBuffer
);
1532 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1534 FreePool (TemBuffer
);
1538 // Synchronize Edit Buffer
1540 if (IsBufferStorage
) {
1541 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1543 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
);
1546 if (Result
!= NULL
) {
1556 Save Question Value to edit copy(cached) or Storage(uncached).
1558 @param FormSet FormSet data structure.
1559 @param Form Form data structure.
1560 @param Question Pointer to the Question.
1561 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1563 @retval EFI_SUCCESS The function completed successfully.
1568 IN FORM_BROWSER_FORMSET
*FormSet
,
1569 IN FORM_BROWSER_FORM
*Form
,
1570 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1571 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1581 FORMSET_STORAGE
*Storage
;
1582 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1587 BOOLEAN IsBufferStorage
;
1594 Status
= EFI_SUCCESS
;
1596 if (SetValueTo
>= GetSetValueWithMax
) {
1597 return EFI_INVALID_PARAMETER
;
1601 // Statement don't have storage, skip them
1603 if (Question
->QuestionId
== 0) {
1608 // If Question value is provided by an Expression, then it is read only
1610 if (Question
->ValueExpression
!= NULL
) {
1615 // Before set question value, evaluate its write expression.
1617 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1618 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1619 if (EFI_ERROR (Status
)) {
1625 // Question value is provided by RTC
1627 Storage
= Question
->Storage
;
1628 QuestionValue
= &Question
->HiiValue
.Value
;
1629 if (Storage
== NULL
) {
1631 // It's a Question without storage, or RTC date/time
1633 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1635 // Date and time define the same Flags bit
1637 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1638 case QF_DATE_STORAGE_TIME
:
1639 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1642 case QF_DATE_STORAGE_WAKEUP
:
1643 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1646 case QF_DATE_STORAGE_NORMAL
:
1649 // For date/time without storage
1654 if (EFI_ERROR (Status
)) {
1658 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1659 EfiTime
.Year
= QuestionValue
->date
.Year
;
1660 EfiTime
.Month
= QuestionValue
->date
.Month
;
1661 EfiTime
.Day
= QuestionValue
->date
.Day
;
1663 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1664 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1665 EfiTime
.Second
= QuestionValue
->time
.Second
;
1668 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1669 Status
= gRT
->SetTime (&EfiTime
);
1671 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1679 // Question value is provided by EFI variable
1681 StorageWidth
= Question
->StorageWidth
;
1682 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1683 if (Question
->BufferValue
!= NULL
) {
1684 Src
= Question
->BufferValue
;
1686 Src
= (UINT8
*) QuestionValue
;
1689 Status
= gRT
->SetVariable (
1690 Question
->VariableName
,
1692 Storage
->Attributes
,
1700 // Question Value is provided by Buffer Storage or NameValue Storage
1702 if (Question
->BufferValue
!= NULL
) {
1703 Src
= Question
->BufferValue
;
1705 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1708 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1709 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1710 IsBufferStorage
= TRUE
;
1712 IsBufferStorage
= FALSE
;
1714 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1716 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1717 if (IsBufferStorage
) {
1718 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1720 // Copy to storage edit buffer
1722 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1723 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1725 // Copy to storage edit buffer
1727 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1732 // Allocate enough string buffer.
1735 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1736 Value
= AllocateZeroPool (BufferLen
);
1737 ASSERT (Value
!= NULL
);
1739 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1741 TemName
= (CHAR16
*) Src
;
1743 for (; *TemName
!= L
'\0'; TemName
++) {
1744 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1747 BufferLen
= StorageWidth
* 2 + 1;
1748 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1749 ASSERT (Value
!= NULL
);
1751 // Convert Buffer to Hex String
1753 TemBuffer
= Src
+ StorageWidth
- 1;
1755 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1756 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1760 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
);
1763 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1764 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1766 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1767 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1769 if (IsBufferStorage
) {
1770 Length
= StrLen (Question
->BlockName
) + 7;
1772 Length
= StrLen (Question
->VariableName
) + 2;
1774 if (!IsBufferStorage
&& IsString
) {
1775 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1777 Length
+= (StorageWidth
* 2);
1779 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1780 ASSERT (ConfigResp
!= NULL
);
1782 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1783 if (IsBufferStorage
) {
1784 StrCat (ConfigResp
, Question
->BlockName
);
1785 StrCat (ConfigResp
, L
"&VALUE=");
1787 StrCat (ConfigResp
, L
"&");
1788 StrCat (ConfigResp
, Question
->VariableName
);
1789 StrCat (ConfigResp
, L
"=");
1792 Value
= ConfigResp
+ StrLen (ConfigResp
);
1794 if (!IsBufferStorage
&& IsString
) {
1796 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1798 TemName
= (CHAR16
*) Src
;
1800 for (; *TemName
!= L
'\0'; TemName
++) {
1801 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1805 // Convert Buffer to Hex String
1807 TemBuffer
= Src
+ StorageWidth
- 1;
1809 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1810 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1815 // Convert to lower char.
1817 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1818 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1819 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1824 // Submit Question Value to Configuration Driver
1826 if (FormSet
->ConfigAccess
!= NULL
) {
1827 Status
= FormSet
->ConfigAccess
->RouteConfig (
1828 FormSet
->ConfigAccess
,
1832 if (EFI_ERROR (Status
)) {
1833 FreePool (ConfigResp
);
1837 FreePool (ConfigResp
);
1839 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1841 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1842 if (TemBuffer
== NULL
) {
1843 Status
= EFI_OUT_OF_RESOURCES
;
1846 Length
= Storage
->Size
;
1847 Status
= gRT
->GetVariable (
1855 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1857 Status
= gRT
->SetVariable (
1860 Storage
->Attributes
,
1864 FreePool (TemBuffer
);
1865 if (EFI_ERROR (Status
)){
1870 // Sync storage, from editbuffer to buffer.
1872 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1880 Perform inconsistent check for a Form.
1882 @param FormSet FormSet data structure.
1883 @param Form Form data structure.
1884 @param Question The Question to be validated.
1885 @param Type Validation type: InConsistent or NoSubmit
1887 @retval EFI_SUCCESS Form validation pass.
1888 @retval other Form validation failed.
1893 IN FORM_BROWSER_FORMSET
*FormSet
,
1894 IN FORM_BROWSER_FORM
*Form
,
1895 IN FORM_BROWSER_STATEMENT
*Question
,
1901 LIST_ENTRY
*ListHead
;
1904 FORM_EXPRESSION
*Expression
;
1906 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1907 ListHead
= &Question
->InconsistentListHead
;
1908 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1909 ListHead
= &Question
->NoSubmitListHead
;
1911 return EFI_UNSUPPORTED
;
1914 Link
= GetFirstNode (ListHead
);
1915 while (!IsNull (ListHead
, Link
)) {
1916 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1919 // Evaluate the expression
1921 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1922 if (EFI_ERROR (Status
)) {
1926 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1928 // Condition meet, show up error message
1930 if (Expression
->Error
!= 0) {
1931 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1933 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1934 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1938 return EFI_NOT_READY
;
1941 Link
= GetNextNode (ListHead
, Link
);
1949 Perform NoSubmit check for each Form in FormSet.
1951 @param FormSet FormSet data structure.
1952 @param CurrentForm Current input form data structure.
1954 @retval EFI_SUCCESS Form validation pass.
1955 @retval other Form validation failed.
1960 IN FORM_BROWSER_FORMSET
*FormSet
,
1961 IN FORM_BROWSER_FORM
*CurrentForm
1966 FORM_BROWSER_STATEMENT
*Question
;
1967 FORM_BROWSER_FORM
*Form
;
1968 LIST_ENTRY
*LinkForm
;
1970 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1971 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1972 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1973 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1975 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
1979 Link
= GetFirstNode (&Form
->StatementListHead
);
1980 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1981 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1983 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
1984 if (EFI_ERROR (Status
)) {
1988 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1996 Fill storage's edit copy with settings requested from Configuration Driver.
1998 @param FormSet FormSet data structure.
1999 @param ConfigInfo The config info related to this form.
2000 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2001 editbuffer to buffer
2002 if TRUE, copy the editbuffer to the buffer.
2003 if FALSE, copy the buffer to the editbuffer.
2005 @retval EFI_SUCCESS The function completed successfully.
2009 SynchronizeStorageForForm (
2010 IN FORM_BROWSER_FORMSET
*FormSet
,
2011 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2012 IN BOOLEAN SyncOrRestore
2016 EFI_STRING Progress
;
2020 NAME_VALUE_NODE
*Node
;
2024 Status
= EFI_SUCCESS
;
2026 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2027 return EFI_NOT_FOUND
;
2030 if (ConfigInfo
->ElementCount
== 0) {
2032 // Skip if there is no RequestElement
2037 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2038 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2039 BufferSize
= ConfigInfo
->Storage
->Size
;
2041 if (SyncOrRestore
) {
2042 Src
= ConfigInfo
->Storage
->EditBuffer
;
2043 Dst
= ConfigInfo
->Storage
->Buffer
;
2045 Src
= ConfigInfo
->Storage
->Buffer
;
2046 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2049 Status
= mHiiConfigRouting
->BlockToConfig(
2051 ConfigInfo
->ConfigRequest
,
2057 if (EFI_ERROR (Status
)) {
2061 Status
= mHiiConfigRouting
->ConfigToBlock (
2068 if (Result
!= NULL
) {
2071 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2072 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2073 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2074 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2076 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2077 if (SyncOrRestore
) {
2078 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2080 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2084 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2092 When discard the question value, call the callback function with Changed type
2093 to inform the hii driver.
2095 @param FormSet FormSet data structure.
2096 @param Form Form data structure.
2100 SendDiscardInfoToDriver (
2101 IN FORM_BROWSER_FORMSET
*FormSet
,
2102 IN FORM_BROWSER_FORM
*Form
2106 FORM_BROWSER_STATEMENT
*Question
;
2108 EFI_HII_VALUE HiiValue
;
2110 BOOLEAN ValueChanged
;
2111 EFI_IFR_TYPE_VALUE
*TypeValue
;
2112 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2114 ValueChanged
= FALSE
;
2117 if(!Form
->NvUpdateRequired
) {
2121 Link
= GetFirstNode (&Form
->StatementListHead
);
2122 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2123 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2124 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2126 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2130 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2134 if (Question
->BufferValue
!= NULL
) {
2135 BufferValue
= AllocateZeroPool (Question
->StorageWidth
);
2136 ASSERT (BufferValue
!= NULL
);
2137 CopyMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
);
2139 HiiValue
.Type
= Question
->HiiValue
.Type
;
2140 CopyMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2143 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
2144 if (EFI_ERROR (Status
)) {
2145 if (BufferValue
!= NULL
) {
2146 FreePool (BufferValue
);
2152 if (Question
->BufferValue
!= NULL
) {
2153 if (CompareMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
)) {
2154 ValueChanged
= TRUE
;
2157 if (CompareMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
))) {
2158 ValueChanged
= TRUE
;
2162 if (BufferValue
!= NULL
) {
2163 FreePool (BufferValue
);
2167 if (!ValueChanged
) {
2171 ValueChanged
= FALSE
;
2173 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2174 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2176 TypeValue
= &Question
->HiiValue
.Value
;
2179 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2180 FormSet
->ConfigAccess
->Callback (
2181 FormSet
->ConfigAccess
,
2182 EFI_BROWSER_ACTION_CHANGED
,
2183 Question
->QuestionId
,
2184 Question
->HiiValue
.Type
,
2192 Validate the FormSet. If the formset is not validate, remove it from the list.
2194 @param FormSet The input FormSet which need to validate.
2196 @retval TRUE The handle is validate.
2197 @retval FALSE The handle is invalidate.
2202 FORM_BROWSER_FORMSET
*FormSet
2205 EFI_HII_HANDLE
*HiiHandles
;
2209 ASSERT (FormSet
!= NULL
);
2212 // Get all the Hii handles
2214 HiiHandles
= HiiGetHiiHandles (NULL
);
2215 ASSERT (HiiHandles
!= NULL
);
2218 // Search for formset of each class type
2220 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2221 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2228 RemoveEntryList (&FormSet
->Link
);
2229 DestroyFormSet (FormSet
);
2232 FreePool (HiiHandles
);
2238 Discard data based on the input setting scope (Form, FormSet or System).
2240 @param FormSet FormSet data structure.
2241 @param Form Form data structure.
2242 @param SettingScope Setting Scope for Discard action.
2244 @retval EFI_SUCCESS The function completed successfully.
2245 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2250 IN FORM_BROWSER_FORMSET
*FormSet
,
2251 IN FORM_BROWSER_FORM
*Form
,
2252 IN BROWSER_SETTING_SCOPE SettingScope
2256 FORMSET_STORAGE
*Storage
;
2257 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2258 FORM_BROWSER_FORMSET
*LocalFormSet
;
2261 // Check the supported setting level.
2263 if (SettingScope
>= MaxLevel
) {
2264 return EFI_UNSUPPORTED
;
2267 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2269 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2270 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2271 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2272 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2274 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2279 // Skip if there is no RequestElement
2281 if (ConfigInfo
->ElementCount
== 0) {
2286 // Prepare <ConfigResp>
2288 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2291 // Call callback with Changed type to inform the driver.
2293 SendDiscardInfoToDriver (FormSet
, Form
);
2296 Form
->NvUpdateRequired
= FALSE
;
2297 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2300 // Discard Buffer storage or Name/Value storage
2302 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2303 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2304 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2305 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2307 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2312 // Skip if there is no RequestElement
2314 if (Storage
->ElementCount
== 0) {
2318 SynchronizeStorage(Storage
, FALSE
);
2321 Link
= GetFirstNode (&FormSet
->FormListHead
);
2322 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2323 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2324 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2327 // Call callback with Changed type to inform the driver.
2329 SendDiscardInfoToDriver (FormSet
, Form
);
2332 UpdateNvInfoInForm (FormSet
, FALSE
);
2333 } else if (SettingScope
== SystemLevel
) {
2335 // System Level Discard.
2339 // Discard changed value for each FormSet in the maintain list.
2341 Link
= GetFirstNode (&gBrowserFormSetList
);
2342 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2343 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2344 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2345 if (!ValidateFormSet(LocalFormSet
)) {
2348 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2349 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2351 // Remove maintain backup list after discard except for the current using FormSet.
2353 RemoveEntryList (&LocalFormSet
->Link
);
2354 DestroyFormSet (LocalFormSet
);
2363 Submit data based on the input Setting level (Form, FormSet or System).
2365 @param FormSet FormSet data structure.
2366 @param Form Form data structure.
2367 @param SettingScope Setting Scope for Submit action.
2369 @retval EFI_SUCCESS The function completed successfully.
2370 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2375 IN FORM_BROWSER_FORMSET
*FormSet
,
2376 IN FORM_BROWSER_FORM
*Form
,
2377 IN BROWSER_SETTING_SCOPE SettingScope
2382 EFI_STRING ConfigResp
;
2383 EFI_STRING Progress
;
2384 FORMSET_STORAGE
*Storage
;
2387 FORM_BROWSER_FORMSET
*LocalFormSet
;
2388 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2391 // Check the supported setting level.
2393 if (SettingScope
>= MaxLevel
) {
2394 return EFI_UNSUPPORTED
;
2398 // Validate the Form by NoSubmit check
2400 Status
= EFI_SUCCESS
;
2401 if (SettingScope
== FormLevel
) {
2402 Status
= NoSubmitCheck (FormSet
, Form
);
2403 } else if (SettingScope
== FormSetLevel
) {
2404 Status
= NoSubmitCheck (FormSet
, NULL
);
2406 if (EFI_ERROR (Status
)) {
2410 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2412 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2413 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2414 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2415 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2417 Storage
= ConfigInfo
->Storage
;
2418 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2423 // Skip if there is no RequestElement
2425 if (ConfigInfo
->ElementCount
== 0) {
2430 // 1. Prepare <ConfigResp>
2432 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2433 if (EFI_ERROR (Status
)) {
2438 // 2. Set value to hii driver or efi variable.
2440 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2441 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2443 // Send <ConfigResp> to Configuration Driver
2445 if (FormSet
->ConfigAccess
!= NULL
) {
2446 Status
= FormSet
->ConfigAccess
->RouteConfig (
2447 FormSet
->ConfigAccess
,
2451 if (EFI_ERROR (Status
)) {
2452 FreePool (ConfigResp
);
2456 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2458 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2459 if (TmpBuf
== NULL
) {
2460 Status
= EFI_OUT_OF_RESOURCES
;
2464 BufferSize
= Storage
->Size
;
2465 Status
= gRT
->GetVariable (
2472 if (EFI_ERROR (Status
)) {
2474 FreePool (ConfigResp
);
2477 ASSERT (BufferSize
== Storage
->Size
);
2478 Status
= mHiiConfigRouting
->ConfigToBlock (
2485 if (EFI_ERROR (Status
)) {
2487 FreePool (ConfigResp
);
2491 Status
= gRT
->SetVariable (
2494 Storage
->Attributes
,
2499 if (EFI_ERROR (Status
)) {
2500 FreePool (ConfigResp
);
2504 FreePool (ConfigResp
);
2506 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2508 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2512 // 4. Update the NV flag.
2514 Form
->NvUpdateRequired
= FALSE
;
2515 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2517 // Submit Buffer storage or Name/Value storage
2519 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2520 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2521 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2522 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2524 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2529 // Skip if there is no RequestElement
2531 if (Storage
->ElementCount
== 0) {
2536 // 1. Prepare <ConfigResp>
2538 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2539 if (EFI_ERROR (Status
)) {
2543 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2544 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2547 // 2. Send <ConfigResp> to Configuration Driver
2549 if (FormSet
->ConfigAccess
!= NULL
) {
2550 Status
= FormSet
->ConfigAccess
->RouteConfig (
2551 FormSet
->ConfigAccess
,
2555 if (EFI_ERROR (Status
)) {
2556 FreePool (ConfigResp
);
2560 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2562 // 1&2. Set the edit data to the variable.
2565 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2566 if (TmpBuf
== NULL
) {
2567 Status
= EFI_OUT_OF_RESOURCES
;
2570 BufferSize
= Storage
->Size
;
2571 Status
= gRT
->GetVariable (
2578 ASSERT (BufferSize
== Storage
->Size
);
2579 Status
= mHiiConfigRouting
->ConfigToBlock (
2586 if (EFI_ERROR (Status
)) {
2588 FreePool (ConfigResp
);
2592 Status
= gRT
->SetVariable (
2595 Storage
->Attributes
,
2599 if (EFI_ERROR (Status
)) {
2601 FreePool (ConfigResp
);
2606 FreePool (ConfigResp
);
2608 // 3. Config success, update storage shadow Buffer
2610 SynchronizeStorage (Storage
, TRUE
);
2614 // 4. Update the NV flag.
2616 UpdateNvInfoInForm (FormSet
, FALSE
);
2617 } else if (SettingScope
== SystemLevel
) {
2619 // System Level Save.
2623 // Save changed value for each FormSet in the maintain list.
2625 Link
= GetFirstNode (&gBrowserFormSetList
);
2626 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2627 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2628 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2629 if (!ValidateFormSet(LocalFormSet
)) {
2632 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2633 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2635 // Remove maintain backup list after save except for the current using FormSet.
2637 RemoveEntryList (&LocalFormSet
->Link
);
2638 DestroyFormSet (LocalFormSet
);
2647 Get Question default value from AltCfg string.
2649 @param FormSet The form set.
2650 @param Question The question.
2651 @param DefaultId The default Id.
2653 @retval EFI_SUCCESS Question is reset to default value.
2657 GetDefaultValueFromAltCfg (
2658 IN FORM_BROWSER_FORMSET
*FormSet
,
2659 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2663 BOOLEAN IsBufferStorage
;
2666 FORMSET_STORAGE
*Storage
;
2667 CHAR16
*ConfigRequest
;
2680 Status
= EFI_NOT_FOUND
;
2683 ConfigRequest
= NULL
;
2687 Storage
= Question
->Storage
;
2689 if ((Storage
== NULL
) ||
2690 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2691 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2696 // Question Value is provided by Buffer Storage or NameValue Storage
2698 if (Question
->BufferValue
!= NULL
) {
2700 // This Question is password or orderedlist
2702 Dst
= Question
->BufferValue
;
2705 // Other type of Questions
2707 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2710 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2711 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2714 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2715 // <ConfigHdr> + "&" + <VariableName>
2717 if (IsBufferStorage
) {
2718 Length
= StrLen (Storage
->ConfigHdr
);
2719 Length
+= StrLen (Question
->BlockName
);
2721 Length
= StrLen (Storage
->ConfigHdr
);
2722 Length
+= StrLen (Question
->VariableName
) + 1;
2724 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2725 ASSERT (ConfigRequest
!= NULL
);
2727 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2728 if (IsBufferStorage
) {
2729 StrCat (ConfigRequest
, Question
->BlockName
);
2731 StrCat (ConfigRequest
, L
"&");
2732 StrCat (ConfigRequest
, Question
->VariableName
);
2735 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2736 FormSet
->ConfigAccess
,
2741 if (EFI_ERROR (Status
)) {
2746 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2747 // Get the default configuration string according to the default ID.
2749 Status
= mHiiConfigRouting
->GetAltConfig (
2755 &DefaultId
, // it can be NULL to get the current setting.
2760 // The required setting can't be found. So, it is not required to be validated and set.
2762 if (EFI_ERROR (Status
)) {
2767 // Skip <ConfigRequest>
2769 if (IsBufferStorage
) {
2770 Value
= StrStr (ConfigResp
, L
"&VALUE");
2771 ASSERT (Value
!= NULL
);
2777 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2778 ASSERT (Value
!= NULL
);
2780 Value
= Value
+ StrLen (Question
->VariableName
);
2782 if (*Value
!= '=') {
2783 Status
= EFI_NOT_FOUND
;
2787 // Skip '=', point to value
2792 // Suppress <AltResp> if any
2795 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2800 LengthStr
= StrLen (Value
);
2801 if (!IsBufferStorage
&& IsString
) {
2802 StringPtr
= (CHAR16
*) Dst
;
2803 ZeroMem (TemStr
, sizeof (TemStr
));
2804 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2805 StrnCpy (TemStr
, Value
+ Index
, 4);
2806 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2809 // Add tailing L'\0' character
2811 StringPtr
[Index
/4] = L
'\0';
2813 ZeroMem (TemStr
, sizeof (TemStr
));
2814 for (Index
= 0; Index
< LengthStr
; Index
++) {
2815 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2816 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2817 if ((Index
& 1) == 0) {
2818 Dst
[Index
/2] = DigitUint8
;
2820 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2826 if (ConfigRequest
!= NULL
){
2827 FreePool (ConfigRequest
);
2830 if (ConfigResp
!= NULL
) {
2831 FreePool (ConfigResp
);
2834 if (Result
!= NULL
) {
2842 Get default Id value used for browser.
2844 @param DefaultId The default id value used by hii.
2846 @retval Browser used default value.
2850 GetDefaultIdForCallBack (
2854 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2855 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2856 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2857 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2858 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2859 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2860 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2861 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2862 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2863 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2864 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2865 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2872 Reset Question to its default value.
2874 @param FormSet The form set.
2875 @param Form The form.
2876 @param Question The question.
2877 @param DefaultId The Class of the default.
2879 @retval EFI_SUCCESS Question is reset to default value.
2883 GetQuestionDefault (
2884 IN FORM_BROWSER_FORMSET
*FormSet
,
2885 IN FORM_BROWSER_FORM
*Form
,
2886 IN FORM_BROWSER_STATEMENT
*Question
,
2892 QUESTION_DEFAULT
*Default
;
2893 QUESTION_OPTION
*Option
;
2894 EFI_HII_VALUE
*HiiValue
;
2896 EFI_STRING StrValue
;
2897 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2898 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2901 Status
= EFI_NOT_FOUND
;
2905 // Statement don't have storage, skip them
2907 if (Question
->QuestionId
== 0) {
2912 // There are Five ways to specify default value for a Question:
2913 // 1, use call back function (highest priority)
2914 // 2, use ExtractConfig function
2915 // 3, use nested EFI_IFR_DEFAULT
2916 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2917 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2919 HiiValue
= &Question
->HiiValue
;
2922 // Get Question defaut value from call back function.
2924 ConfigAccess
= FormSet
->ConfigAccess
;
2925 Action
= GetDefaultIdForCallBack (DefaultId
);
2926 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2927 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2928 Status
= ConfigAccess
->Callback (
2931 Question
->QuestionId
,
2936 if (!EFI_ERROR (Status
)) {
2942 // Get default value from altcfg string.
2944 if (ConfigAccess
!= NULL
) {
2945 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2946 if (!EFI_ERROR (Status
)) {
2952 // EFI_IFR_DEFAULT has highest priority
2954 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2955 Link
= GetFirstNode (&Question
->DefaultListHead
);
2956 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2957 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2959 if (Default
->DefaultId
== DefaultId
) {
2960 if (Default
->ValueExpression
!= NULL
) {
2962 // Default is provided by an Expression, evaluate it
2964 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2965 if (EFI_ERROR (Status
)) {
2969 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
2970 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
2971 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
2972 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
2973 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
2975 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
2976 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
2978 FreePool (Default
->ValueExpression
->Result
.Buffer
);
2980 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
2981 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2984 // Default value is embedded in EFI_IFR_DEFAULT
2986 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2989 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2990 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
2991 if (StrValue
== NULL
) {
2992 return EFI_NOT_FOUND
;
2994 if (Question
->StorageWidth
> StrSize (StrValue
)) {
2995 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
2997 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3004 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3009 // EFI_ONE_OF_OPTION
3011 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3012 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3014 // OneOfOption could only provide Standard and Manufacturing default
3016 Link
= GetFirstNode (&Question
->OptionListHead
);
3017 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3018 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3019 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3021 if ((Option
->SuppressExpression
!= NULL
) &&
3022 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3026 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3027 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3029 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3038 // EFI_IFR_CHECKBOX - lowest priority
3040 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3041 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3043 // Checkbox could only provide Standard and Manufacturing default
3045 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3046 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3048 HiiValue
->Value
.b
= TRUE
;
3050 HiiValue
->Value
.b
= FALSE
;
3058 // For Questions without default
3060 Status
= EFI_NOT_FOUND
;
3061 switch (Question
->Operand
) {
3062 case EFI_IFR_NUMERIC_OP
:
3064 // Take minimum value as numeric default value
3066 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3067 HiiValue
->Value
.u64
= Question
->Minimum
;
3068 Status
= EFI_SUCCESS
;
3072 case EFI_IFR_ONE_OF_OP
:
3074 // Take first oneof option as oneof's default value
3076 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3077 Link
= GetFirstNode (&Question
->OptionListHead
);
3078 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3079 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3080 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3082 if ((Option
->SuppressExpression
!= NULL
) &&
3083 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3087 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3088 Status
= EFI_SUCCESS
;
3094 case EFI_IFR_ORDERED_LIST_OP
:
3096 // Take option sequence in IFR as ordered list's default value
3099 Link
= GetFirstNode (&Question
->OptionListHead
);
3100 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3101 Status
= EFI_SUCCESS
;
3102 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3103 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3105 if ((Option
->SuppressExpression
!= NULL
) &&
3106 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3110 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3113 if (Index
>= Question
->MaxContainers
) {
3128 Reset Questions to their initial value or default value in a Form, Formset or System.
3130 GetDefaultValueScope parameter decides which questions will reset
3131 to its default value.
3133 @param FormSet FormSet data structure.
3134 @param Form Form data structure.
3135 @param DefaultId The Class of the default.
3136 @param SettingScope Setting Scope for Default action.
3137 @param GetDefaultValueScope Get default value scope.
3138 @param Storage Get default value only for this storage.
3139 @param RetrieveValueFirst Whether call the retrieve call back to
3140 get the initial value before get default
3143 @retval EFI_SUCCESS The function completed successfully.
3144 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3149 IN FORM_BROWSER_FORMSET
*FormSet
,
3150 IN FORM_BROWSER_FORM
*Form
,
3151 IN UINT16 DefaultId
,
3152 IN BROWSER_SETTING_SCOPE SettingScope
,
3153 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3154 IN FORMSET_STORAGE
*Storage OPTIONAL
,
3155 IN BOOLEAN RetrieveValueFirst
3159 LIST_ENTRY
*FormLink
;
3161 FORM_BROWSER_STATEMENT
*Question
;
3162 FORM_BROWSER_FORMSET
*BackUpFormSet
;
3163 FORM_BROWSER_FORMSET
*LocalFormSet
;
3164 EFI_HII_HANDLE
*HiiHandles
;
3168 Status
= EFI_SUCCESS
;
3171 // Check the supported setting level.
3173 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3174 return EFI_UNSUPPORTED
;
3177 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3178 return EFI_UNSUPPORTED
;
3181 if (SettingScope
== FormLevel
) {
3183 // Extract Form default
3185 Link
= GetFirstNode (&Form
->StatementListHead
);
3186 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3187 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3188 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3191 // If get default value only for this storage, check the storage first.
3193 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3198 // If get default value only for no storage question, just skip the question which has storage.
3200 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3205 // If Question is disabled, don't reset it to default
3207 if (Question
->Expression
!= NULL
) {
3208 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3213 if (RetrieveValueFirst
) {
3215 // Call the Retrieve call back to get the initial question value.
3217 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3221 // If not request to get the initial value or get initial value fail, then get default value.
3223 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3224 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3225 if (EFI_ERROR (Status
)) {
3231 // Synchronize Buffer storage's Edit buffer
3233 if ((Question
->Storage
!= NULL
) &&
3234 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3235 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3237 // Update Form NV flag.
3239 Form
->NvUpdateRequired
= TRUE
;
3242 } else if (SettingScope
== FormSetLevel
) {
3243 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3244 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3245 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3246 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3247 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3249 } else if (SettingScope
== SystemLevel
) {
3251 // Open all FormSet by locate HII packages.
3252 // Initiliaze the maintain FormSet to store default data as back up data.
3254 BackUpFormSet
= gOldFormSet
;
3258 // Get all the Hii handles
3260 HiiHandles
= HiiGetHiiHandles (NULL
);
3261 ASSERT (HiiHandles
!= NULL
);
3264 // Search for formset of each class type
3266 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3268 // Check HiiHandles[Index] does exist in global maintain list.
3270 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3275 // Initilize FormSet Setting
3277 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3278 ASSERT (LocalFormSet
!= NULL
);
3279 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3280 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
, FALSE
);
3281 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3282 DestroyFormSet (LocalFormSet
);
3285 Status
= InitializeCurrentSetting (LocalFormSet
);
3286 if (EFI_ERROR (Status
)) {
3287 DestroyFormSet (LocalFormSet
);
3291 // Initilize Questions' Value
3293 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
3294 if (EFI_ERROR (Status
)) {
3295 DestroyFormSet (LocalFormSet
);
3300 // Add FormSet into the maintain list.
3302 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3306 // Free resources, and restore gOldFormSet and gClassOfVfr
3308 FreePool (HiiHandles
);
3309 gOldFormSet
= BackUpFormSet
;
3312 // Set Default Value for each FormSet in the maintain list.
3314 Link
= GetFirstNode (&gBrowserFormSetList
);
3315 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3316 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3317 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3318 if (!ValidateFormSet(LocalFormSet
)) {
3321 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3329 Initialize Question's Edit copy from Storage.
3331 @param Selection Selection contains the information about
3332 the Selection, form and formset to be displayed.
3333 Selection action may be updated in retrieve callback.
3334 If Selection is NULL, only initialize Question value.
3335 @param FormSet FormSet data structure.
3336 @param Form Form data structure.
3338 @retval EFI_SUCCESS The function completed successfully.
3343 IN OUT UI_MENU_SELECTION
*Selection
,
3344 IN FORM_BROWSER_FORMSET
*FormSet
,
3345 IN FORM_BROWSER_FORM
*Form
3350 FORM_BROWSER_STATEMENT
*Question
;
3354 Link
= GetFirstNode (&Form
->StatementListHead
);
3355 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3356 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3359 // Initialize local copy of Value for each Question
3361 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3362 if (EFI_ERROR (Status
)) {
3366 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3367 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3371 // Call the Retrieve call back function for all questions.
3373 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3374 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3376 // Check QuestionValue does exist.
3378 StorageWidth
= Question
->StorageWidth
;
3379 if (Question
->BufferValue
!= NULL
) {
3380 BufferValue
= Question
->BufferValue
;
3382 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3386 // For efivarstore storage, initial question value first.
3388 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3389 Status
= gRT
->GetVariable (
3390 Question
->VariableName
,
3391 &Question
->Storage
->Guid
,
3398 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3401 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3408 Initialize Question's Edit copy from Storage for the whole Formset.
3410 @param Selection Selection contains the information about
3411 the Selection, form and formset to be displayed.
3412 Selection action may be updated in retrieve callback.
3413 If Selection is NULL, only initialize Question value.
3414 @param FormSet FormSet data structure.
3416 @retval EFI_SUCCESS The function completed successfully.
3421 IN OUT UI_MENU_SELECTION
*Selection
,
3422 IN FORM_BROWSER_FORMSET
*FormSet
3427 FORM_BROWSER_FORM
*Form
;
3429 Link
= GetFirstNode (&FormSet
->FormListHead
);
3430 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3431 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3434 // Initialize local copy of Value for each Form
3436 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3437 if (EFI_ERROR (Status
)) {
3441 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3448 Fill storage's edit copy with settings requested from Configuration Driver.
3450 @param FormSet FormSet data structure.
3451 @param Storage Buffer Storage.
3453 @retval EFI_SUCCESS The function completed successfully.
3458 IN FORM_BROWSER_FORMSET
*FormSet
,
3459 IN FORMSET_STORAGE
*Storage
3463 EFI_STRING Progress
;
3467 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3471 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3472 Status
= gRT
->GetVariable (
3476 (UINTN
*)&Storage
->Size
,
3482 if (FormSet
->ConfigAccess
== NULL
) {
3483 return EFI_NOT_FOUND
;
3486 if (Storage
->ElementCount
== 0) {
3488 // Skip if there is no RequestElement
3494 // Request current settings from Configuration Driver
3496 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3497 FormSet
->ConfigAccess
,
3498 Storage
->ConfigRequest
,
3502 if (EFI_ERROR (Status
)) {
3507 // Convert Result from <ConfigAltResp> to <ConfigResp>
3509 StrPtr
= StrStr (Result
, L
"&GUID=");
3510 if (StrPtr
!= NULL
) {
3514 Status
= ConfigRespToStorage (Storage
, Result
);
3521 Copy uncommitted data from source Storage to destination Storage.
3523 @param Dst Target Storage for uncommitted data.
3524 @param Src Source Storage for uncommitted data.
3526 @retval EFI_SUCCESS The function completed successfully.
3527 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
3532 IN OUT FORMSET_STORAGE
*Dst
,
3533 IN FORMSET_STORAGE
*Src
3537 NAME_VALUE_NODE
*Node
;
3539 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
3540 return EFI_INVALID_PARAMETER
;
3543 switch (Src
->Type
) {
3544 case EFI_HII_VARSTORE_BUFFER
:
3545 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3546 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
3547 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
3550 case EFI_HII_VARSTORE_NAME_VALUE
:
3551 Link
= GetFirstNode (&Src
->NameValueListHead
);
3552 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
3553 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3555 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, GetSetValueWithEditBuffer
);
3556 SetValueByName (Dst
, Node
->Name
, Node
->Value
, GetSetValueWithBuffer
);
3558 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
3562 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3571 Get old question value from the saved formset.
3573 @param Statement The question which need to get old question value.
3574 @param OldFormSet FormSet data structure saved in the list.
3578 GetOldQuestionValue (
3579 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
3580 IN FORM_BROWSER_FORMSET
*OldFormSet
3583 LIST_ENTRY
*FormLink
;
3585 FORM_BROWSER_STATEMENT
*Question
;
3586 FORM_BROWSER_FORM
*Form
;
3588 FormLink
= GetFirstNode (&OldFormSet
->FormListHead
);
3589 while (!IsNull (&OldFormSet
->FormListHead
, FormLink
)) {
3590 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3591 FormLink
= GetNextNode (&OldFormSet
->FormListHead
, FormLink
);
3593 Link
= GetFirstNode (&Form
->StatementListHead
);
3594 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3595 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3596 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3598 if (Question
->QuestionId
!= Statement
->QuestionId
) {
3602 CopyMem (&Statement
->HiiValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3609 Get old question value from the saved formset, all these questions not have
3612 @param FormSet FormSet data structure which is used now.
3613 @param OldFormSet FormSet data structure saved in the list.
3617 CopyOldValueForNoStorageQst (
3618 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
3619 IN FORM_BROWSER_FORMSET
*OldFormSet
3622 LIST_ENTRY
*FormLink
;
3624 FORM_BROWSER_STATEMENT
*Question
;
3625 FORM_BROWSER_FORM
*Form
;
3627 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3628 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3629 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3630 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3632 Link
= GetFirstNode (&Form
->StatementListHead
);
3633 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3634 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3635 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3637 if (Question
->Storage
== NULL
) {
3638 GetOldQuestionValue (Question
, OldFormSet
);
3645 Get current setting of Questions.
3647 @param FormSet FormSet data structure.
3649 @retval EFI_SUCCESS The function completed successfully.
3653 InitializeCurrentSetting (
3654 IN OUT FORM_BROWSER_FORMSET
*FormSet
3659 FORMSET_STORAGE
*Storage
;
3660 FORMSET_STORAGE
*StorageSrc
;
3661 FORMSET_STORAGE
*OldStorage
;
3662 FORM_BROWSER_FORM
*Form
;
3663 FORM_BROWSER_FORM
*Form2
;
3667 // Extract default from IFR binary for no storage questions.
3669 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
3672 // Request current settings from Configuration Driver
3674 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3675 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3676 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3679 if (gOldFormSet
!= NULL
) {
3681 // Try to find the Storage in backup formset gOldFormSet
3683 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3684 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3685 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3687 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3688 OldStorage
= StorageSrc
;
3692 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3696 if (OldStorage
== NULL
) {
3698 // Storage is not found in backup formset, request it from ConfigDriver
3700 Status
= LoadStorage (FormSet
, Storage
);
3702 if (EFI_ERROR (Status
)) {
3704 // If get last time changed value failed, extract default from IFR binary
3706 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3708 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3709 // in current situation.
3711 UpdateNvInfoInForm (FormSet
, FALSE
);
3715 // Now Edit Buffer is filled with default values(lower priority) or current
3716 // settings(higher priority), sychronize it to shadow Buffer
3718 SynchronizeStorage (Storage
, TRUE
);
3721 // Storage found in backup formset, use it
3723 Status
= CopyStorage (Storage
, OldStorage
);
3726 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3730 // If has old formset, get the old nv update status.
3732 if (gOldFormSet
!= NULL
) {
3733 Link
= GetFirstNode (&FormSet
->FormListHead
);
3734 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3735 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3737 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3738 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3739 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3741 if (Form
->FormId
== Form2
->FormId
) {
3742 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3746 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3748 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3757 Fetch the Ifr binary data of a FormSet.
3759 @param Handle PackageList Handle
3760 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3761 specified (NULL or zero GUID), take the first
3762 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3763 found in package list.
3764 On output, GUID of the formset found(if not NULL).
3765 @param BinaryLength The length of the FormSet IFR binary.
3766 @param BinaryData The buffer designed to receive the FormSet.
3768 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3769 BufferLength was updated.
3770 @retval EFI_INVALID_PARAMETER The handle is unknown.
3771 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3772 be found with the requested FormId.
3777 IN EFI_HII_HANDLE Handle
,
3778 IN OUT EFI_GUID
*FormSetGuid
,
3779 OUT UINTN
*BinaryLength
,
3780 OUT UINT8
**BinaryData
3784 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3790 UINT32 PackageListLength
;
3791 EFI_HII_PACKAGE_HEADER PackageHeader
;
3793 UINT8 NumberOfClassGuid
;
3794 BOOLEAN ClassGuidMatch
;
3795 EFI_GUID
*ClassGuid
;
3796 EFI_GUID
*ComparingGuid
;
3800 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3803 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3805 if (FormSetGuid
== NULL
) {
3806 ComparingGuid
= &gZeroGuid
;
3808 ComparingGuid
= FormSetGuid
;
3812 // Get HII PackageList
3815 HiiPackageList
= NULL
;
3816 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3817 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3818 HiiPackageList
= AllocatePool (BufferSize
);
3819 ASSERT (HiiPackageList
!= NULL
);
3821 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3823 if (EFI_ERROR (Status
)) {
3826 ASSERT (HiiPackageList
!= NULL
);
3829 // Get Form package from this HII package List
3831 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3833 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3835 ClassGuidMatch
= FALSE
;
3836 while (Offset
< PackageListLength
) {
3837 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3838 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3840 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3842 // Search FormSet in this Form Package
3844 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3845 while (Offset2
< PackageHeader
.Length
) {
3846 OpCodeData
= Package
+ Offset2
;
3848 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3850 // Try to compare against formset GUID
3852 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3853 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3857 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3859 // Try to compare against formset class GUID
3861 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3862 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3863 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3864 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3865 ClassGuidMatch
= TRUE
;
3869 if (ClassGuidMatch
) {
3872 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3873 ClassGuidMatch
= TRUE
;
3878 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3881 if (Offset2
< PackageHeader
.Length
) {
3883 // Target formset found
3889 Offset
+= PackageHeader
.Length
;
3892 if (Offset
>= PackageListLength
) {
3894 // Form package not found in this Package List
3896 FreePool (HiiPackageList
);
3897 return EFI_NOT_FOUND
;
3900 if (FormSetGuid
!= NULL
) {
3902 // Return the FormSet GUID
3904 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3908 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3909 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3910 // of the Form Package.
3912 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3913 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3915 FreePool (HiiPackageList
);
3917 if (*BinaryData
== NULL
) {
3918 return EFI_OUT_OF_RESOURCES
;
3926 Initialize the internal data structure of a FormSet.
3928 @param Handle PackageList Handle
3929 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3930 specified (NULL or zero GUID), take the first
3931 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3932 found in package list.
3933 On output, GUID of the formset found(if not NULL).
3934 @param FormSet FormSet data structure.
3935 @param UpdateGlobalVar Whether need to update the global variable.
3937 @retval EFI_SUCCESS The function completed successfully.
3938 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3943 IN EFI_HII_HANDLE Handle
,
3944 IN OUT EFI_GUID
*FormSetGuid
,
3945 OUT FORM_BROWSER_FORMSET
*FormSet
,
3946 IN BOOLEAN UpdateGlobalVar
3950 EFI_HANDLE DriverHandle
;
3953 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3954 if (EFI_ERROR (Status
)) {
3958 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3959 FormSet
->HiiHandle
= Handle
;
3960 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3963 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3965 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3966 if (EFI_ERROR (Status
)) {
3969 FormSet
->DriverHandle
= DriverHandle
;
3970 Status
= gBS
->HandleProtocol (
3972 &gEfiHiiConfigAccessProtocolGuid
,
3973 (VOID
**) &FormSet
->ConfigAccess
3975 if (EFI_ERROR (Status
)) {
3977 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3978 // list, then there will be no configuration action required
3980 FormSet
->ConfigAccess
= NULL
;
3984 // Parse the IFR binary OpCodes
3986 Status
= ParseOpCodes (FormSet
);
3987 if (EFI_ERROR (Status
)) {
3992 // If not need to update the global variable, just return.
3994 if (!UpdateGlobalVar
) {
3999 // Set VFR type by FormSet SubClass field
4001 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
4002 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
4003 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
4007 // Set VFR type by FormSet class guid
4009 for (Index
= 0; Index
< 3; Index
++) {
4010 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
4011 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
4016 gFunctionKeySetting
= ENABLE_FUNCTION_KEY_SETTING
;
4018 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
4019 gFrontPageHandle
= FormSet
->HiiHandle
;
4020 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
4024 // Match GUID to find out the function key setting. If match fail, use the default setting.
4026 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
4027 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
4029 // Update the function key setting.
4031 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
4040 Save globals used by previous call to SendForm(). SendForm() may be called from
4041 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4042 So, save globals of previous call to SendForm() and restore them upon exit.
4046 SaveBrowserContext (
4050 BROWSER_CONTEXT
*Context
;
4052 gBrowserContextCount
++;
4053 if (gBrowserContextCount
== 1) {
4055 // This is not reentry of SendForm(), no context to save
4060 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4061 ASSERT (Context
!= NULL
);
4063 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4066 // Save FormBrowser context
4068 Context
->BannerData
= gBannerData
;
4069 Context
->ClassOfVfr
= gClassOfVfr
;
4070 Context
->FunctionKeySetting
= gFunctionKeySetting
;
4071 Context
->ResetRequired
= gResetRequired
;
4072 Context
->Direction
= gDirection
;
4073 Context
->EnterString
= gEnterString
;
4074 Context
->EnterCommitString
= gEnterCommitString
;
4075 Context
->EnterEscapeString
= gEnterEscapeString
;
4076 Context
->EscapeString
= gEscapeString
;
4077 Context
->MoveHighlight
= gMoveHighlight
;
4078 Context
->MakeSelection
= gMakeSelection
;
4079 Context
->DecNumericInput
= gDecNumericInput
;
4080 Context
->HexNumericInput
= gHexNumericInput
;
4081 Context
->ToggleCheckBox
= gToggleCheckBox
;
4082 Context
->PromptForData
= gPromptForData
;
4083 Context
->PromptForPassword
= gPromptForPassword
;
4084 Context
->PromptForNewPassword
= gPromptForNewPassword
;
4085 Context
->ConfirmPassword
= gConfirmPassword
;
4086 Context
->ConfirmError
= gConfirmError
;
4087 Context
->PassowordInvalid
= gPassowordInvalid
;
4088 Context
->PressEnter
= gPressEnter
;
4089 Context
->EmptyString
= gEmptyString
;
4090 Context
->AreYouSure
= gAreYouSure
;
4091 Context
->YesResponse
= gYesResponse
;
4092 Context
->NoResponse
= gNoResponse
;
4093 Context
->MiniString
= gMiniString
;
4094 Context
->PlusString
= gPlusString
;
4095 Context
->MinusString
= gMinusString
;
4096 Context
->AdjustNumber
= gAdjustNumber
;
4097 Context
->SaveChanges
= gSaveChanges
;
4098 Context
->OptionMismatch
= gOptionMismatch
;
4099 Context
->FormSuppress
= gFormSuppress
;
4100 Context
->PromptBlockWidth
= gPromptBlockWidth
;
4101 Context
->OptionBlockWidth
= gOptionBlockWidth
;
4102 Context
->HelpBlockWidth
= gHelpBlockWidth
;
4103 Context
->OldFormSet
= gOldFormSet
;
4104 Context
->MenuRefreshHead
= gMenuRefreshHead
;
4105 Context
->ProtocolNotFound
= gProtocolNotFound
;
4107 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
4108 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
4111 // Insert to FormBrowser context list
4113 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4118 Restore globals used by previous call to SendForm().
4122 RestoreBrowserContext (
4127 BROWSER_CONTEXT
*Context
;
4129 ASSERT (gBrowserContextCount
!= 0);
4130 gBrowserContextCount
--;
4131 if (gBrowserContextCount
== 0) {
4133 // This is not reentry of SendForm(), no context to restore
4138 ASSERT (!IsListEmpty (&gBrowserContextList
));
4140 Link
= GetFirstNode (&gBrowserContextList
);
4141 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4144 // Restore FormBrowser context
4146 gBannerData
= Context
->BannerData
;
4147 gClassOfVfr
= Context
->ClassOfVfr
;
4148 gFunctionKeySetting
= Context
->FunctionKeySetting
;
4149 gResetRequired
= Context
->ResetRequired
;
4150 gDirection
= Context
->Direction
;
4151 gEnterString
= Context
->EnterString
;
4152 gEnterCommitString
= Context
->EnterCommitString
;
4153 gEnterEscapeString
= Context
->EnterEscapeString
;
4154 gEscapeString
= Context
->EscapeString
;
4155 gMoveHighlight
= Context
->MoveHighlight
;
4156 gMakeSelection
= Context
->MakeSelection
;
4157 gDecNumericInput
= Context
->DecNumericInput
;
4158 gHexNumericInput
= Context
->HexNumericInput
;
4159 gToggleCheckBox
= Context
->ToggleCheckBox
;
4160 gPromptForData
= Context
->PromptForData
;
4161 gPromptForPassword
= Context
->PromptForPassword
;
4162 gPromptForNewPassword
= Context
->PromptForNewPassword
;
4163 gConfirmPassword
= Context
->ConfirmPassword
;
4164 gConfirmError
= Context
->ConfirmError
;
4165 gPassowordInvalid
= Context
->PassowordInvalid
;
4166 gPressEnter
= Context
->PressEnter
;
4167 gEmptyString
= Context
->EmptyString
;
4168 gAreYouSure
= Context
->AreYouSure
;
4169 gYesResponse
= Context
->YesResponse
;
4170 gNoResponse
= Context
->NoResponse
;
4171 gMiniString
= Context
->MiniString
;
4172 gPlusString
= Context
->PlusString
;
4173 gMinusString
= Context
->MinusString
;
4174 gAdjustNumber
= Context
->AdjustNumber
;
4175 gSaveChanges
= Context
->SaveChanges
;
4176 gOptionMismatch
= Context
->OptionMismatch
;
4177 gFormSuppress
= Context
->FormSuppress
;
4178 gPromptBlockWidth
= Context
->PromptBlockWidth
;
4179 gOptionBlockWidth
= Context
->OptionBlockWidth
;
4180 gHelpBlockWidth
= Context
->HelpBlockWidth
;
4181 gOldFormSet
= Context
->OldFormSet
;
4182 gMenuRefreshHead
= Context
->MenuRefreshHead
;
4183 gProtocolNotFound
= Context
->ProtocolNotFound
;
4185 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
4186 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
4189 // Remove from FormBrowser context list
4191 RemoveEntryList (&Context
->Link
);
4192 gBS
->FreePool (Context
);
4196 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4198 @param Handle The Hii Handle.
4200 @return the found FormSet context. If no found, NULL will return.
4203 FORM_BROWSER_FORMSET
*
4204 GetFormSetFromHiiHandle (
4205 EFI_HII_HANDLE Handle
4209 FORM_BROWSER_FORMSET
*FormSet
;
4211 Link
= GetFirstNode (&gBrowserFormSetList
);
4212 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4213 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4214 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4215 if (!ValidateFormSet(FormSet
)) {
4218 if (FormSet
->HiiHandle
== Handle
) {
4227 Check whether the input HII handle is the FormSet that is being used.
4229 @param Handle The Hii Handle.
4231 @retval TRUE HII handle is being used.
4232 @retval FALSE HII handle is not being used.
4236 IsHiiHandleInBrowserContext (
4237 EFI_HII_HANDLE Handle
4241 BROWSER_CONTEXT
*Context
;
4244 // HiiHandle is Current FormSet.
4246 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
4251 // Check whether HiiHandle is in BrowserContext.
4253 Link
= GetFirstNode (&gBrowserContextList
);
4254 while (!IsNull (&gBrowserContextList
, Link
)) {
4255 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4256 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
4258 // HiiHandle is in BrowserContext
4262 Link
= GetNextNode (&gBrowserContextList
, Link
);
4269 Find the registered HotKey based on KeyData.
4271 @param[in] KeyData A pointer to a buffer that describes the keystroke
4272 information for the hot key.
4274 @return The registered HotKey context. If no found, NULL will return.
4277 GetHotKeyFromRegisterList (
4278 IN EFI_INPUT_KEY
*KeyData
4282 BROWSER_HOT_KEY
*HotKey
;
4284 Link
= GetFirstNode (&gBrowserHotKeyList
);
4285 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4286 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4287 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4290 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4297 Configure what scope the hot key will impact.
4298 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4299 If no scope is set, the default scope will be FormSet level.
4300 After all registered hot keys are removed, previous Scope can reset to another level.
4302 @param[in] Scope Scope level to be set.
4304 @retval EFI_SUCCESS Scope is set correctly.
4305 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4306 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4312 IN BROWSER_SETTING_SCOPE Scope
4315 if (Scope
>= MaxLevel
) {
4316 return EFI_INVALID_PARAMETER
;
4320 // When no hot key registered in system or on the first setting,
4321 // Scope can be set.
4323 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4324 gBrowserSettingScope
= Scope
;
4325 mBrowserScopeFirstSet
= FALSE
;
4326 } else if (Scope
!= gBrowserSettingScope
) {
4327 return EFI_UNSUPPORTED
;
4334 Register the hot key with its browser action, or unregistered the hot key.
4335 Only support hot key that is not printable character (control key, function key, etc.).
4336 If the action value is zero, the hot key will be unregistered if it has been registered.
4337 If the same hot key has been registered, the new action and help string will override the previous ones.
4339 @param[in] KeyData A pointer to a buffer that describes the keystroke
4340 information for the hot key. Its type is EFI_INPUT_KEY to
4341 be supported by all ConsoleIn devices.
4342 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4343 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4344 @param[in] HelpString Help string that describes the hot key information.
4345 Its value may be NULL for the unregistered hot key.
4347 @retval EFI_SUCCESS Hot key is registered or unregistered.
4348 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4349 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4350 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4355 IN EFI_INPUT_KEY
*KeyData
,
4357 IN UINT16 DefaultId
,
4358 IN EFI_STRING HelpString OPTIONAL
4361 BROWSER_HOT_KEY
*HotKey
;
4364 // Check input parameters.
4366 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4367 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4368 return EFI_INVALID_PARAMETER
;
4372 // Check whether the input KeyData is in BrowserHotKeyList.
4374 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4377 // Unregister HotKey
4379 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4380 if (HotKey
!= NULL
) {
4382 // The registered HotKey is found.
4383 // Remove it from List, and free its resource.
4385 RemoveEntryList (&HotKey
->Link
);
4386 FreePool (HotKey
->KeyData
);
4387 FreePool (HotKey
->HelpString
);
4391 // The registered HotKey is not found.
4393 return EFI_NOT_FOUND
;
4398 // Register HotKey into List.
4400 if (HotKey
== NULL
) {
4402 // Create new Key, and add it into List.
4404 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4405 ASSERT (HotKey
!= NULL
);
4406 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4407 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4408 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4412 // Fill HotKey information.
4414 HotKey
->Action
= Action
;
4415 HotKey
->DefaultId
= DefaultId
;
4416 if (HotKey
->HelpString
!= NULL
) {
4417 FreePool (HotKey
->HelpString
);
4419 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4425 Register Exit handler function.
4426 When more than one handler function is registered, the latter one will override the previous one.
4427 When NULL handler is specified, the previous Exit handler will be unregistered.
4429 @param[in] Handler Pointer to handler function.
4434 RegiserExitHandler (
4435 IN EXIT_HANDLER Handler
4438 ExitHandlerFunction
= Handler
;
4443 Create reminder to let user to choose save or discard the changed browser data.
4444 Caller can use it to actively check the changed browser data.
4446 @retval BROWSER_NO_CHANGES No browser data is changed.
4447 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4448 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4458 FORM_BROWSER_FORMSET
*FormSet
;
4459 BOOLEAN IsDataChanged
;
4460 UINT32 DataSavedAction
;
4461 CHAR16
*YesResponse
;
4463 CHAR16
*EmptyString
;
4464 CHAR16
*ChangeReminderString
;
4465 CHAR16
*SaveConfirmString
;
4468 DataSavedAction
= BROWSER_NO_CHANGES
;
4469 IsDataChanged
= FALSE
;
4470 Link
= GetFirstNode (&gBrowserFormSetList
);
4471 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4472 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4473 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4474 if (!ValidateFormSet(FormSet
)) {
4477 if (IsNvUpdateRequired (FormSet
)) {
4478 IsDataChanged
= TRUE
;
4484 // No data is changed. No save is required.
4486 if (!IsDataChanged
) {
4487 return DataSavedAction
;
4491 // If data is changed, prompt user
4493 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4495 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4496 ASSERT (YesResponse
!= NULL
);
4497 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4498 ASSERT (NoResponse
!= NULL
);
4499 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4500 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4501 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4504 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4506 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4507 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4511 // If the user hits the YesResponse key
4513 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4514 SubmitForm (NULL
, NULL
, SystemLevel
);
4515 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4517 DiscardForm (NULL
, NULL
, SystemLevel
);
4518 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4519 gResetRequired
= FALSE
;
4522 FreePool (YesResponse
);
4523 FreePool (NoResponse
);
4524 FreePool (EmptyString
);
4525 FreePool (SaveConfirmString
);
4526 FreePool (ChangeReminderString
);
4528 return DataSavedAction
;