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 // Save globals used by SendForm()
250 SaveBrowserContext ();
252 gResetRequired
= FALSE
;
253 Status
= EFI_SUCCESS
;
254 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
257 // Seed the dimensions in the global
259 gST
->ConOut
->QueryMode (
261 gST
->ConOut
->Mode
->Mode
,
262 &gScreenDimensions
.RightColumn
,
263 &gScreenDimensions
.BottomRow
266 if (ScreenDimensions
!= NULL
) {
268 // Check local dimension vs. global dimension.
270 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
271 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
273 Status
= EFI_INVALID_PARAMETER
;
277 // Local dimension validation.
279 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
280 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
281 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
283 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
284 SCROLL_ARROW_HEIGHT
*
286 FRONT_PAGE_HEADER_HEIGHT
+
291 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
293 Status
= EFI_INVALID_PARAMETER
;
299 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
300 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
301 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
304 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
306 InitializeBrowserStrings ();
308 gFunctionKeySetting
= ENABLE_FUNCTION_KEY_SETTING
;
311 // Ensure we are in Text mode
313 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
315 for (Index
= 0; Index
< HandleCount
; Index
++) {
316 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
317 ASSERT (Selection
!= NULL
);
319 Selection
->Handle
= Handles
[Index
];
320 if (FormSetGuid
!= NULL
) {
321 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
322 Selection
->FormId
= FormId
;
324 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
328 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
329 ASSERT (FormSet
!= NULL
);
332 // Initialize internal data structures of FormSet
334 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
, TRUE
);
335 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
336 DestroyFormSet (FormSet
);
339 Selection
->FormSet
= FormSet
;
342 // Try to find pre FormSet in the maintain backup list.
344 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
347 // Display this formset
349 gCurrentSelection
= Selection
;
351 Status
= SetupBrowser (Selection
);
353 gCurrentSelection
= NULL
;
355 if (EFI_ERROR (Status
)) {
359 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
361 if (gOldFormSet
!= NULL
) {
363 // If no data is changed, don't need to save current FormSet into the maintain list.
365 if (!IsNvUpdateRequired (gOldFormSet
)) {
366 RemoveEntryList (&gOldFormSet
->Link
);
367 DestroyFormSet (gOldFormSet
);
372 FreePool (Selection
);
375 if (ActionRequest
!= NULL
) {
376 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
377 if (gResetRequired
) {
378 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
382 FreeBrowserStrings ();
384 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
385 gST
->ConOut
->ClearScreen (gST
->ConOut
);
389 // Restore globals used by SendForm()
391 RestoreBrowserContext ();
398 This function is called by a callback handler to retrieve uncommitted state
399 data from the browser.
401 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
403 @param ResultsDataSize A pointer to the size of the buffer associated
405 @param ResultsData A string returned from an IFR browser or
406 equivalent. The results string will have no
407 routing information in them.
408 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
409 (if RetrieveData = TRUE) data from the uncommitted
410 browser state information or set (if RetrieveData
411 = FALSE) data in the uncommitted browser state
413 @param VariableGuid An optional field to indicate the target variable
415 @param VariableName An optional field to indicate the target
416 human-readable variable name.
418 @retval EFI_SUCCESS The results have been distributed or are awaiting
420 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
421 contain the results data.
427 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
428 IN OUT UINTN
*ResultsDataSize
,
429 IN OUT EFI_STRING ResultsData
,
430 IN BOOLEAN RetrieveData
,
431 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
432 IN CONST CHAR16
*VariableName OPTIONAL
437 FORMSET_STORAGE
*Storage
;
438 FORM_BROWSER_FORMSET
*FormSet
;
445 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
446 return EFI_INVALID_PARAMETER
;
449 if (gCurrentSelection
== NULL
) {
450 return EFI_NOT_READY
;
455 FormSet
= gCurrentSelection
->FormSet
;
458 // Find target storage
460 Link
= GetFirstNode (&FormSet
->StorageListHead
);
461 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
462 return EFI_UNSUPPORTED
;
465 if (VariableGuid
!= NULL
) {
467 // Try to find target storage
470 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
471 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
472 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
474 if (CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
475 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
476 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
478 // Buffer storage require both GUID and Name
480 if (VariableName
== NULL
) {
481 return EFI_NOT_FOUND
;
484 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
494 return EFI_NOT_FOUND
;
498 // GUID/Name is not specified, take the first storage in FormSet
500 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
505 // Skip if there is no RequestElement
507 if (Storage
->ElementCount
== 0) {
512 // Generate <ConfigResp>
514 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
515 if (EFI_ERROR (Status
)) {
520 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
522 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
524 BufferSize
= StrSize (StrPtr
);
525 if (*ResultsDataSize
< BufferSize
) {
526 *ResultsDataSize
= BufferSize
;
528 FreePool (ConfigResp
);
529 return EFI_BUFFER_TOO_SMALL
;
532 *ResultsDataSize
= BufferSize
;
533 CopyMem (ResultsData
, StrPtr
, BufferSize
);
535 FreePool (ConfigResp
);
538 // Prepare <ConfigResp>
540 TmpSize
= StrLen (ResultsData
);
541 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
542 ConfigResp
= AllocateZeroPool (BufferSize
);
543 ASSERT (ConfigResp
!= NULL
);
545 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
546 StrCat (ConfigResp
, L
"&");
547 StrCat (ConfigResp
, ResultsData
);
550 // Update Browser uncommited data
552 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
553 if (EFI_ERROR (Status
)) {
562 Notify function will remove the formset in the maintain list
563 once this formset is removed.
565 Functions which are registered to receive notification of
566 database events have this prototype. The actual event is encoded
567 in NotifyType. The following table describes how PackageType,
568 PackageGuid, Handle, and Package are used for each of the
571 @param PackageType Package type of the notification.
573 @param PackageGuid If PackageType is
574 EFI_HII_PACKAGE_TYPE_GUID, then this is
575 the pointer to the GUID from the Guid
576 field of EFI_HII_PACKAGE_GUID_HEADER.
577 Otherwise, it must be NULL.
579 @param Package Points to the package referred to by the
580 notification Handle The handle of the package
581 list which contains the specified package.
583 @param Handle The HII handle.
585 @param NotifyType The type of change concerning the
587 EFI_HII_DATABASE_NOTIFY_TYPE.
592 FormsetRemoveNotify (
593 IN UINT8 PackageType
,
594 IN CONST EFI_GUID
*PackageGuid
,
595 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
596 IN EFI_HII_HANDLE Handle
,
597 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
600 FORM_BROWSER_FORMSET
*FormSet
;
603 // Ignore the update for current using formset, which is handled by another notify function.
605 if (IsHiiHandleInBrowserContext (Handle
)) {
610 // Remove the backup FormSet data when the Form Package is removed.
612 FormSet
= GetFormSetFromHiiHandle (Handle
);
613 if (FormSet
!= NULL
) {
614 RemoveEntryList (&FormSet
->Link
);
615 DestroyFormSet (FormSet
);
622 Initialize Setup Browser driver.
624 @param ImageHandle The image handle.
625 @param SystemTable The system table.
627 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
628 @return Other value if failed to initialize the Setup Browser module.
634 IN EFI_HANDLE ImageHandle
,
635 IN EFI_SYSTEM_TABLE
*SystemTable
639 EFI_HANDLE NotifyHandle
;
640 EFI_INPUT_KEY DefaultHotKey
;
641 EFI_STRING HelpString
;
644 // Locate required Hii relative protocols
646 Status
= gBS
->LocateProtocol (
647 &gEfiHiiDatabaseProtocolGuid
,
649 (VOID
**) &mHiiDatabase
651 ASSERT_EFI_ERROR (Status
);
653 Status
= gBS
->LocateProtocol (
654 &gEfiHiiStringProtocolGuid
,
656 (VOID
**) &mHiiString
658 ASSERT_EFI_ERROR (Status
);
660 Status
= gBS
->LocateProtocol (
661 &gEfiHiiConfigRoutingProtocolGuid
,
663 (VOID
**) &mHiiConfigRouting
665 ASSERT_EFI_ERROR (Status
);
667 Status
= gBS
->LocateProtocol (
668 &gEfiDevicePathFromTextProtocolGuid
,
670 (VOID
**) &mPathFromText
674 // Publish our HII data
676 gHiiHandle
= HiiAddPackages (
682 ASSERT (gHiiHandle
!= NULL
);
685 // Initialize Driver private data
687 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
688 ASSERT (gBannerData
!= NULL
);
691 // Initialize generic help strings.
693 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
694 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
695 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
698 // Install FormBrowser2 protocol
700 mPrivateData
.Handle
= NULL
;
701 Status
= gBS
->InstallProtocolInterface (
702 &mPrivateData
.Handle
,
703 &gEfiFormBrowser2ProtocolGuid
,
704 EFI_NATIVE_INTERFACE
,
705 &mPrivateData
.FormBrowser2
707 ASSERT_EFI_ERROR (Status
);
710 // Install default HotKey F10 for Save
712 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
713 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
714 DefaultHotKey
.ScanCode
= SCAN_F10
;
715 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
716 FreePool (HelpString
);
718 // Install default HotKey F9 for Reset To Defaults
720 DefaultHotKey
.ScanCode
= SCAN_F9
;
721 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
722 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
723 FreePool (HelpString
);
726 // Install FormBrowserEx protocol
728 mPrivateData
.Handle
= NULL
;
729 Status
= gBS
->InstallProtocolInterface (
730 &mPrivateData
.Handle
,
731 &gEfiFormBrowserExProtocolGuid
,
732 EFI_NATIVE_INTERFACE
,
733 &mPrivateData
.FormBrowserEx
735 ASSERT_EFI_ERROR (Status
);
738 // Register notify for Form package remove
740 Status
= mHiiDatabase
->RegisterPackageNotify (
742 EFI_HII_PACKAGE_FORMS
,
745 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
748 ASSERT_EFI_ERROR (Status
);
755 Create a new string in HII Package List.
757 @param String The String to be added
758 @param HiiHandle The package list in the HII database to insert the
761 @return The output string.
767 IN EFI_HII_HANDLE HiiHandle
770 EFI_STRING_ID StringId
;
772 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
773 ASSERT (StringId
!= 0);
780 Delete a string from HII Package List.
782 @param StringId Id of the string in HII database.
783 @param HiiHandle The HII package list handle.
785 @retval EFI_SUCCESS The string was deleted successfully.
790 IN EFI_STRING_ID StringId
,
791 IN EFI_HII_HANDLE HiiHandle
796 NullChar
= CHAR_NULL
;
797 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
803 Get the string based on the StringId and HII Package List Handle.
805 @param Token The String's ID.
806 @param HiiHandle The package list in the HII database to search for
807 the specified string.
809 @return The output string.
814 IN EFI_STRING_ID Token
,
815 IN EFI_HII_HANDLE HiiHandle
820 if (HiiHandle
== NULL
) {
824 String
= HiiGetString (HiiHandle
, Token
, NULL
);
825 if (String
== NULL
) {
826 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
827 ASSERT (String
!= NULL
);
829 return (CHAR16
*) String
;
834 Allocate new memory and then copy the Unicode string Source to Destination.
836 @param Dest Location to copy string
837 @param Src String to copy
842 IN OUT CHAR16
**Dest
,
849 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
850 ASSERT (*Dest
!= NULL
);
855 Allocate new memory and concatinate Source on the end of Destination.
857 @param Dest String to added to the end of.
858 @param Src String to concatinate.
863 IN OUT CHAR16
**Dest
,
871 NewStringCpy (Dest
, Src
);
875 TmpSize
= StrSize (*Dest
);
876 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
877 ASSERT (NewString
!= NULL
);
879 StrCpy (NewString
, *Dest
);
880 StrCat (NewString
, Src
);
888 Synchronize or restore Storage's Edit copy and Shadow copy.
890 @param Storage The Storage to be synchronized.
891 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
893 if TRUE, copy the editbuffer to the buffer.
894 if FALSE, copy the buffer to the editbuffer.
899 IN FORMSET_STORAGE
*Storage
,
900 IN BOOLEAN SyncOrRestore
904 NAME_VALUE_NODE
*Node
;
906 switch (Storage
->Type
) {
907 case EFI_HII_VARSTORE_BUFFER
:
908 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
910 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
912 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
916 case EFI_HII_VARSTORE_NAME_VALUE
:
917 Link
= GetFirstNode (&Storage
->NameValueListHead
);
918 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
919 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
922 NewStringCpy (&Node
->Value
, Node
->EditValue
);
924 NewStringCpy (&Node
->EditValue
, Node
->Value
);
927 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
931 case EFI_HII_VARSTORE_EFI_VARIABLE
:
939 Get Value for given Name from a NameValue Storage.
941 @param Storage The NameValue Storage.
942 @param Name The Name.
943 @param Value The retured Value.
944 @param GetValueFrom Where to get source value, from EditValue or Value.
946 @retval EFI_SUCCESS Value found for given Name.
947 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
952 IN FORMSET_STORAGE
*Storage
,
954 IN OUT CHAR16
**Value
,
955 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
959 NAME_VALUE_NODE
*Node
;
961 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
962 return EFI_INVALID_PARAMETER
;
967 Link
= GetFirstNode (&Storage
->NameValueListHead
);
968 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
969 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
971 if (StrCmp (Name
, Node
->Name
) == 0) {
972 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
973 NewStringCpy (Value
, Node
->EditValue
);
975 NewStringCpy (Value
, Node
->Value
);
980 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
983 return EFI_NOT_FOUND
;
988 Set Value of given Name in a NameValue Storage.
990 @param Storage The NameValue Storage.
991 @param Name The Name.
992 @param Value The Value to set.
993 @param SetValueTo Whether update editValue or Value.
995 @retval EFI_SUCCESS Value found for given Name.
996 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1001 IN FORMSET_STORAGE
*Storage
,
1004 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1008 NAME_VALUE_NODE
*Node
;
1011 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1012 return EFI_INVALID_PARAMETER
;
1015 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1016 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1017 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1019 if (StrCmp (Name
, Node
->Name
) == 0) {
1020 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1021 Buffer
= Node
->EditValue
;
1023 Buffer
= Node
->Value
;
1025 if (Buffer
!= NULL
) {
1028 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1029 ASSERT (Buffer
!= NULL
);
1030 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1031 Node
->EditValue
= Buffer
;
1033 Node
->Value
= Buffer
;
1038 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1041 return EFI_NOT_FOUND
;
1046 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1048 @param Buffer The Storage to be conveted.
1049 @param ConfigResp The returned <ConfigResp>.
1050 @param SingleForm Whether update data for single form or formset level.
1052 @retval EFI_SUCCESS Convert success.
1053 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1057 StorageToConfigResp (
1059 IN CHAR16
**ConfigResp
,
1060 IN BOOLEAN SingleForm
1064 EFI_STRING Progress
;
1066 NAME_VALUE_NODE
*Node
;
1067 CHAR16
*ConfigRequest
;
1068 FORMSET_STORAGE
*Storage
;
1069 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
1071 Status
= EFI_SUCCESS
;
1073 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
1074 Storage
= ConfigInfo
->Storage
;
1075 ConfigRequest
= ConfigInfo
->ConfigRequest
;
1077 Storage
= (FORMSET_STORAGE
*) Buffer
;
1078 ConfigRequest
= Storage
->ConfigRequest
;
1081 switch (Storage
->Type
) {
1082 case EFI_HII_VARSTORE_BUFFER
:
1083 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1084 Status
= mHiiConfigRouting
->BlockToConfig (
1087 Storage
->EditBuffer
,
1094 case EFI_HII_VARSTORE_NAME_VALUE
:
1096 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1098 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1099 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1100 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1102 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1103 NewStringCat (ConfigResp
, L
"&");
1104 NewStringCat (ConfigResp
, Node
->Name
);
1105 NewStringCat (ConfigResp
, L
"=");
1106 NewStringCat (ConfigResp
, Node
->EditValue
);
1108 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1112 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1114 Status
= EFI_INVALID_PARAMETER
;
1123 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1125 @param Storage The Storage to receive the settings.
1126 @param ConfigResp The <ConfigResp> to be converted.
1128 @retval EFI_SUCCESS Convert success.
1129 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1133 ConfigRespToStorage (
1134 IN FORMSET_STORAGE
*Storage
,
1135 IN CHAR16
*ConfigResp
1139 EFI_STRING Progress
;
1145 Status
= EFI_SUCCESS
;
1147 switch (Storage
->Type
) {
1148 case EFI_HII_VARSTORE_BUFFER
:
1149 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1150 BufferSize
= Storage
->Size
;
1151 Status
= mHiiConfigRouting
->ConfigToBlock (
1154 Storage
->EditBuffer
,
1160 case EFI_HII_VARSTORE_NAME_VALUE
:
1161 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1162 if (StrPtr
== NULL
) {
1165 StrPtr
= StrStr (ConfigResp
, L
"&");
1166 while (StrPtr
!= NULL
) {
1170 StrPtr
= StrPtr
+ 1;
1172 StrPtr
= StrStr (StrPtr
, L
"=");
1173 if (StrPtr
== NULL
) {
1181 StrPtr
= StrPtr
+ 1;
1183 StrPtr
= StrStr (StrPtr
, L
"&");
1184 if (StrPtr
!= NULL
) {
1187 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
);
1191 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1193 Status
= EFI_INVALID_PARAMETER
;
1202 Get Question's current Value.
1204 @param FormSet FormSet data structure.
1205 @param Form Form data structure.
1206 @param Question Question to be initialized.
1207 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1209 @retval EFI_SUCCESS The function completed successfully.
1214 IN FORM_BROWSER_FORMSET
*FormSet
,
1215 IN FORM_BROWSER_FORM
*Form
,
1216 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1217 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1226 FORMSET_STORAGE
*Storage
;
1227 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1228 CHAR16
*ConfigRequest
;
1236 BOOLEAN IsBufferStorage
;
1242 Status
= EFI_SUCCESS
;
1246 if (GetValueFrom
>= GetSetValueWithMax
) {
1247 return EFI_INVALID_PARAMETER
;
1251 // Statement don't have storage, skip them
1253 if (Question
->QuestionId
== 0) {
1258 // Question value is provided by an Expression, evaluate it
1260 if (Question
->ValueExpression
!= NULL
) {
1261 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1262 if (!EFI_ERROR (Status
)) {
1263 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1264 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1265 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1266 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1267 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1269 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1270 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1272 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1274 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1275 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1281 // Get question value by read expression.
1283 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1284 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1285 if (!EFI_ERROR (Status
) &&
1286 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1288 // Only update question value to the valid result.
1290 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1291 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1292 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1293 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1294 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1296 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1297 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1299 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1301 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1302 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1308 // Question value is provided by RTC
1310 Storage
= Question
->Storage
;
1311 QuestionValue
= &Question
->HiiValue
.Value
;
1312 if (Storage
== NULL
) {
1314 // It's a Question without storage, or RTC date/time
1316 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1318 // Date and time define the same Flags bit
1320 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1321 case QF_DATE_STORAGE_TIME
:
1322 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1325 case QF_DATE_STORAGE_WAKEUP
:
1326 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1329 case QF_DATE_STORAGE_NORMAL
:
1332 // For date/time without storage
1337 if (EFI_ERROR (Status
)) {
1341 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1342 QuestionValue
->date
.Year
= EfiTime
.Year
;
1343 QuestionValue
->date
.Month
= EfiTime
.Month
;
1344 QuestionValue
->date
.Day
= EfiTime
.Day
;
1346 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1347 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1348 QuestionValue
->time
.Second
= EfiTime
.Second
;
1356 // Question value is provided by EFI variable
1358 StorageWidth
= Question
->StorageWidth
;
1359 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1360 if (Question
->BufferValue
!= NULL
) {
1361 Dst
= Question
->BufferValue
;
1363 Dst
= (UINT8
*) QuestionValue
;
1366 Status
= gRT
->GetVariable (
1367 Question
->VariableName
,
1374 // Always return success, even this EFI variable doesn't exist
1380 // Question Value is provided by Buffer Storage or NameValue Storage
1382 if (Question
->BufferValue
!= NULL
) {
1384 // This Question is password or orderedlist
1386 Dst
= Question
->BufferValue
;
1389 // Other type of Questions
1391 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1394 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1395 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1396 IsBufferStorage
= TRUE
;
1398 IsBufferStorage
= FALSE
;
1400 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1401 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1402 if (IsBufferStorage
) {
1403 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1405 // Copy from storage Edit buffer
1407 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1410 // Copy from storage Edit buffer
1412 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1416 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1417 if (EFI_ERROR (Status
)) {
1421 ASSERT (Value
!= NULL
);
1422 LengthStr
= StrLen (Value
);
1423 Status
= EFI_SUCCESS
;
1426 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1427 // Add string tail char L'\0' into Length
1429 Length
= StorageWidth
+ sizeof (CHAR16
);
1430 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1431 Status
= EFI_BUFFER_TOO_SMALL
;
1433 StringPtr
= (CHAR16
*) Dst
;
1434 ZeroMem (TemStr
, sizeof (TemStr
));
1435 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1436 StrnCpy (TemStr
, Value
+ Index
, 4);
1437 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1440 // Add tailing L'\0' character
1442 StringPtr
[Index
/4] = L
'\0';
1445 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1446 Status
= EFI_BUFFER_TOO_SMALL
;
1448 ZeroMem (TemStr
, sizeof (TemStr
));
1449 for (Index
= 0; Index
< LengthStr
; Index
++) {
1450 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1451 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1452 if ((Index
& 1) == 0) {
1453 Dst
[Index
/2] = DigitUint8
;
1455 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1464 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1466 // Request current settings from Configuration Driver
1468 if (FormSet
->ConfigAccess
== NULL
) {
1469 return EFI_NOT_FOUND
;
1473 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1474 // <ConfigHdr> + "&" + <VariableName>
1476 if (IsBufferStorage
) {
1477 Length
= StrLen (Storage
->ConfigHdr
);
1478 Length
+= StrLen (Question
->BlockName
);
1480 Length
= StrLen (Storage
->ConfigHdr
);
1481 Length
+= StrLen (Question
->VariableName
) + 1;
1483 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1484 ASSERT (ConfigRequest
!= NULL
);
1486 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1487 if (IsBufferStorage
) {
1488 StrCat (ConfigRequest
, Question
->BlockName
);
1490 StrCat (ConfigRequest
, L
"&");
1491 StrCat (ConfigRequest
, Question
->VariableName
);
1494 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1495 FormSet
->ConfigAccess
,
1500 FreePool (ConfigRequest
);
1501 if (EFI_ERROR (Status
)) {
1506 // Skip <ConfigRequest>
1508 if (IsBufferStorage
) {
1509 Value
= StrStr (Result
, L
"&VALUE");
1510 if (Value
== NULL
) {
1512 return EFI_NOT_FOUND
;
1519 Value
= Result
+ Length
;
1521 if (*Value
!= '=') {
1523 return EFI_NOT_FOUND
;
1526 // Skip '=', point to value
1531 // Suppress <AltResp> if any
1534 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1539 LengthStr
= StrLen (Value
);
1540 Status
= EFI_SUCCESS
;
1541 if (!IsBufferStorage
&& IsString
) {
1543 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1544 // Add string tail char L'\0' into Length
1546 Length
= StorageWidth
+ sizeof (CHAR16
);
1547 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1548 Status
= EFI_BUFFER_TOO_SMALL
;
1550 StringPtr
= (CHAR16
*) Dst
;
1551 ZeroMem (TemStr
, sizeof (TemStr
));
1552 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1553 StrnCpy (TemStr
, Value
+ Index
, 4);
1554 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1557 // Add tailing L'\0' character
1559 StringPtr
[Index
/4] = L
'\0';
1562 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1563 Status
= EFI_BUFFER_TOO_SMALL
;
1565 ZeroMem (TemStr
, sizeof (TemStr
));
1566 for (Index
= 0; Index
< LengthStr
; Index
++) {
1567 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1568 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1569 if ((Index
& 1) == 0) {
1570 Dst
[Index
/2] = DigitUint8
;
1572 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1578 if (EFI_ERROR (Status
)) {
1582 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1584 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1585 if (TemBuffer
== NULL
) {
1586 Status
= EFI_OUT_OF_RESOURCES
;
1589 Length
= Storage
->Size
;
1590 Status
= gRT
->GetVariable (
1597 if (EFI_ERROR (Status
)) {
1598 FreePool (TemBuffer
);
1602 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1604 FreePool (TemBuffer
);
1608 // Synchronize Edit Buffer
1610 if (IsBufferStorage
) {
1611 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1613 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
);
1616 if (Result
!= NULL
) {
1626 Save Question Value to edit copy(cached) or Storage(uncached).
1628 @param FormSet FormSet data structure.
1629 @param Form Form data structure.
1630 @param Question Pointer to the Question.
1631 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1633 @retval EFI_SUCCESS The function completed successfully.
1638 IN FORM_BROWSER_FORMSET
*FormSet
,
1639 IN FORM_BROWSER_FORM
*Form
,
1640 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1641 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1651 FORMSET_STORAGE
*Storage
;
1652 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1657 BOOLEAN IsBufferStorage
;
1664 Status
= EFI_SUCCESS
;
1666 if (SetValueTo
>= GetSetValueWithMax
) {
1667 return EFI_INVALID_PARAMETER
;
1671 // Statement don't have storage, skip them
1673 if (Question
->QuestionId
== 0) {
1678 // If Question value is provided by an Expression, then it is read only
1680 if (Question
->ValueExpression
!= NULL
) {
1685 // Before set question value, evaluate its write expression.
1687 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1688 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1689 if (EFI_ERROR (Status
)) {
1695 // Question value is provided by RTC
1697 Storage
= Question
->Storage
;
1698 QuestionValue
= &Question
->HiiValue
.Value
;
1699 if (Storage
== NULL
) {
1701 // It's a Question without storage, or RTC date/time
1703 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1705 // Date and time define the same Flags bit
1707 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1708 case QF_DATE_STORAGE_TIME
:
1709 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1712 case QF_DATE_STORAGE_WAKEUP
:
1713 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1716 case QF_DATE_STORAGE_NORMAL
:
1719 // For date/time without storage
1724 if (EFI_ERROR (Status
)) {
1728 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1729 EfiTime
.Year
= QuestionValue
->date
.Year
;
1730 EfiTime
.Month
= QuestionValue
->date
.Month
;
1731 EfiTime
.Day
= QuestionValue
->date
.Day
;
1733 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1734 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1735 EfiTime
.Second
= QuestionValue
->time
.Second
;
1738 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1739 Status
= gRT
->SetTime (&EfiTime
);
1741 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1749 // Question value is provided by EFI variable
1751 StorageWidth
= Question
->StorageWidth
;
1752 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1753 if (Question
->BufferValue
!= NULL
) {
1754 Src
= Question
->BufferValue
;
1756 Src
= (UINT8
*) QuestionValue
;
1759 Status
= gRT
->SetVariable (
1760 Question
->VariableName
,
1762 Storage
->Attributes
,
1770 // Question Value is provided by Buffer Storage or NameValue Storage
1772 if (Question
->BufferValue
!= NULL
) {
1773 Src
= Question
->BufferValue
;
1775 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1778 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1779 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1780 IsBufferStorage
= TRUE
;
1782 IsBufferStorage
= FALSE
;
1784 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1786 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1787 if (IsBufferStorage
) {
1788 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1790 // Copy to storage edit buffer
1792 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1793 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1795 // Copy to storage edit buffer
1797 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1802 // Allocate enough string buffer.
1805 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1806 Value
= AllocateZeroPool (BufferLen
);
1807 ASSERT (Value
!= NULL
);
1809 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1811 TemName
= (CHAR16
*) Src
;
1813 for (; *TemName
!= L
'\0'; TemName
++) {
1814 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1817 BufferLen
= StorageWidth
* 2 + 1;
1818 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1819 ASSERT (Value
!= NULL
);
1821 // Convert Buffer to Hex String
1823 TemBuffer
= Src
+ StorageWidth
- 1;
1825 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1826 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1830 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
);
1833 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1834 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1836 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1837 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1839 if (IsBufferStorage
) {
1840 Length
= StrLen (Question
->BlockName
) + 7;
1842 Length
= StrLen (Question
->VariableName
) + 2;
1844 if (!IsBufferStorage
&& IsString
) {
1845 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1847 Length
+= (StorageWidth
* 2);
1849 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1850 ASSERT (ConfigResp
!= NULL
);
1852 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1853 if (IsBufferStorage
) {
1854 StrCat (ConfigResp
, Question
->BlockName
);
1855 StrCat (ConfigResp
, L
"&VALUE=");
1857 StrCat (ConfigResp
, L
"&");
1858 StrCat (ConfigResp
, Question
->VariableName
);
1859 StrCat (ConfigResp
, L
"=");
1862 Value
= ConfigResp
+ StrLen (ConfigResp
);
1864 if (!IsBufferStorage
&& IsString
) {
1866 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1868 TemName
= (CHAR16
*) Src
;
1870 for (; *TemName
!= L
'\0'; TemName
++) {
1871 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1875 // Convert Buffer to Hex String
1877 TemBuffer
= Src
+ StorageWidth
- 1;
1879 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1880 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1885 // Convert to lower char.
1887 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1888 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1889 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1894 // Submit Question Value to Configuration Driver
1896 if (FormSet
->ConfigAccess
!= NULL
) {
1897 Status
= FormSet
->ConfigAccess
->RouteConfig (
1898 FormSet
->ConfigAccess
,
1902 if (EFI_ERROR (Status
)) {
1903 FreePool (ConfigResp
);
1907 FreePool (ConfigResp
);
1909 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1911 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1912 if (TemBuffer
== NULL
) {
1913 Status
= EFI_OUT_OF_RESOURCES
;
1916 Length
= Storage
->Size
;
1917 Status
= gRT
->GetVariable (
1925 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1927 Status
= gRT
->SetVariable (
1930 Storage
->Attributes
,
1934 FreePool (TemBuffer
);
1935 if (EFI_ERROR (Status
)){
1940 // Sync storage, from editbuffer to buffer.
1942 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1950 Perform inconsistent check for a Form.
1952 @param FormSet FormSet data structure.
1953 @param Form Form data structure.
1954 @param Question The Question to be validated.
1955 @param Type Validation type: InConsistent or NoSubmit
1957 @retval EFI_SUCCESS Form validation pass.
1958 @retval other Form validation failed.
1963 IN FORM_BROWSER_FORMSET
*FormSet
,
1964 IN FORM_BROWSER_FORM
*Form
,
1965 IN FORM_BROWSER_STATEMENT
*Question
,
1971 LIST_ENTRY
*ListHead
;
1974 FORM_EXPRESSION
*Expression
;
1976 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1977 ListHead
= &Question
->InconsistentListHead
;
1978 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1979 ListHead
= &Question
->NoSubmitListHead
;
1981 return EFI_UNSUPPORTED
;
1984 Link
= GetFirstNode (ListHead
);
1985 while (!IsNull (ListHead
, Link
)) {
1986 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1989 // Evaluate the expression
1991 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1992 if (EFI_ERROR (Status
)) {
1996 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1998 // Condition meet, show up error message
2000 if (Expression
->Error
!= 0) {
2001 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2003 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
2004 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
2008 return EFI_NOT_READY
;
2011 Link
= GetNextNode (ListHead
, Link
);
2019 Perform NoSubmit check for each Form in FormSet.
2021 @param FormSet FormSet data structure.
2022 @param CurrentForm Current input form data structure.
2024 @retval EFI_SUCCESS Form validation pass.
2025 @retval other Form validation failed.
2030 IN FORM_BROWSER_FORMSET
*FormSet
,
2031 IN FORM_BROWSER_FORM
*CurrentForm
2036 FORM_BROWSER_STATEMENT
*Question
;
2037 FORM_BROWSER_FORM
*Form
;
2038 LIST_ENTRY
*LinkForm
;
2040 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2041 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2042 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2043 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2045 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2049 Link
= GetFirstNode (&Form
->StatementListHead
);
2050 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2051 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2053 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2054 if (EFI_ERROR (Status
)) {
2058 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2066 Fill storage's edit copy with settings requested from Configuration Driver.
2068 @param FormSet FormSet data structure.
2069 @param ConfigInfo The config info related to this form.
2070 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2071 editbuffer to buffer
2072 if TRUE, copy the editbuffer to the buffer.
2073 if FALSE, copy the buffer to the editbuffer.
2075 @retval EFI_SUCCESS The function completed successfully.
2079 SynchronizeStorageForForm (
2080 IN FORM_BROWSER_FORMSET
*FormSet
,
2081 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2082 IN BOOLEAN SyncOrRestore
2086 EFI_STRING Progress
;
2090 NAME_VALUE_NODE
*Node
;
2094 Status
= EFI_SUCCESS
;
2096 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2097 return EFI_NOT_FOUND
;
2100 if (ConfigInfo
->ElementCount
== 0) {
2102 // Skip if there is no RequestElement
2107 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2108 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2109 BufferSize
= ConfigInfo
->Storage
->Size
;
2111 if (SyncOrRestore
) {
2112 Src
= ConfigInfo
->Storage
->EditBuffer
;
2113 Dst
= ConfigInfo
->Storage
->Buffer
;
2115 Src
= ConfigInfo
->Storage
->Buffer
;
2116 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2119 Status
= mHiiConfigRouting
->BlockToConfig(
2121 ConfigInfo
->ConfigRequest
,
2127 if (EFI_ERROR (Status
)) {
2131 Status
= mHiiConfigRouting
->ConfigToBlock (
2138 if (Result
!= NULL
) {
2141 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2142 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2143 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2144 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2146 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2147 if (SyncOrRestore
) {
2148 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2150 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2154 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2162 When discard the question value, call the callback function with Changed type
2163 to inform the hii driver.
2165 @param FormSet FormSet data structure.
2166 @param Form Form data structure.
2170 SendDiscardInfoToDriver (
2171 IN FORM_BROWSER_FORMSET
*FormSet
,
2172 IN FORM_BROWSER_FORM
*Form
2176 FORM_BROWSER_STATEMENT
*Question
;
2178 EFI_HII_VALUE HiiValue
;
2180 BOOLEAN ValueChanged
;
2181 EFI_IFR_TYPE_VALUE
*TypeValue
;
2182 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2184 ValueChanged
= FALSE
;
2187 if(!Form
->NvUpdateRequired
) {
2191 Link
= GetFirstNode (&Form
->StatementListHead
);
2192 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2193 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2194 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2196 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2200 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2204 if (Question
->BufferValue
!= NULL
) {
2205 BufferValue
= AllocateZeroPool (Question
->StorageWidth
);
2206 ASSERT (BufferValue
!= NULL
);
2207 CopyMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
);
2209 HiiValue
.Type
= Question
->HiiValue
.Type
;
2210 CopyMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2213 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
2214 if (EFI_ERROR (Status
)) {
2215 if (BufferValue
!= NULL
) {
2216 FreePool (BufferValue
);
2222 if (Question
->BufferValue
!= NULL
) {
2223 if (CompareMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
)) {
2224 ValueChanged
= TRUE
;
2227 if (CompareMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
))) {
2228 ValueChanged
= TRUE
;
2232 if (BufferValue
!= NULL
) {
2233 FreePool (BufferValue
);
2237 if (!ValueChanged
) {
2241 ValueChanged
= FALSE
;
2243 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2244 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2246 TypeValue
= &Question
->HiiValue
.Value
;
2249 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2250 FormSet
->ConfigAccess
->Callback (
2251 FormSet
->ConfigAccess
,
2252 EFI_BROWSER_ACTION_CHANGED
,
2253 Question
->QuestionId
,
2254 Question
->HiiValue
.Type
,
2262 Discard data based on the input setting scope (Form, FormSet or System).
2264 @param FormSet FormSet data structure.
2265 @param Form Form data structure.
2266 @param SettingScope Setting Scope for Discard action.
2268 @retval EFI_SUCCESS The function completed successfully.
2269 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2274 IN FORM_BROWSER_FORMSET
*FormSet
,
2275 IN FORM_BROWSER_FORM
*Form
,
2276 IN BROWSER_SETTING_SCOPE SettingScope
2280 FORMSET_STORAGE
*Storage
;
2281 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2282 FORM_BROWSER_FORMSET
*LocalFormSet
;
2285 // Check the supported setting level.
2287 if (SettingScope
>= MaxLevel
) {
2288 return EFI_UNSUPPORTED
;
2291 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2293 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2294 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2295 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2296 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2298 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2303 // Skip if there is no RequestElement
2305 if (ConfigInfo
->ElementCount
== 0) {
2310 // Prepare <ConfigResp>
2312 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2315 // Call callback with Changed type to inform the driver.
2317 SendDiscardInfoToDriver (FormSet
, Form
);
2320 Form
->NvUpdateRequired
= FALSE
;
2321 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2324 // Discard Buffer storage or Name/Value storage
2326 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2327 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2328 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2329 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2331 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2336 // Skip if there is no RequestElement
2338 if (Storage
->ElementCount
== 0) {
2342 SynchronizeStorage(Storage
, FALSE
);
2345 Link
= GetFirstNode (&FormSet
->FormListHead
);
2346 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2347 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2348 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2351 // Call callback with Changed type to inform the driver.
2353 SendDiscardInfoToDriver (FormSet
, Form
);
2356 UpdateNvInfoInForm (FormSet
, FALSE
);
2357 } else if (SettingScope
== SystemLevel
) {
2359 // System Level Discard.
2363 // Discard changed value for each FormSet in the maintain list.
2365 Link
= GetFirstNode (&gBrowserFormSetList
);
2366 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2367 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2368 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2369 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2370 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2372 // Remove maintain backup list after discard except for the current using FormSet.
2374 RemoveEntryList (&LocalFormSet
->Link
);
2375 DestroyFormSet (LocalFormSet
);
2384 Submit data based on the input Setting level (Form, FormSet or System).
2386 @param FormSet FormSet data structure.
2387 @param Form Form data structure.
2388 @param SettingScope Setting Scope for Submit action.
2390 @retval EFI_SUCCESS The function completed successfully.
2391 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2396 IN FORM_BROWSER_FORMSET
*FormSet
,
2397 IN FORM_BROWSER_FORM
*Form
,
2398 IN BROWSER_SETTING_SCOPE SettingScope
2403 EFI_STRING ConfigResp
;
2404 EFI_STRING Progress
;
2405 FORMSET_STORAGE
*Storage
;
2408 FORM_BROWSER_FORMSET
*LocalFormSet
;
2409 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2412 // Check the supported setting level.
2414 if (SettingScope
>= MaxLevel
) {
2415 return EFI_UNSUPPORTED
;
2419 // Validate the Form by NoSubmit check
2421 Status
= EFI_SUCCESS
;
2422 if (SettingScope
== FormLevel
) {
2423 Status
= NoSubmitCheck (FormSet
, Form
);
2424 } else if (SettingScope
== FormSetLevel
) {
2425 Status
= NoSubmitCheck (FormSet
, NULL
);
2427 if (EFI_ERROR (Status
)) {
2431 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2433 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2434 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2435 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2436 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2438 Storage
= ConfigInfo
->Storage
;
2439 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2444 // Skip if there is no RequestElement
2446 if (ConfigInfo
->ElementCount
== 0) {
2451 // 1. Prepare <ConfigResp>
2453 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2454 if (EFI_ERROR (Status
)) {
2459 // 2. Set value to hii driver or efi variable.
2461 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2462 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2464 // Send <ConfigResp> to Configuration Driver
2466 if (FormSet
->ConfigAccess
!= NULL
) {
2467 Status
= FormSet
->ConfigAccess
->RouteConfig (
2468 FormSet
->ConfigAccess
,
2472 if (EFI_ERROR (Status
)) {
2473 FreePool (ConfigResp
);
2477 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2479 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2480 if (TmpBuf
== NULL
) {
2481 Status
= EFI_OUT_OF_RESOURCES
;
2485 BufferSize
= Storage
->Size
;
2486 Status
= gRT
->GetVariable (
2493 if (EFI_ERROR (Status
)) {
2495 FreePool (ConfigResp
);
2498 ASSERT (BufferSize
== Storage
->Size
);
2499 Status
= mHiiConfigRouting
->ConfigToBlock (
2506 if (EFI_ERROR (Status
)) {
2508 FreePool (ConfigResp
);
2512 Status
= gRT
->SetVariable (
2515 Storage
->Attributes
,
2520 if (EFI_ERROR (Status
)) {
2521 FreePool (ConfigResp
);
2525 FreePool (ConfigResp
);
2527 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2529 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2533 // 4. Update the NV flag.
2535 Form
->NvUpdateRequired
= FALSE
;
2536 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2538 // Submit Buffer storage or Name/Value storage
2540 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2541 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2542 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2543 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2545 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2550 // Skip if there is no RequestElement
2552 if (Storage
->ElementCount
== 0) {
2557 // 1. Prepare <ConfigResp>
2559 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2560 if (EFI_ERROR (Status
)) {
2564 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2565 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2568 // 2. Send <ConfigResp> to Configuration Driver
2570 if (FormSet
->ConfigAccess
!= NULL
) {
2571 Status
= FormSet
->ConfigAccess
->RouteConfig (
2572 FormSet
->ConfigAccess
,
2576 if (EFI_ERROR (Status
)) {
2577 FreePool (ConfigResp
);
2581 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2583 // 1&2. Set the edit data to the variable.
2586 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2587 if (TmpBuf
== NULL
) {
2588 Status
= EFI_OUT_OF_RESOURCES
;
2591 BufferSize
= Storage
->Size
;
2592 Status
= gRT
->GetVariable (
2599 ASSERT (BufferSize
== Storage
->Size
);
2600 Status
= mHiiConfigRouting
->ConfigToBlock (
2607 if (EFI_ERROR (Status
)) {
2609 FreePool (ConfigResp
);
2613 Status
= gRT
->SetVariable (
2616 Storage
->Attributes
,
2620 if (EFI_ERROR (Status
)) {
2622 FreePool (ConfigResp
);
2627 FreePool (ConfigResp
);
2629 // 3. Config success, update storage shadow Buffer
2631 SynchronizeStorage (Storage
, TRUE
);
2635 // 4. Update the NV flag.
2637 UpdateNvInfoInForm (FormSet
, FALSE
);
2638 } else if (SettingScope
== SystemLevel
) {
2640 // System Level Save.
2644 // Save changed value for each FormSet in the maintain list.
2646 Link
= GetFirstNode (&gBrowserFormSetList
);
2647 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2648 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2649 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2650 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2651 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2653 // Remove maintain backup list after save except for the current using FormSet.
2655 RemoveEntryList (&LocalFormSet
->Link
);
2656 DestroyFormSet (LocalFormSet
);
2665 Get Question default value from AltCfg string.
2667 @param FormSet The form set.
2668 @param Question The question.
2669 @param DefaultId The default Id.
2671 @retval EFI_SUCCESS Question is reset to default value.
2675 GetDefaultValueFromAltCfg (
2676 IN FORM_BROWSER_FORMSET
*FormSet
,
2677 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2681 BOOLEAN IsBufferStorage
;
2684 FORMSET_STORAGE
*Storage
;
2685 CHAR16
*ConfigRequest
;
2698 Status
= EFI_NOT_FOUND
;
2701 ConfigRequest
= NULL
;
2705 Storage
= Question
->Storage
;
2707 if ((Storage
== NULL
) ||
2708 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2709 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2714 // Question Value is provided by Buffer Storage or NameValue Storage
2716 if (Question
->BufferValue
!= NULL
) {
2718 // This Question is password or orderedlist
2720 Dst
= Question
->BufferValue
;
2723 // Other type of Questions
2725 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2728 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2729 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2732 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2733 // <ConfigHdr> + "&" + <VariableName>
2735 if (IsBufferStorage
) {
2736 Length
= StrLen (Storage
->ConfigHdr
);
2737 Length
+= StrLen (Question
->BlockName
);
2739 Length
= StrLen (Storage
->ConfigHdr
);
2740 Length
+= StrLen (Question
->VariableName
) + 1;
2742 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2743 ASSERT (ConfigRequest
!= NULL
);
2745 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2746 if (IsBufferStorage
) {
2747 StrCat (ConfigRequest
, Question
->BlockName
);
2749 StrCat (ConfigRequest
, L
"&");
2750 StrCat (ConfigRequest
, Question
->VariableName
);
2753 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2754 FormSet
->ConfigAccess
,
2759 if (EFI_ERROR (Status
)) {
2764 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2765 // Get the default configuration string according to the default ID.
2767 Status
= mHiiConfigRouting
->GetAltConfig (
2773 &DefaultId
, // it can be NULL to get the current setting.
2778 // The required setting can't be found. So, it is not required to be validated and set.
2780 if (EFI_ERROR (Status
)) {
2785 // Skip <ConfigRequest>
2787 if (IsBufferStorage
) {
2788 Value
= StrStr (ConfigResp
, L
"&VALUE");
2789 ASSERT (Value
!= NULL
);
2795 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2796 ASSERT (Value
!= NULL
);
2798 Value
= Value
+ StrLen (Question
->VariableName
);
2800 if (*Value
!= '=') {
2801 Status
= EFI_NOT_FOUND
;
2805 // Skip '=', point to value
2810 // Suppress <AltResp> if any
2813 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2818 LengthStr
= StrLen (Value
);
2819 if (!IsBufferStorage
&& IsString
) {
2820 StringPtr
= (CHAR16
*) Dst
;
2821 ZeroMem (TemStr
, sizeof (TemStr
));
2822 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2823 StrnCpy (TemStr
, Value
+ Index
, 4);
2824 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2827 // Add tailing L'\0' character
2829 StringPtr
[Index
/4] = L
'\0';
2831 ZeroMem (TemStr
, sizeof (TemStr
));
2832 for (Index
= 0; Index
< LengthStr
; Index
++) {
2833 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2834 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2835 if ((Index
& 1) == 0) {
2836 Dst
[Index
/2] = DigitUint8
;
2838 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2844 if (ConfigRequest
!= NULL
){
2845 FreePool (ConfigRequest
);
2848 if (ConfigResp
!= NULL
) {
2849 FreePool (ConfigResp
);
2852 if (Result
!= NULL
) {
2860 Get default Id value used for browser.
2862 @param DefaultId The default id value used by hii.
2864 @retval Browser used default value.
2868 GetDefaultIdForCallBack (
2872 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2873 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2874 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2875 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2876 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2877 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2878 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2879 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2880 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2881 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2882 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2883 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2890 Reset Question to its default value.
2892 @param FormSet The form set.
2893 @param Form The form.
2894 @param Question The question.
2895 @param DefaultId The Class of the default.
2897 @retval EFI_SUCCESS Question is reset to default value.
2901 GetQuestionDefault (
2902 IN FORM_BROWSER_FORMSET
*FormSet
,
2903 IN FORM_BROWSER_FORM
*Form
,
2904 IN FORM_BROWSER_STATEMENT
*Question
,
2910 QUESTION_DEFAULT
*Default
;
2911 QUESTION_OPTION
*Option
;
2912 EFI_HII_VALUE
*HiiValue
;
2914 EFI_STRING StrValue
;
2915 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2916 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2919 Status
= EFI_NOT_FOUND
;
2923 // Statement don't have storage, skip them
2925 if (Question
->QuestionId
== 0) {
2930 // There are Five ways to specify default value for a Question:
2931 // 1, use call back function (highest priority)
2932 // 2, use ExtractConfig function
2933 // 3, use nested EFI_IFR_DEFAULT
2934 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2935 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2937 HiiValue
= &Question
->HiiValue
;
2940 // Get Question defaut value from call back function.
2942 ConfigAccess
= FormSet
->ConfigAccess
;
2943 Action
= GetDefaultIdForCallBack (DefaultId
);
2944 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2945 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2946 Status
= ConfigAccess
->Callback (
2949 Question
->QuestionId
,
2954 if (!EFI_ERROR (Status
)) {
2960 // Get default value from altcfg string.
2962 if (ConfigAccess
!= NULL
) {
2963 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2964 if (!EFI_ERROR (Status
)) {
2970 // EFI_IFR_DEFAULT has highest priority
2972 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2973 Link
= GetFirstNode (&Question
->DefaultListHead
);
2974 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2975 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2977 if (Default
->DefaultId
== DefaultId
) {
2978 if (Default
->ValueExpression
!= NULL
) {
2980 // Default is provided by an Expression, evaluate it
2982 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2983 if (EFI_ERROR (Status
)) {
2987 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
2988 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
2989 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
2990 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
2991 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
2993 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
2994 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
2996 FreePool (Default
->ValueExpression
->Result
.Buffer
);
2998 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
2999 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3002 // Default value is embedded in EFI_IFR_DEFAULT
3004 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3007 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3008 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3009 if (StrValue
== NULL
) {
3010 return EFI_NOT_FOUND
;
3012 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3013 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3015 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3022 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3027 // EFI_ONE_OF_OPTION
3029 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3030 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3032 // OneOfOption could only provide Standard and Manufacturing default
3034 Link
= GetFirstNode (&Question
->OptionListHead
);
3035 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3036 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3037 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3039 if ((Option
->SuppressExpression
!= NULL
) &&
3040 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3044 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3045 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3047 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3056 // EFI_IFR_CHECKBOX - lowest priority
3058 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3059 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3061 // Checkbox could only provide Standard and Manufacturing default
3063 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3064 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3066 HiiValue
->Value
.b
= TRUE
;
3068 HiiValue
->Value
.b
= FALSE
;
3076 // For Questions without default
3078 Status
= EFI_NOT_FOUND
;
3079 switch (Question
->Operand
) {
3080 case EFI_IFR_NUMERIC_OP
:
3082 // Take minimum value as numeric default value
3084 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3085 HiiValue
->Value
.u64
= Question
->Minimum
;
3086 Status
= EFI_SUCCESS
;
3090 case EFI_IFR_ONE_OF_OP
:
3092 // Take first oneof option as oneof's default value
3094 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3095 Link
= GetFirstNode (&Question
->OptionListHead
);
3096 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3097 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3098 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3100 if ((Option
->SuppressExpression
!= NULL
) &&
3101 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3105 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3106 Status
= EFI_SUCCESS
;
3112 case EFI_IFR_ORDERED_LIST_OP
:
3114 // Take option sequence in IFR as ordered list's default value
3117 Link
= GetFirstNode (&Question
->OptionListHead
);
3118 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3119 Status
= EFI_SUCCESS
;
3120 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3121 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3123 if ((Option
->SuppressExpression
!= NULL
) &&
3124 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3128 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3131 if (Index
>= Question
->MaxContainers
) {
3146 Reset Questions to their initial value or default value in a Form, Formset or System.
3148 GetDefaultValueScope parameter decides which questions will reset
3149 to its default value.
3151 @param FormSet FormSet data structure.
3152 @param Form Form data structure.
3153 @param DefaultId The Class of the default.
3154 @param SettingScope Setting Scope for Default action.
3155 @param GetDefaultValueScope Get default value scope.
3156 @param Storage Get default value only for this storage.
3157 @param RetrieveValueFirst Whether call the retrieve call back to
3158 get the initial value before get default
3161 @retval EFI_SUCCESS The function completed successfully.
3162 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3167 IN FORM_BROWSER_FORMSET
*FormSet
,
3168 IN FORM_BROWSER_FORM
*Form
,
3169 IN UINT16 DefaultId
,
3170 IN BROWSER_SETTING_SCOPE SettingScope
,
3171 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3172 IN FORMSET_STORAGE
*Storage OPTIONAL
,
3173 IN BOOLEAN RetrieveValueFirst
3177 LIST_ENTRY
*FormLink
;
3179 FORM_BROWSER_STATEMENT
*Question
;
3180 FORM_BROWSER_FORMSET
*BackUpFormSet
;
3181 FORM_BROWSER_FORMSET
*LocalFormSet
;
3182 EFI_HII_HANDLE
*HiiHandles
;
3186 Status
= EFI_SUCCESS
;
3189 // Check the supported setting level.
3191 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3192 return EFI_UNSUPPORTED
;
3195 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3196 return EFI_UNSUPPORTED
;
3199 if (SettingScope
== FormLevel
) {
3201 // Extract Form default
3203 Link
= GetFirstNode (&Form
->StatementListHead
);
3204 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3205 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3206 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3209 // If get default value only for this storage, check the storage first.
3211 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3216 // If get default value only for no storage question, just skip the question which has storage.
3218 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3223 // If Question is disabled, don't reset it to default
3225 if (Question
->Expression
!= NULL
) {
3226 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3231 if (RetrieveValueFirst
) {
3233 // Call the Retrieve call back to get the initial question value.
3235 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3239 // If not request to get the initial value or get initial value fail, then get default value.
3241 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3242 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3243 if (EFI_ERROR (Status
)) {
3249 // Synchronize Buffer storage's Edit buffer
3251 if ((Question
->Storage
!= NULL
) &&
3252 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3253 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3255 // Update Form NV flag.
3257 Form
->NvUpdateRequired
= TRUE
;
3260 } else if (SettingScope
== FormSetLevel
) {
3261 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3262 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3263 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3264 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3265 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3267 } else if (SettingScope
== SystemLevel
) {
3269 // Open all FormSet by locate HII packages.
3270 // Initiliaze the maintain FormSet to store default data as back up data.
3272 BackUpFormSet
= gOldFormSet
;
3276 // Get all the Hii handles
3278 HiiHandles
= HiiGetHiiHandles (NULL
);
3279 ASSERT (HiiHandles
!= NULL
);
3282 // Search for formset of each class type
3284 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3286 // Check HiiHandles[Index] does exist in global maintain list.
3288 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3293 // Initilize FormSet Setting
3295 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3296 ASSERT (LocalFormSet
!= NULL
);
3297 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3298 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
, FALSE
);
3299 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3300 DestroyFormSet (LocalFormSet
);
3303 Status
= InitializeCurrentSetting (LocalFormSet
);
3304 if (EFI_ERROR (Status
)) {
3305 DestroyFormSet (LocalFormSet
);
3309 // Initilize Questions' Value
3311 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
3312 if (EFI_ERROR (Status
)) {
3313 DestroyFormSet (LocalFormSet
);
3318 // Add FormSet into the maintain list.
3320 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3324 // Free resources, and restore gOldFormSet and gClassOfVfr
3326 FreePool (HiiHandles
);
3327 gOldFormSet
= BackUpFormSet
;
3330 // Set Default Value for each FormSet in the maintain list.
3332 Link
= GetFirstNode (&gBrowserFormSetList
);
3333 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3334 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3335 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3336 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3344 Initialize Question's Edit copy from Storage.
3346 @param Selection Selection contains the information about
3347 the Selection, form and formset to be displayed.
3348 Selection action may be updated in retrieve callback.
3349 If Selection is NULL, only initialize Question value.
3350 @param FormSet FormSet data structure.
3351 @param Form Form data structure.
3353 @retval EFI_SUCCESS The function completed successfully.
3358 IN OUT UI_MENU_SELECTION
*Selection
,
3359 IN FORM_BROWSER_FORMSET
*FormSet
,
3360 IN FORM_BROWSER_FORM
*Form
3365 FORM_BROWSER_STATEMENT
*Question
;
3369 Link
= GetFirstNode (&Form
->StatementListHead
);
3370 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3371 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3374 // Initialize local copy of Value for each Question
3376 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3377 if (EFI_ERROR (Status
)) {
3381 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3382 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3386 // Call the Retrieve call back function for all questions.
3388 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3389 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3391 // Check QuestionValue does exist.
3393 StorageWidth
= Question
->StorageWidth
;
3394 if (Question
->BufferValue
!= NULL
) {
3395 BufferValue
= Question
->BufferValue
;
3397 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3401 // For efivarstore storage, initial question value first.
3403 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3404 Status
= gRT
->GetVariable (
3405 Question
->VariableName
,
3406 &Question
->Storage
->Guid
,
3413 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3416 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3423 Initialize Question's Edit copy from Storage for the whole Formset.
3425 @param Selection Selection contains the information about
3426 the Selection, form and formset to be displayed.
3427 Selection action may be updated in retrieve callback.
3428 If Selection is NULL, only initialize Question value.
3429 @param FormSet FormSet data structure.
3431 @retval EFI_SUCCESS The function completed successfully.
3436 IN OUT UI_MENU_SELECTION
*Selection
,
3437 IN FORM_BROWSER_FORMSET
*FormSet
3442 FORM_BROWSER_FORM
*Form
;
3444 Link
= GetFirstNode (&FormSet
->FormListHead
);
3445 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3446 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3449 // Initialize local copy of Value for each Form
3451 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3452 if (EFI_ERROR (Status
)) {
3456 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3463 Fill storage's edit copy with settings requested from Configuration Driver.
3465 @param FormSet FormSet data structure.
3466 @param Storage Buffer Storage.
3468 @retval EFI_SUCCESS The function completed successfully.
3473 IN FORM_BROWSER_FORMSET
*FormSet
,
3474 IN FORMSET_STORAGE
*Storage
3478 EFI_STRING Progress
;
3482 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3486 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3487 Status
= gRT
->GetVariable (
3491 (UINTN
*)&Storage
->Size
,
3497 if (FormSet
->ConfigAccess
== NULL
) {
3498 return EFI_NOT_FOUND
;
3501 if (Storage
->ElementCount
== 0) {
3503 // Skip if there is no RequestElement
3509 // Request current settings from Configuration Driver
3511 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3512 FormSet
->ConfigAccess
,
3513 Storage
->ConfigRequest
,
3517 if (EFI_ERROR (Status
)) {
3522 // Convert Result from <ConfigAltResp> to <ConfigResp>
3524 StrPtr
= StrStr (Result
, L
"&GUID=");
3525 if (StrPtr
!= NULL
) {
3529 Status
= ConfigRespToStorage (Storage
, Result
);
3536 Copy uncommitted data from source Storage to destination Storage.
3538 @param Dst Target Storage for uncommitted data.
3539 @param Src Source Storage for uncommitted data.
3541 @retval EFI_SUCCESS The function completed successfully.
3542 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
3547 IN OUT FORMSET_STORAGE
*Dst
,
3548 IN FORMSET_STORAGE
*Src
3552 NAME_VALUE_NODE
*Node
;
3554 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
3555 return EFI_INVALID_PARAMETER
;
3558 switch (Src
->Type
) {
3559 case EFI_HII_VARSTORE_BUFFER
:
3560 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3561 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
3562 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
3565 case EFI_HII_VARSTORE_NAME_VALUE
:
3566 Link
= GetFirstNode (&Src
->NameValueListHead
);
3567 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
3568 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3570 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, GetSetValueWithEditBuffer
);
3571 SetValueByName (Dst
, Node
->Name
, Node
->Value
, GetSetValueWithBuffer
);
3573 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
3577 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3586 Get old question value from the saved formset.
3588 @param Statement The question which need to get old question value.
3589 @param OldFormSet FormSet data structure saved in the list.
3593 GetOldQuestionValue (
3594 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
3595 IN FORM_BROWSER_FORMSET
*OldFormSet
3598 LIST_ENTRY
*FormLink
;
3600 FORM_BROWSER_STATEMENT
*Question
;
3601 FORM_BROWSER_FORM
*Form
;
3603 FormLink
= GetFirstNode (&OldFormSet
->FormListHead
);
3604 while (!IsNull (&OldFormSet
->FormListHead
, FormLink
)) {
3605 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3606 FormLink
= GetNextNode (&OldFormSet
->FormListHead
, FormLink
);
3608 Link
= GetFirstNode (&Form
->StatementListHead
);
3609 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3610 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3611 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3613 if (Question
->QuestionId
!= Statement
->QuestionId
) {
3617 CopyMem (&Statement
->HiiValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3624 Get old question value from the saved formset, all these questions not have
3627 @param FormSet FormSet data structure which is used now.
3628 @param OldFormSet FormSet data structure saved in the list.
3632 CopyOldValueForNoStorageQst (
3633 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
3634 IN FORM_BROWSER_FORMSET
*OldFormSet
3637 LIST_ENTRY
*FormLink
;
3639 FORM_BROWSER_STATEMENT
*Question
;
3640 FORM_BROWSER_FORM
*Form
;
3642 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3643 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3644 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3645 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3647 Link
= GetFirstNode (&Form
->StatementListHead
);
3648 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3649 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3650 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3652 if (Question
->Storage
== NULL
) {
3653 GetOldQuestionValue (Question
, OldFormSet
);
3660 Get current setting of Questions.
3662 @param FormSet FormSet data structure.
3664 @retval EFI_SUCCESS The function completed successfully.
3668 InitializeCurrentSetting (
3669 IN OUT FORM_BROWSER_FORMSET
*FormSet
3674 FORMSET_STORAGE
*Storage
;
3675 FORMSET_STORAGE
*StorageSrc
;
3676 FORMSET_STORAGE
*OldStorage
;
3677 FORM_BROWSER_FORM
*Form
;
3678 FORM_BROWSER_FORM
*Form2
;
3682 // Extract default from IFR binary for no storage questions.
3684 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
3687 // Request current settings from Configuration Driver
3689 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3690 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3691 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3694 if (gOldFormSet
!= NULL
) {
3696 // Try to find the Storage in backup formset gOldFormSet
3698 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3699 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3700 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3702 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3703 OldStorage
= StorageSrc
;
3707 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3711 if (OldStorage
== NULL
) {
3713 // Storage is not found in backup formset, request it from ConfigDriver
3715 Status
= LoadStorage (FormSet
, Storage
);
3717 if (EFI_ERROR (Status
)) {
3719 // If get last time changed value failed, extract default from IFR binary
3721 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3723 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3724 // in current situation.
3726 UpdateNvInfoInForm (FormSet
, FALSE
);
3730 // Now Edit Buffer is filled with default values(lower priority) or current
3731 // settings(higher priority), sychronize it to shadow Buffer
3733 SynchronizeStorage (Storage
, TRUE
);
3736 // Storage found in backup formset, use it
3738 Status
= CopyStorage (Storage
, OldStorage
);
3741 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3745 // If has old formset, get the old nv update status.
3747 if (gOldFormSet
!= NULL
) {
3748 Link
= GetFirstNode (&FormSet
->FormListHead
);
3749 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3750 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3752 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3753 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3754 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3756 if (Form
->FormId
== Form2
->FormId
) {
3757 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3761 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3763 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3772 Fetch the Ifr binary data of a FormSet.
3774 @param Handle PackageList Handle
3775 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3776 specified (NULL or zero GUID), take the first
3777 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3778 found in package list.
3779 On output, GUID of the formset found(if not NULL).
3780 @param BinaryLength The length of the FormSet IFR binary.
3781 @param BinaryData The buffer designed to receive the FormSet.
3783 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3784 BufferLength was updated.
3785 @retval EFI_INVALID_PARAMETER The handle is unknown.
3786 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3787 be found with the requested FormId.
3792 IN EFI_HII_HANDLE Handle
,
3793 IN OUT EFI_GUID
*FormSetGuid
,
3794 OUT UINTN
*BinaryLength
,
3795 OUT UINT8
**BinaryData
3799 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3805 UINT32 PackageListLength
;
3806 EFI_HII_PACKAGE_HEADER PackageHeader
;
3808 UINT8 NumberOfClassGuid
;
3809 BOOLEAN ClassGuidMatch
;
3810 EFI_GUID
*ClassGuid
;
3811 EFI_GUID
*ComparingGuid
;
3815 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3818 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3820 if (FormSetGuid
== NULL
) {
3821 ComparingGuid
= &gZeroGuid
;
3823 ComparingGuid
= FormSetGuid
;
3827 // Get HII PackageList
3830 HiiPackageList
= NULL
;
3831 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3832 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3833 HiiPackageList
= AllocatePool (BufferSize
);
3834 ASSERT (HiiPackageList
!= NULL
);
3836 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3838 if (EFI_ERROR (Status
)) {
3841 ASSERT (HiiPackageList
!= NULL
);
3844 // Get Form package from this HII package List
3846 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3848 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3850 ClassGuidMatch
= FALSE
;
3851 while (Offset
< PackageListLength
) {
3852 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3853 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3855 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3857 // Search FormSet in this Form Package
3859 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3860 while (Offset2
< PackageHeader
.Length
) {
3861 OpCodeData
= Package
+ Offset2
;
3863 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3865 // Try to compare against formset GUID
3867 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3868 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3872 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3874 // Try to compare against formset class GUID
3876 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3877 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3878 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3879 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3880 ClassGuidMatch
= TRUE
;
3884 if (ClassGuidMatch
) {
3887 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3888 ClassGuidMatch
= TRUE
;
3893 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3896 if (Offset2
< PackageHeader
.Length
) {
3898 // Target formset found
3904 Offset
+= PackageHeader
.Length
;
3907 if (Offset
>= PackageListLength
) {
3909 // Form package not found in this Package List
3911 FreePool (HiiPackageList
);
3912 return EFI_NOT_FOUND
;
3915 if (FormSetGuid
!= NULL
) {
3917 // Return the FormSet GUID
3919 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3923 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3924 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3925 // of the Form Package.
3927 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3928 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3930 FreePool (HiiPackageList
);
3932 if (*BinaryData
== NULL
) {
3933 return EFI_OUT_OF_RESOURCES
;
3941 Initialize the internal data structure of a FormSet.
3943 @param Handle PackageList Handle
3944 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3945 specified (NULL or zero GUID), take the first
3946 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3947 found in package list.
3948 On output, GUID of the formset found(if not NULL).
3949 @param FormSet FormSet data structure.
3950 @param UpdateGlobalVar Whether need to update the global variable.
3952 @retval EFI_SUCCESS The function completed successfully.
3953 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3958 IN EFI_HII_HANDLE Handle
,
3959 IN OUT EFI_GUID
*FormSetGuid
,
3960 OUT FORM_BROWSER_FORMSET
*FormSet
,
3961 IN BOOLEAN UpdateGlobalVar
3965 EFI_HANDLE DriverHandle
;
3968 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3969 if (EFI_ERROR (Status
)) {
3973 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3974 FormSet
->HiiHandle
= Handle
;
3975 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3978 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3980 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3981 if (EFI_ERROR (Status
)) {
3984 FormSet
->DriverHandle
= DriverHandle
;
3985 Status
= gBS
->HandleProtocol (
3987 &gEfiHiiConfigAccessProtocolGuid
,
3988 (VOID
**) &FormSet
->ConfigAccess
3990 if (EFI_ERROR (Status
)) {
3992 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3993 // list, then there will be no configuration action required
3995 FormSet
->ConfigAccess
= NULL
;
3999 // Parse the IFR binary OpCodes
4001 Status
= ParseOpCodes (FormSet
);
4002 if (EFI_ERROR (Status
)) {
4007 // If not need to update the global variable, just return.
4009 if (!UpdateGlobalVar
) {
4014 // Set VFR type by FormSet SubClass field
4016 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
4017 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
4018 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
4022 // Set VFR type by FormSet class guid
4024 for (Index
= 0; Index
< 3; Index
++) {
4025 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
4026 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
4031 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
4032 gFrontPageHandle
= FormSet
->HiiHandle
;
4033 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
4037 // Match GUID to find out the function key setting. If match fail, use the default setting.
4039 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
4040 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
4042 // Update the function key setting.
4044 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
4053 Save globals used by previous call to SendForm(). SendForm() may be called from
4054 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4055 So, save globals of previous call to SendForm() and restore them upon exit.
4059 SaveBrowserContext (
4063 BROWSER_CONTEXT
*Context
;
4065 gBrowserContextCount
++;
4066 if (gBrowserContextCount
== 1) {
4068 // This is not reentry of SendForm(), no context to save
4073 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4074 ASSERT (Context
!= NULL
);
4076 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4079 // Save FormBrowser context
4081 Context
->BannerData
= gBannerData
;
4082 Context
->ClassOfVfr
= gClassOfVfr
;
4083 Context
->FunctionKeySetting
= gFunctionKeySetting
;
4084 Context
->ResetRequired
= gResetRequired
;
4085 Context
->Direction
= gDirection
;
4086 Context
->EnterString
= gEnterString
;
4087 Context
->EnterCommitString
= gEnterCommitString
;
4088 Context
->EnterEscapeString
= gEnterEscapeString
;
4089 Context
->EscapeString
= gEscapeString
;
4090 Context
->MoveHighlight
= gMoveHighlight
;
4091 Context
->MakeSelection
= gMakeSelection
;
4092 Context
->DecNumericInput
= gDecNumericInput
;
4093 Context
->HexNumericInput
= gHexNumericInput
;
4094 Context
->ToggleCheckBox
= gToggleCheckBox
;
4095 Context
->PromptForData
= gPromptForData
;
4096 Context
->PromptForPassword
= gPromptForPassword
;
4097 Context
->PromptForNewPassword
= gPromptForNewPassword
;
4098 Context
->ConfirmPassword
= gConfirmPassword
;
4099 Context
->ConfirmError
= gConfirmError
;
4100 Context
->PassowordInvalid
= gPassowordInvalid
;
4101 Context
->PressEnter
= gPressEnter
;
4102 Context
->EmptyString
= gEmptyString
;
4103 Context
->AreYouSure
= gAreYouSure
;
4104 Context
->YesResponse
= gYesResponse
;
4105 Context
->NoResponse
= gNoResponse
;
4106 Context
->MiniString
= gMiniString
;
4107 Context
->PlusString
= gPlusString
;
4108 Context
->MinusString
= gMinusString
;
4109 Context
->AdjustNumber
= gAdjustNumber
;
4110 Context
->SaveChanges
= gSaveChanges
;
4111 Context
->OptionMismatch
= gOptionMismatch
;
4112 Context
->FormSuppress
= gFormSuppress
;
4113 Context
->PromptBlockWidth
= gPromptBlockWidth
;
4114 Context
->OptionBlockWidth
= gOptionBlockWidth
;
4115 Context
->HelpBlockWidth
= gHelpBlockWidth
;
4116 Context
->OldFormSet
= gOldFormSet
;
4117 Context
->MenuRefreshHead
= gMenuRefreshHead
;
4119 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
4120 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
4123 // Insert to FormBrowser context list
4125 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4130 Restore globals used by previous call to SendForm().
4134 RestoreBrowserContext (
4139 BROWSER_CONTEXT
*Context
;
4141 ASSERT (gBrowserContextCount
!= 0);
4142 gBrowserContextCount
--;
4143 if (gBrowserContextCount
== 0) {
4145 // This is not reentry of SendForm(), no context to restore
4150 ASSERT (!IsListEmpty (&gBrowserContextList
));
4152 Link
= GetFirstNode (&gBrowserContextList
);
4153 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4156 // Restore FormBrowser context
4158 gBannerData
= Context
->BannerData
;
4159 gClassOfVfr
= Context
->ClassOfVfr
;
4160 gFunctionKeySetting
= Context
->FunctionKeySetting
;
4161 gResetRequired
= Context
->ResetRequired
;
4162 gDirection
= Context
->Direction
;
4163 gEnterString
= Context
->EnterString
;
4164 gEnterCommitString
= Context
->EnterCommitString
;
4165 gEnterEscapeString
= Context
->EnterEscapeString
;
4166 gEscapeString
= Context
->EscapeString
;
4167 gMoveHighlight
= Context
->MoveHighlight
;
4168 gMakeSelection
= Context
->MakeSelection
;
4169 gDecNumericInput
= Context
->DecNumericInput
;
4170 gHexNumericInput
= Context
->HexNumericInput
;
4171 gToggleCheckBox
= Context
->ToggleCheckBox
;
4172 gPromptForData
= Context
->PromptForData
;
4173 gPromptForPassword
= Context
->PromptForPassword
;
4174 gPromptForNewPassword
= Context
->PromptForNewPassword
;
4175 gConfirmPassword
= Context
->ConfirmPassword
;
4176 gConfirmError
= Context
->ConfirmError
;
4177 gPassowordInvalid
= Context
->PassowordInvalid
;
4178 gPressEnter
= Context
->PressEnter
;
4179 gEmptyString
= Context
->EmptyString
;
4180 gAreYouSure
= Context
->AreYouSure
;
4181 gYesResponse
= Context
->YesResponse
;
4182 gNoResponse
= Context
->NoResponse
;
4183 gMiniString
= Context
->MiniString
;
4184 gPlusString
= Context
->PlusString
;
4185 gMinusString
= Context
->MinusString
;
4186 gAdjustNumber
= Context
->AdjustNumber
;
4187 gSaveChanges
= Context
->SaveChanges
;
4188 gOptionMismatch
= Context
->OptionMismatch
;
4189 gFormSuppress
= Context
->FormSuppress
;
4190 gPromptBlockWidth
= Context
->PromptBlockWidth
;
4191 gOptionBlockWidth
= Context
->OptionBlockWidth
;
4192 gHelpBlockWidth
= Context
->HelpBlockWidth
;
4193 gOldFormSet
= Context
->OldFormSet
;
4194 gMenuRefreshHead
= Context
->MenuRefreshHead
;
4195 gProtocolNotFound
= Context
->ProtocolNotFound
;
4197 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
4198 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
4201 // Remove from FormBrowser context list
4203 RemoveEntryList (&Context
->Link
);
4204 gBS
->FreePool (Context
);
4208 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4210 @param Handle The Hii Handle.
4212 @return the found FormSet context. If no found, NULL will return.
4215 FORM_BROWSER_FORMSET
*
4216 GetFormSetFromHiiHandle (
4217 EFI_HII_HANDLE Handle
4221 FORM_BROWSER_FORMSET
*FormSet
;
4223 Link
= GetFirstNode (&gBrowserFormSetList
);
4224 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4225 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4226 if (FormSet
->HiiHandle
== Handle
) {
4229 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4236 Check whether the input HII handle is the FormSet that is being used.
4238 @param Handle The Hii Handle.
4240 @retval TRUE HII handle is being used.
4241 @retval FALSE HII handle is not being used.
4245 IsHiiHandleInBrowserContext (
4246 EFI_HII_HANDLE Handle
4250 BROWSER_CONTEXT
*Context
;
4253 // HiiHandle is Current FormSet.
4255 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
4260 // Check whether HiiHandle is in BrowserContext.
4262 Link
= GetFirstNode (&gBrowserContextList
);
4263 while (!IsNull (&gBrowserContextList
, Link
)) {
4264 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4265 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
4267 // HiiHandle is in BrowserContext
4271 Link
= GetNextNode (&gBrowserContextList
, Link
);
4278 Find the registered HotKey based on KeyData.
4280 @param[in] KeyData A pointer to a buffer that describes the keystroke
4281 information for the hot key.
4283 @return The registered HotKey context. If no found, NULL will return.
4286 GetHotKeyFromRegisterList (
4287 IN EFI_INPUT_KEY
*KeyData
4291 BROWSER_HOT_KEY
*HotKey
;
4293 Link
= GetFirstNode (&gBrowserHotKeyList
);
4294 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4295 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4296 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4299 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4306 Configure what scope the hot key will impact.
4307 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4308 If no scope is set, the default scope will be FormSet level.
4309 After all registered hot keys are removed, previous Scope can reset to another level.
4311 @param[in] Scope Scope level to be set.
4313 @retval EFI_SUCCESS Scope is set correctly.
4314 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4315 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4321 IN BROWSER_SETTING_SCOPE Scope
4324 if (Scope
>= MaxLevel
) {
4325 return EFI_INVALID_PARAMETER
;
4329 // When no hot key registered in system or on the first setting,
4330 // Scope can be set.
4332 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4333 gBrowserSettingScope
= Scope
;
4334 mBrowserScopeFirstSet
= FALSE
;
4335 } else if (Scope
!= gBrowserSettingScope
) {
4336 return EFI_UNSUPPORTED
;
4343 Register the hot key with its browser action, or unregistered the hot key.
4344 Only support hot key that is not printable character (control key, function key, etc.).
4345 If the action value is zero, the hot key will be unregistered if it has been registered.
4346 If the same hot key has been registered, the new action and help string will override the previous ones.
4348 @param[in] KeyData A pointer to a buffer that describes the keystroke
4349 information for the hot key. Its type is EFI_INPUT_KEY to
4350 be supported by all ConsoleIn devices.
4351 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4352 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4353 @param[in] HelpString Help string that describes the hot key information.
4354 Its value may be NULL for the unregistered hot key.
4356 @retval EFI_SUCCESS Hot key is registered or unregistered.
4357 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4358 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4359 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4364 IN EFI_INPUT_KEY
*KeyData
,
4366 IN UINT16 DefaultId
,
4367 IN EFI_STRING HelpString OPTIONAL
4370 BROWSER_HOT_KEY
*HotKey
;
4373 // Check input parameters.
4375 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4376 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4377 return EFI_INVALID_PARAMETER
;
4381 // Check whether the input KeyData is in BrowserHotKeyList.
4383 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4386 // Unregister HotKey
4388 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4389 if (HotKey
!= NULL
) {
4391 // The registered HotKey is found.
4392 // Remove it from List, and free its resource.
4394 RemoveEntryList (&HotKey
->Link
);
4395 FreePool (HotKey
->KeyData
);
4396 FreePool (HotKey
->HelpString
);
4400 // The registered HotKey is not found.
4402 return EFI_NOT_FOUND
;
4407 // Register HotKey into List.
4409 if (HotKey
== NULL
) {
4411 // Create new Key, and add it into List.
4413 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4414 ASSERT (HotKey
!= NULL
);
4415 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4416 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4417 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4421 // Fill HotKey information.
4423 HotKey
->Action
= Action
;
4424 HotKey
->DefaultId
= DefaultId
;
4425 if (HotKey
->HelpString
!= NULL
) {
4426 FreePool (HotKey
->HelpString
);
4428 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4434 Register Exit handler function.
4435 When more than one handler function is registered, the latter one will override the previous one.
4436 When NULL handler is specified, the previous Exit handler will be unregistered.
4438 @param[in] Handler Pointer to handler function.
4443 RegiserExitHandler (
4444 IN EXIT_HANDLER Handler
4447 ExitHandlerFunction
= Handler
;
4452 Create reminder to let user to choose save or discard the changed browser data.
4453 Caller can use it to actively check the changed browser data.
4455 @retval BROWSER_NO_CHANGES No browser data is changed.
4456 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4457 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4467 FORM_BROWSER_FORMSET
*FormSet
;
4468 BOOLEAN IsDataChanged
;
4469 UINT32 DataSavedAction
;
4470 CHAR16
*YesResponse
;
4472 CHAR16
*EmptyString
;
4473 CHAR16
*ChangeReminderString
;
4474 CHAR16
*SaveConfirmString
;
4477 DataSavedAction
= BROWSER_NO_CHANGES
;
4478 IsDataChanged
= FALSE
;
4479 Link
= GetFirstNode (&gBrowserFormSetList
);
4480 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4481 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4482 if (IsNvUpdateRequired (FormSet
)) {
4483 IsDataChanged
= TRUE
;
4486 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4490 // No data is changed. No save is required.
4492 if (!IsDataChanged
) {
4493 return DataSavedAction
;
4497 // If data is changed, prompt user
4499 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4501 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4502 ASSERT (YesResponse
!= NULL
);
4503 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4504 ASSERT (NoResponse
!= NULL
);
4505 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4506 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4507 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4510 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4512 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4513 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4517 // If the user hits the YesResponse key
4519 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4520 SubmitForm (NULL
, NULL
, SystemLevel
);
4521 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4523 DiscardForm (NULL
, NULL
, SystemLevel
);
4524 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4525 gResetRequired
= FALSE
;
4528 FreePool (YesResponse
);
4529 FreePool (NoResponse
);
4530 FreePool (EmptyString
);
4531 FreePool (SaveConfirmString
);
4532 FreePool (ChangeReminderString
);
4534 return DataSavedAction
;