2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2012, 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
;
36 UINTN gBrowserContextCount
= 0;
37 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
38 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
39 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
41 BANNER_DATA
*gBannerData
;
42 EFI_HII_HANDLE gFrontPageHandle
;
44 UINTN gFunctionKeySetting
;
45 BOOLEAN gResetRequired
;
46 EFI_HII_HANDLE gHiiHandle
;
48 EFI_SCREEN_DESCRIPTOR gScreenDimensions
;
49 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
50 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
51 EXIT_HANDLER ExitHandlerFunction
= NULL
;
55 // Browser Global Strings
58 CHAR16
*gDiscardFailed
;
59 CHAR16
*gDefaultFailed
;
61 CHAR16
*gEnterCommitString
;
62 CHAR16
*gEnterEscapeString
;
63 CHAR16
*gEscapeString
;
64 CHAR16
*gMoveHighlight
;
65 CHAR16
*gMakeSelection
;
66 CHAR16
*gDecNumericInput
;
67 CHAR16
*gHexNumericInput
;
68 CHAR16
*gToggleCheckBox
;
69 CHAR16
*gPromptForData
;
70 CHAR16
*gPromptForPassword
;
71 CHAR16
*gPromptForNewPassword
;
72 CHAR16
*gConfirmPassword
;
73 CHAR16
*gConfirmError
;
74 CHAR16
*gPassowordInvalid
;
83 CHAR16
*gAdjustNumber
;
85 CHAR16
*gOptionMismatch
;
86 CHAR16
*gFormSuppress
;
88 CHAR16
*mUnknownString
= L
"!";
90 CHAR16 gPromptBlockWidth
;
91 CHAR16 gOptionBlockWidth
;
92 CHAR16 gHelpBlockWidth
;
94 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
95 EFI_GUID gSetupBrowserGuid
= {
96 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
99 FORM_BROWSER_FORMSET
*gOldFormSet
= NULL
;
101 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
121 NONE_FUNCTION_KEY_SETTING
142 NONE_FUNCTION_KEY_SETTING
163 NONE_FUNCTION_KEY_SETTING
166 // BMM File Explorer FormSet.
184 NONE_FUNCTION_KEY_SETTING
189 This is the routine which an external caller uses to direct the browser
190 where to obtain it's information.
193 @param This The Form Browser protocol instanse.
194 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
195 display a list of the formsets for the handles specified.
196 @param HandleCount The number of Handles specified in Handle.
197 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
198 field in the EFI_IFR_FORM_SET op-code for the specified
199 forms-based package. If FormSetGuid is NULL, then this
200 function will display the first found forms package.
201 @param FormId This field specifies which EFI_IFR_FORM to render as the first
202 displayable page. If this field has a value of 0x0000, then
203 the forms browser will render the specified forms in their encoded order.
204 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
206 @param ActionRequest Points to the action recommended by the form.
208 @retval EFI_SUCCESS The function completed successfully.
209 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
210 @retval EFI_NOT_FOUND No valid forms could be found to display.
216 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
217 IN EFI_HII_HANDLE
*Handles
,
218 IN UINTN HandleCount
,
219 IN EFI_GUID
*FormSetGuid
, OPTIONAL
220 IN UINT16 FormId
, OPTIONAL
221 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
222 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
226 UI_MENU_SELECTION
*Selection
;
228 FORM_BROWSER_FORMSET
*FormSet
;
232 // Calculate total number of Register HotKeys.
235 Link
= GetFirstNode (&gBrowserHotKeyList
);
236 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
237 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
241 // Show three HotKeys help information on one ROW.
243 gFooterHeight
= FOOTER_HEIGHT
+ (Index
/ 3);
246 // Save globals used by SendForm()
248 SaveBrowserContext ();
250 gResetRequired
= FALSE
;
251 Status
= EFI_SUCCESS
;
252 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
255 // Seed the dimensions in the global
257 gST
->ConOut
->QueryMode (
259 gST
->ConOut
->Mode
->Mode
,
260 &gScreenDimensions
.RightColumn
,
261 &gScreenDimensions
.BottomRow
264 if (ScreenDimensions
!= NULL
) {
266 // Check local dimension vs. global dimension.
268 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
269 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
271 Status
= EFI_INVALID_PARAMETER
;
275 // Local dimension validation.
277 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
278 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
279 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
281 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
282 SCROLL_ARROW_HEIGHT
*
284 FRONT_PAGE_HEADER_HEIGHT
+
289 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
291 Status
= EFI_INVALID_PARAMETER
;
297 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
298 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
299 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
302 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
304 InitializeBrowserStrings ();
306 gFunctionKeySetting
= ENABLE_FUNCTION_KEY_SETTING
;
309 // Ensure we are in Text mode
311 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
313 for (Index
= 0; Index
< HandleCount
; Index
++) {
314 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
315 ASSERT (Selection
!= NULL
);
317 Selection
->Handle
= Handles
[Index
];
318 if (FormSetGuid
!= NULL
) {
319 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
320 Selection
->FormId
= FormId
;
322 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
326 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
327 ASSERT (FormSet
!= NULL
);
330 // Initialize internal data structures of FormSet
332 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
, TRUE
);
333 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
334 DestroyFormSet (FormSet
);
337 Selection
->FormSet
= FormSet
;
340 // Try to find pre FormSet in the maintain backup list.
342 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
345 // Display this formset
347 gCurrentSelection
= Selection
;
349 Status
= SetupBrowser (Selection
);
351 gCurrentSelection
= NULL
;
353 if (EFI_ERROR (Status
)) {
357 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
359 if (gOldFormSet
!= NULL
) {
361 // If no data is changed, don't need to save current FormSet into the maintain list.
363 if (!IsNvUpdateRequired (gOldFormSet
)) {
364 RemoveEntryList (&gOldFormSet
->Link
);
365 DestroyFormSet (gOldFormSet
);
370 FreePool (Selection
);
373 if (ActionRequest
!= NULL
) {
374 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
375 if (gResetRequired
) {
376 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
380 FreeBrowserStrings ();
382 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
383 gST
->ConOut
->ClearScreen (gST
->ConOut
);
387 // Restore globals used by SendForm()
389 RestoreBrowserContext ();
396 This function is called by a callback handler to retrieve uncommitted state
397 data from the browser.
399 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
401 @param ResultsDataSize A pointer to the size of the buffer associated
403 @param ResultsData A string returned from an IFR browser or
404 equivalent. The results string will have no
405 routing information in them.
406 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
407 (if RetrieveData = TRUE) data from the uncommitted
408 browser state information or set (if RetrieveData
409 = FALSE) data in the uncommitted browser state
411 @param VariableGuid An optional field to indicate the target variable
413 @param VariableName An optional field to indicate the target
414 human-readable variable name.
416 @retval EFI_SUCCESS The results have been distributed or are awaiting
418 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
419 contain the results data.
425 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
426 IN OUT UINTN
*ResultsDataSize
,
427 IN OUT EFI_STRING ResultsData
,
428 IN BOOLEAN RetrieveData
,
429 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
430 IN CONST CHAR16
*VariableName OPTIONAL
435 FORMSET_STORAGE
*Storage
;
436 FORM_BROWSER_FORMSET
*FormSet
;
443 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
444 return EFI_INVALID_PARAMETER
;
447 if (gCurrentSelection
== NULL
) {
448 return EFI_NOT_READY
;
453 FormSet
= gCurrentSelection
->FormSet
;
456 // Find target storage
458 Link
= GetFirstNode (&FormSet
->StorageListHead
);
459 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
460 return EFI_UNSUPPORTED
;
463 if (VariableGuid
!= NULL
) {
465 // Try to find target storage
468 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
469 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
470 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
472 if (CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
473 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
474 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
476 // Buffer storage require both GUID and Name
478 if (VariableName
== NULL
) {
479 return EFI_NOT_FOUND
;
482 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
492 return EFI_NOT_FOUND
;
496 // GUID/Name is not specified, take the first storage in FormSet
498 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
503 // Skip if there is no RequestElement
505 if (Storage
->ElementCount
== 0) {
510 // Generate <ConfigResp>
512 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
513 if (EFI_ERROR (Status
)) {
518 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
520 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
522 BufferSize
= StrSize (StrPtr
);
523 if (*ResultsDataSize
< BufferSize
) {
524 *ResultsDataSize
= BufferSize
;
526 FreePool (ConfigResp
);
527 return EFI_BUFFER_TOO_SMALL
;
530 *ResultsDataSize
= BufferSize
;
531 CopyMem (ResultsData
, StrPtr
, BufferSize
);
533 FreePool (ConfigResp
);
536 // Prepare <ConfigResp>
538 TmpSize
= StrLen (ResultsData
);
539 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
540 ConfigResp
= AllocateZeroPool (BufferSize
);
541 ASSERT (ConfigResp
!= NULL
);
543 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
544 StrCat (ConfigResp
, L
"&");
545 StrCat (ConfigResp
, ResultsData
);
548 // Update Browser uncommited data
550 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
551 if (EFI_ERROR (Status
)) {
560 Notify function will remove the formset in the maintain list
561 once this formset is removed.
563 Functions which are registered to receive notification of
564 database events have this prototype. The actual event is encoded
565 in NotifyType. The following table describes how PackageType,
566 PackageGuid, Handle, and Package are used for each of the
569 @param PackageType Package type of the notification.
571 @param PackageGuid If PackageType is
572 EFI_HII_PACKAGE_TYPE_GUID, then this is
573 the pointer to the GUID from the Guid
574 field of EFI_HII_PACKAGE_GUID_HEADER.
575 Otherwise, it must be NULL.
577 @param Package Points to the package referred to by the
578 notification Handle The handle of the package
579 list which contains the specified package.
581 @param Handle The HII handle.
583 @param NotifyType The type of change concerning the
585 EFI_HII_DATABASE_NOTIFY_TYPE.
590 FormsetRemoveNotify (
591 IN UINT8 PackageType
,
592 IN CONST EFI_GUID
*PackageGuid
,
593 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
594 IN EFI_HII_HANDLE Handle
,
595 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
598 FORM_BROWSER_FORMSET
*FormSet
;
601 // Ignore the update for current using formset, which is handled by another notify function.
603 if (IsHiiHandleInBrowserContext (Handle
)) {
608 // Remove the backup FormSet data when the Form Package is removed.
610 FormSet
= GetFormSetFromHiiHandle (Handle
);
611 if (FormSet
!= NULL
) {
612 RemoveEntryList (&FormSet
->Link
);
613 DestroyFormSet (FormSet
);
620 Initialize Setup Browser driver.
622 @param ImageHandle The image handle.
623 @param SystemTable The system table.
625 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
626 @return Other value if failed to initialize the Setup Browser module.
632 IN EFI_HANDLE ImageHandle
,
633 IN EFI_SYSTEM_TABLE
*SystemTable
637 EFI_HANDLE NotifyHandle
;
638 EFI_INPUT_KEY DefaultHotKey
;
639 EFI_STRING HelpString
;
642 // Locate required Hii relative protocols
644 Status
= gBS
->LocateProtocol (
645 &gEfiHiiDatabaseProtocolGuid
,
647 (VOID
**) &mHiiDatabase
649 ASSERT_EFI_ERROR (Status
);
651 Status
= gBS
->LocateProtocol (
652 &gEfiHiiStringProtocolGuid
,
654 (VOID
**) &mHiiString
656 ASSERT_EFI_ERROR (Status
);
658 Status
= gBS
->LocateProtocol (
659 &gEfiHiiConfigRoutingProtocolGuid
,
661 (VOID
**) &mHiiConfigRouting
663 ASSERT_EFI_ERROR (Status
);
666 // Publish our HII data
668 gHiiHandle
= HiiAddPackages (
674 ASSERT (gHiiHandle
!= NULL
);
677 // Initialize Driver private data
679 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
680 ASSERT (gBannerData
!= NULL
);
683 // Initialize generic help strings.
685 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
686 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
687 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
690 // Install FormBrowser2 protocol
692 mPrivateData
.Handle
= NULL
;
693 Status
= gBS
->InstallProtocolInterface (
694 &mPrivateData
.Handle
,
695 &gEfiFormBrowser2ProtocolGuid
,
696 EFI_NATIVE_INTERFACE
,
697 &mPrivateData
.FormBrowser2
699 ASSERT_EFI_ERROR (Status
);
702 // Install default HotKey F10 for Save
704 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
705 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
706 DefaultHotKey
.ScanCode
= SCAN_F10
;
707 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
708 FreePool (HelpString
);
710 // Install default HotKey F9 for Reset To Defaults
712 DefaultHotKey
.ScanCode
= SCAN_F9
;
713 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
714 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
715 FreePool (HelpString
);
718 // Install FormBrowserEx protocol
720 mPrivateData
.Handle
= NULL
;
721 Status
= gBS
->InstallProtocolInterface (
722 &mPrivateData
.Handle
,
723 &gEfiFormBrowserExProtocolGuid
,
724 EFI_NATIVE_INTERFACE
,
725 &mPrivateData
.FormBrowserEx
727 ASSERT_EFI_ERROR (Status
);
730 // Register notify for Form package remove
732 Status
= mHiiDatabase
->RegisterPackageNotify (
734 EFI_HII_PACKAGE_FORMS
,
737 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
740 ASSERT_EFI_ERROR (Status
);
747 Create a new string in HII Package List.
749 @param String The String to be added
750 @param HiiHandle The package list in the HII database to insert the
753 @return The output string.
759 IN EFI_HII_HANDLE HiiHandle
762 EFI_STRING_ID StringId
;
764 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
765 ASSERT (StringId
!= 0);
772 Delete a string from HII Package List.
774 @param StringId Id of the string in HII database.
775 @param HiiHandle The HII package list handle.
777 @retval EFI_SUCCESS The string was deleted successfully.
782 IN EFI_STRING_ID StringId
,
783 IN EFI_HII_HANDLE HiiHandle
788 NullChar
= CHAR_NULL
;
789 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
795 Get the string based on the StringId and HII Package List Handle.
797 @param Token The String's ID.
798 @param HiiHandle The package list in the HII database to search for
799 the specified string.
801 @return The output string.
806 IN EFI_STRING_ID Token
,
807 IN EFI_HII_HANDLE HiiHandle
812 if (HiiHandle
== NULL
) {
816 String
= HiiGetString (HiiHandle
, Token
, NULL
);
817 if (String
== NULL
) {
818 String
= AllocateCopyPool (sizeof (mUnknownString
), mUnknownString
);
819 ASSERT (String
!= NULL
);
821 return (CHAR16
*) String
;
826 Allocate new memory and then copy the Unicode string Source to Destination.
828 @param Dest Location to copy string
829 @param Src String to copy
834 IN OUT CHAR16
**Dest
,
841 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
842 ASSERT (*Dest
!= NULL
);
847 Allocate new memory and concatinate Source on the end of Destination.
849 @param Dest String to added to the end of.
850 @param Src String to concatinate.
855 IN OUT CHAR16
**Dest
,
863 NewStringCpy (Dest
, Src
);
867 TmpSize
= StrSize (*Dest
);
868 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
869 ASSERT (NewString
!= NULL
);
871 StrCpy (NewString
, *Dest
);
872 StrCat (NewString
, Src
);
880 Synchronize or restore Storage's Edit copy and Shadow copy.
882 @param Storage The Storage to be synchronized.
883 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
885 if TRUE, copy the editbuffer to the buffer.
886 if FALSE, copy the buffer to the editbuffer.
891 IN FORMSET_STORAGE
*Storage
,
892 IN BOOLEAN SyncOrRestore
896 NAME_VALUE_NODE
*Node
;
898 switch (Storage
->Type
) {
899 case EFI_HII_VARSTORE_BUFFER
:
900 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
902 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
904 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
908 case EFI_HII_VARSTORE_NAME_VALUE
:
909 Link
= GetFirstNode (&Storage
->NameValueListHead
);
910 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
911 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
914 NewStringCpy (&Node
->Value
, Node
->EditValue
);
916 NewStringCpy (&Node
->EditValue
, Node
->Value
);
919 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
923 case EFI_HII_VARSTORE_EFI_VARIABLE
:
931 Get Value for given Name from a NameValue Storage.
933 @param Storage The NameValue Storage.
934 @param Name The Name.
935 @param Value The retured Value.
937 @retval EFI_SUCCESS Value found for given Name.
938 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
943 IN FORMSET_STORAGE
*Storage
,
945 IN OUT CHAR16
**Value
949 NAME_VALUE_NODE
*Node
;
953 Link
= GetFirstNode (&Storage
->NameValueListHead
);
954 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
955 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
957 if (StrCmp (Name
, Node
->Name
) == 0) {
958 NewStringCpy (Value
, Node
->EditValue
);
962 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
965 return EFI_NOT_FOUND
;
970 Set Value of given Name in a NameValue Storage.
972 @param Storage The NameValue Storage.
973 @param Name The Name.
974 @param Value The Value to set.
975 @param Edit Whether update editValue or Value.
977 @retval EFI_SUCCESS Value found for given Name.
978 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
983 IN FORMSET_STORAGE
*Storage
,
990 NAME_VALUE_NODE
*Node
;
993 Link
= GetFirstNode (&Storage
->NameValueListHead
);
994 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
995 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
997 if (StrCmp (Name
, Node
->Name
) == 0) {
999 Buffer
= Node
->EditValue
;
1001 Buffer
= Node
->Value
;
1003 if (Buffer
!= NULL
) {
1006 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1007 ASSERT (Buffer
!= NULL
);
1009 Node
->EditValue
= Buffer
;
1011 Node
->Value
= Buffer
;
1016 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1019 return EFI_NOT_FOUND
;
1024 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1026 @param Buffer The Storage to be conveted.
1027 @param ConfigResp The returned <ConfigResp>.
1028 @param SingleForm Whether update data for single form or formset level.
1030 @retval EFI_SUCCESS Convert success.
1031 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1035 StorageToConfigResp (
1037 IN CHAR16
**ConfigResp
,
1038 IN BOOLEAN SingleForm
1042 EFI_STRING Progress
;
1044 NAME_VALUE_NODE
*Node
;
1045 CHAR16
*ConfigRequest
;
1046 FORMSET_STORAGE
*Storage
;
1047 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
1049 Status
= EFI_SUCCESS
;
1051 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
1052 Storage
= ConfigInfo
->Storage
;
1053 ConfigRequest
= ConfigInfo
->ConfigRequest
;
1055 Storage
= (FORMSET_STORAGE
*) Buffer
;
1056 ConfigRequest
= Storage
->ConfigRequest
;
1059 switch (Storage
->Type
) {
1060 case EFI_HII_VARSTORE_BUFFER
:
1061 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1062 Status
= mHiiConfigRouting
->BlockToConfig (
1065 Storage
->EditBuffer
,
1072 case EFI_HII_VARSTORE_NAME_VALUE
:
1074 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1076 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1077 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1078 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1080 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1081 NewStringCat (ConfigResp
, L
"&");
1082 NewStringCat (ConfigResp
, Node
->Name
);
1083 NewStringCat (ConfigResp
, L
"=");
1084 NewStringCat (ConfigResp
, Node
->EditValue
);
1086 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1090 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1092 Status
= EFI_INVALID_PARAMETER
;
1101 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1103 @param Storage The Storage to receive the settings.
1104 @param ConfigResp The <ConfigResp> to be converted.
1106 @retval EFI_SUCCESS Convert success.
1107 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1111 ConfigRespToStorage (
1112 IN FORMSET_STORAGE
*Storage
,
1113 IN CHAR16
*ConfigResp
1117 EFI_STRING Progress
;
1123 Status
= EFI_SUCCESS
;
1125 switch (Storage
->Type
) {
1126 case EFI_HII_VARSTORE_BUFFER
:
1127 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1128 BufferSize
= Storage
->Size
;
1129 Status
= mHiiConfigRouting
->ConfigToBlock (
1132 Storage
->EditBuffer
,
1138 case EFI_HII_VARSTORE_NAME_VALUE
:
1139 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1140 if (StrPtr
== NULL
) {
1143 StrPtr
= StrStr (ConfigResp
, L
"&");
1144 while (StrPtr
!= NULL
) {
1148 StrPtr
= StrPtr
+ 1;
1150 StrPtr
= StrStr (StrPtr
, L
"=");
1151 if (StrPtr
== NULL
) {
1159 StrPtr
= StrPtr
+ 1;
1161 StrPtr
= StrStr (StrPtr
, L
"&");
1162 if (StrPtr
!= NULL
) {
1165 SetValueByName (Storage
, Name
, Value
, TRUE
);
1169 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1171 Status
= EFI_INVALID_PARAMETER
;
1180 Get Question's current Value.
1182 @param FormSet FormSet data structure.
1183 @param Form Form data structure.
1184 @param Question Question to be initialized.
1185 @param Cached TRUE: get from Edit copy FALSE: get from original
1188 @retval EFI_SUCCESS The function completed successfully.
1193 IN FORM_BROWSER_FORMSET
*FormSet
,
1194 IN FORM_BROWSER_FORM
*Form
,
1195 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1205 FORMSET_STORAGE
*Storage
;
1206 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1207 CHAR16
*ConfigRequest
;
1215 BOOLEAN IsBufferStorage
;
1221 Status
= EFI_SUCCESS
;
1226 // Statement don't have storage, skip them
1228 if (Question
->QuestionId
== 0) {
1233 // Question value is provided by an Expression, evaluate it
1235 if (Question
->ValueExpression
!= NULL
) {
1236 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1237 if (!EFI_ERROR (Status
)) {
1238 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1239 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1240 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1241 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1242 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1244 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1245 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1247 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1249 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1250 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1256 // Get question value by read expression.
1258 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1259 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1260 if (!EFI_ERROR (Status
) &&
1261 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1263 // Only update question value to the valid result.
1265 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1266 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1267 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1268 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1269 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1271 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1272 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1274 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1276 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1277 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1283 // Question value is provided by RTC
1285 Storage
= Question
->Storage
;
1286 QuestionValue
= &Question
->HiiValue
.Value
;
1287 if (Storage
== NULL
) {
1289 // It's a Question without storage, or RTC date/time
1291 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1293 // Date and time define the same Flags bit
1295 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1296 case QF_DATE_STORAGE_TIME
:
1297 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1300 case QF_DATE_STORAGE_WAKEUP
:
1301 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1304 case QF_DATE_STORAGE_NORMAL
:
1307 // For date/time without storage
1312 if (EFI_ERROR (Status
)) {
1316 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1317 QuestionValue
->date
.Year
= EfiTime
.Year
;
1318 QuestionValue
->date
.Month
= EfiTime
.Month
;
1319 QuestionValue
->date
.Day
= EfiTime
.Day
;
1321 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1322 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1323 QuestionValue
->time
.Second
= EfiTime
.Second
;
1331 // Question value is provided by EFI variable
1333 StorageWidth
= Question
->StorageWidth
;
1334 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1335 if (Question
->BufferValue
!= NULL
) {
1336 Dst
= Question
->BufferValue
;
1338 Dst
= (UINT8
*) QuestionValue
;
1341 Status
= gRT
->GetVariable (
1342 Question
->VariableName
,
1349 // Always return success, even this EFI variable doesn't exist
1355 // Question Value is provided by Buffer Storage or NameValue Storage
1357 if (Question
->BufferValue
!= NULL
) {
1359 // This Question is password or orderedlist
1361 Dst
= Question
->BufferValue
;
1364 // Other type of Questions
1366 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1369 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1370 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1371 IsBufferStorage
= TRUE
;
1373 IsBufferStorage
= FALSE
;
1375 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1377 if (IsBufferStorage
) {
1379 // Copy from storage Edit buffer
1381 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1384 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
);
1385 if (EFI_ERROR (Status
)) {
1389 ASSERT (Value
!= NULL
);
1390 LengthStr
= StrLen (Value
);
1391 Status
= EFI_SUCCESS
;
1394 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1395 // Add string tail char L'\0' into Length
1397 Length
= StorageWidth
+ sizeof (CHAR16
);
1398 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1399 Status
= EFI_BUFFER_TOO_SMALL
;
1401 StringPtr
= (CHAR16
*) Dst
;
1402 ZeroMem (TemStr
, sizeof (TemStr
));
1403 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1404 StrnCpy (TemStr
, Value
+ Index
, 4);
1405 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1408 // Add tailing L'\0' character
1410 StringPtr
[Index
/4] = L
'\0';
1413 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1414 Status
= EFI_BUFFER_TOO_SMALL
;
1416 ZeroMem (TemStr
, sizeof (TemStr
));
1417 for (Index
= 0; Index
< LengthStr
; Index
++) {
1418 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1419 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1420 if ((Index
& 1) == 0) {
1421 Dst
[Index
/2] = DigitUint8
;
1423 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1432 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1434 // Request current settings from Configuration Driver
1436 if (FormSet
->ConfigAccess
== NULL
) {
1437 return EFI_NOT_FOUND
;
1441 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1442 // <ConfigHdr> + "&" + <VariableName>
1444 if (IsBufferStorage
) {
1445 Length
= StrLen (Storage
->ConfigHdr
);
1446 Length
+= StrLen (Question
->BlockName
);
1448 Length
= StrLen (Storage
->ConfigHdr
);
1449 Length
+= StrLen (Question
->VariableName
) + 1;
1451 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1452 ASSERT (ConfigRequest
!= NULL
);
1454 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1455 if (IsBufferStorage
) {
1456 StrCat (ConfigRequest
, Question
->BlockName
);
1458 StrCat (ConfigRequest
, L
"&");
1459 StrCat (ConfigRequest
, Question
->VariableName
);
1462 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1463 FormSet
->ConfigAccess
,
1468 FreePool (ConfigRequest
);
1469 if (EFI_ERROR (Status
)) {
1474 // Skip <ConfigRequest>
1476 if (IsBufferStorage
) {
1477 Value
= StrStr (Result
, L
"&VALUE");
1478 if (Value
== NULL
) {
1480 return EFI_NOT_FOUND
;
1487 Value
= Result
+ Length
;
1489 if (*Value
!= '=') {
1491 return EFI_NOT_FOUND
;
1494 // Skip '=', point to value
1499 // Suppress <AltResp> if any
1502 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1507 LengthStr
= StrLen (Value
);
1508 Status
= EFI_SUCCESS
;
1509 if (!IsBufferStorage
&& IsString
) {
1511 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1512 // Add string tail char L'\0' into Length
1514 Length
= StorageWidth
+ sizeof (CHAR16
);
1515 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1516 Status
= EFI_BUFFER_TOO_SMALL
;
1518 StringPtr
= (CHAR16
*) Dst
;
1519 ZeroMem (TemStr
, sizeof (TemStr
));
1520 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1521 StrnCpy (TemStr
, Value
+ Index
, 4);
1522 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1525 // Add tailing L'\0' character
1527 StringPtr
[Index
/4] = L
'\0';
1530 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1531 Status
= EFI_BUFFER_TOO_SMALL
;
1533 ZeroMem (TemStr
, sizeof (TemStr
));
1534 for (Index
= 0; Index
< LengthStr
; Index
++) {
1535 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1536 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1537 if ((Index
& 1) == 0) {
1538 Dst
[Index
/2] = DigitUint8
;
1540 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1546 if (EFI_ERROR (Status
)) {
1550 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1552 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1553 if (TemBuffer
== NULL
) {
1554 Status
= EFI_OUT_OF_RESOURCES
;
1557 Length
= Storage
->Size
;
1558 Status
= gRT
->GetVariable (
1565 if (EFI_ERROR (Status
)) {
1566 FreePool (TemBuffer
);
1570 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1572 FreePool (TemBuffer
);
1576 // Synchronize Edit Buffer
1578 if (IsBufferStorage
) {
1579 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1581 SetValueByName (Storage
, Question
->VariableName
, Value
, TRUE
);
1584 if (Result
!= NULL
) {
1594 Save Question Value to edit copy(cached) or Storage(uncached).
1596 @param FormSet FormSet data structure.
1597 @param Form Form data structure.
1598 @param Question Pointer to the Question.
1599 @param Cached TRUE: set to Edit copy FALSE: set to original
1602 @retval EFI_SUCCESS The function completed successfully.
1607 IN FORM_BROWSER_FORMSET
*FormSet
,
1608 IN FORM_BROWSER_FORM
*Form
,
1609 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1620 FORMSET_STORAGE
*Storage
;
1621 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1626 BOOLEAN IsBufferStorage
;
1633 Status
= EFI_SUCCESS
;
1636 // Statement don't have storage, skip them
1638 if (Question
->QuestionId
== 0) {
1643 // If Question value is provided by an Expression, then it is read only
1645 if (Question
->ValueExpression
!= NULL
) {
1650 // Before set question value, evaluate its write expression.
1652 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1653 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1654 if (EFI_ERROR (Status
)) {
1660 // Question value is provided by RTC
1662 Storage
= Question
->Storage
;
1663 QuestionValue
= &Question
->HiiValue
.Value
;
1664 if (Storage
== NULL
) {
1666 // It's a Question without storage, or RTC date/time
1668 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1670 // Date and time define the same Flags bit
1672 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1673 case QF_DATE_STORAGE_TIME
:
1674 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1677 case QF_DATE_STORAGE_WAKEUP
:
1678 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1681 case QF_DATE_STORAGE_NORMAL
:
1684 // For date/time without storage
1689 if (EFI_ERROR (Status
)) {
1693 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1694 EfiTime
.Year
= QuestionValue
->date
.Year
;
1695 EfiTime
.Month
= QuestionValue
->date
.Month
;
1696 EfiTime
.Day
= QuestionValue
->date
.Day
;
1698 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1699 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1700 EfiTime
.Second
= QuestionValue
->time
.Second
;
1703 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1704 Status
= gRT
->SetTime (&EfiTime
);
1706 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1714 // Question value is provided by EFI variable
1716 StorageWidth
= Question
->StorageWidth
;
1717 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1718 if (Question
->BufferValue
!= NULL
) {
1719 Src
= Question
->BufferValue
;
1721 Src
= (UINT8
*) QuestionValue
;
1724 Status
= gRT
->SetVariable (
1725 Question
->VariableName
,
1727 Storage
->Attributes
,
1735 // Question Value is provided by Buffer Storage or NameValue Storage
1737 if (Question
->BufferValue
!= NULL
) {
1738 Src
= Question
->BufferValue
;
1740 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1743 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1744 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1745 IsBufferStorage
= TRUE
;
1747 IsBufferStorage
= FALSE
;
1749 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1750 if (IsBufferStorage
) {
1752 // Copy to storage edit buffer
1754 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1758 // Allocate enough string buffer.
1761 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1762 Value
= AllocateZeroPool (BufferLen
);
1763 ASSERT (Value
!= NULL
);
1765 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1767 TemName
= (CHAR16
*) Src
;
1769 for (; *TemName
!= L
'\0'; TemName
++) {
1770 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1773 BufferLen
= StorageWidth
* 2 + 1;
1774 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1775 ASSERT (Value
!= NULL
);
1777 // Convert Buffer to Hex String
1779 TemBuffer
= Src
+ StorageWidth
- 1;
1781 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1782 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1786 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, TRUE
);
1791 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1793 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1794 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1796 if (IsBufferStorage
) {
1797 Length
= StrLen (Question
->BlockName
) + 7;
1799 Length
= StrLen (Question
->VariableName
) + 2;
1801 if (!IsBufferStorage
&& IsString
) {
1802 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1804 Length
+= (StorageWidth
* 2);
1806 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1807 ASSERT (ConfigResp
!= NULL
);
1809 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1810 if (IsBufferStorage
) {
1811 StrCat (ConfigResp
, Question
->BlockName
);
1812 StrCat (ConfigResp
, L
"&VALUE=");
1814 StrCat (ConfigResp
, L
"&");
1815 StrCat (ConfigResp
, Question
->VariableName
);
1816 StrCat (ConfigResp
, L
"=");
1819 Value
= ConfigResp
+ StrLen (ConfigResp
);
1821 if (!IsBufferStorage
&& IsString
) {
1823 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1825 TemName
= (CHAR16
*) Src
;
1827 for (; *TemName
!= L
'\0'; TemName
++) {
1828 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1832 // Convert Buffer to Hex String
1834 TemBuffer
= Src
+ StorageWidth
- 1;
1836 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1837 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1842 // Convert to lower char.
1844 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1845 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1846 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1851 // Submit Question Value to Configuration Driver
1853 if (FormSet
->ConfigAccess
!= NULL
) {
1854 Status
= FormSet
->ConfigAccess
->RouteConfig (
1855 FormSet
->ConfigAccess
,
1859 if (EFI_ERROR (Status
)) {
1860 FreePool (ConfigResp
);
1864 FreePool (ConfigResp
);
1866 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1868 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1869 if (TemBuffer
== NULL
) {
1870 Status
= EFI_OUT_OF_RESOURCES
;
1873 Length
= Storage
->Size
;
1874 Status
= gRT
->GetVariable (
1882 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1884 Status
= gRT
->SetVariable (
1887 Storage
->Attributes
,
1891 FreePool (TemBuffer
);
1892 if (EFI_ERROR (Status
)){
1897 // Sync storage, from editbuffer to buffer.
1899 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1907 Perform inconsistent check for a Form.
1909 @param FormSet FormSet data structure.
1910 @param Form Form data structure.
1911 @param Question The Question to be validated.
1912 @param Type Validation type: InConsistent or NoSubmit
1914 @retval EFI_SUCCESS Form validation pass.
1915 @retval other Form validation failed.
1920 IN FORM_BROWSER_FORMSET
*FormSet
,
1921 IN FORM_BROWSER_FORM
*Form
,
1922 IN FORM_BROWSER_STATEMENT
*Question
,
1928 LIST_ENTRY
*ListHead
;
1931 FORM_EXPRESSION
*Expression
;
1933 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1934 ListHead
= &Question
->InconsistentListHead
;
1935 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1936 ListHead
= &Question
->NoSubmitListHead
;
1938 return EFI_UNSUPPORTED
;
1941 Link
= GetFirstNode (ListHead
);
1942 while (!IsNull (ListHead
, Link
)) {
1943 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1946 // Evaluate the expression
1948 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1949 if (EFI_ERROR (Status
)) {
1953 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1955 // Condition meet, show up error message
1957 if (Expression
->Error
!= 0) {
1958 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1960 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1961 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1965 return EFI_NOT_READY
;
1968 Link
= GetNextNode (ListHead
, Link
);
1976 Perform NoSubmit check for each Form in FormSet.
1978 @param FormSet FormSet data structure.
1979 @param CurrentForm Current input form data structure.
1981 @retval EFI_SUCCESS Form validation pass.
1982 @retval other Form validation failed.
1987 IN FORM_BROWSER_FORMSET
*FormSet
,
1988 IN FORM_BROWSER_FORM
*CurrentForm
1993 FORM_BROWSER_STATEMENT
*Question
;
1994 FORM_BROWSER_FORM
*Form
;
1995 LIST_ENTRY
*LinkForm
;
1997 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1998 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1999 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2000 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2002 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2006 Link
= GetFirstNode (&Form
->StatementListHead
);
2007 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2008 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2010 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2011 if (EFI_ERROR (Status
)) {
2015 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2023 Fill storage's edit copy with settings requested from Configuration Driver.
2025 @param FormSet FormSet data structure.
2026 @param ConfigInfo The config info related to this form.
2027 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2028 editbuffer to buffer
2029 if TRUE, copy the editbuffer to the buffer.
2030 if FALSE, copy the buffer to the editbuffer.
2032 @retval EFI_SUCCESS The function completed successfully.
2036 SynchronizeStorageForForm (
2037 IN FORM_BROWSER_FORMSET
*FormSet
,
2038 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2039 IN BOOLEAN SyncOrRestore
2043 EFI_STRING Progress
;
2047 NAME_VALUE_NODE
*Node
;
2051 Status
= EFI_SUCCESS
;
2053 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2054 return EFI_NOT_FOUND
;
2057 if (ConfigInfo
->ElementCount
== 0) {
2059 // Skip if there is no RequestElement
2064 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2065 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2066 BufferSize
= ConfigInfo
->Storage
->Size
;
2068 if (SyncOrRestore
) {
2069 Src
= ConfigInfo
->Storage
->EditBuffer
;
2070 Dst
= ConfigInfo
->Storage
->Buffer
;
2072 Src
= ConfigInfo
->Storage
->Buffer
;
2073 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2076 Status
= mHiiConfigRouting
->BlockToConfig(
2078 ConfigInfo
->ConfigRequest
,
2084 if (EFI_ERROR (Status
)) {
2088 Status
= mHiiConfigRouting
->ConfigToBlock (
2095 if (Result
!= NULL
) {
2098 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2099 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2100 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2101 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2103 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2104 if (SyncOrRestore
) {
2105 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2107 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2111 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2120 Discard data based on the input setting scope (Form, FormSet or System).
2122 @param FormSet FormSet data structure.
2123 @param Form Form data structure.
2124 @param SettingScope Setting Scope for Discard action.
2126 @retval EFI_SUCCESS The function completed successfully.
2127 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2132 IN FORM_BROWSER_FORMSET
*FormSet
,
2133 IN FORM_BROWSER_FORM
*Form
,
2134 IN BROWSER_SETTING_SCOPE SettingScope
2138 FORMSET_STORAGE
*Storage
;
2139 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2140 FORM_BROWSER_FORMSET
*LocalFormSet
;
2143 // Check the supported setting level.
2145 if (SettingScope
>= MaxLevel
) {
2146 return EFI_UNSUPPORTED
;
2149 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2151 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2152 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2153 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2154 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2156 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2161 // Skip if there is no RequestElement
2163 if (ConfigInfo
->ElementCount
== 0) {
2168 // Prepare <ConfigResp>
2170 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2173 Form
->NvUpdateRequired
= FALSE
;
2174 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2176 // Discard Buffer storage or Name/Value storage
2178 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2179 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2180 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2181 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2183 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2188 // Skip if there is no RequestElement
2190 if (Storage
->ElementCount
== 0) {
2194 SynchronizeStorage(Storage
, FALSE
);
2197 UpdateNvInfoInForm (FormSet
, FALSE
);
2198 } else if (SettingScope
== SystemLevel
) {
2200 // System Level Discard.
2204 // Discard changed value for each FormSet in the maintain list.
2206 Link
= GetFirstNode (&gBrowserFormSetList
);
2207 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2208 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2209 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2210 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2211 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2213 // Remove maintain backup list after discard except for the current using FormSet.
2215 RemoveEntryList (&LocalFormSet
->Link
);
2216 DestroyFormSet (LocalFormSet
);
2225 Submit data based on the input Setting level (Form, FormSet or System).
2227 @param FormSet FormSet data structure.
2228 @param Form Form data structure.
2229 @param SettingScope Setting Scope for Submit action.
2231 @retval EFI_SUCCESS The function completed successfully.
2232 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2237 IN FORM_BROWSER_FORMSET
*FormSet
,
2238 IN FORM_BROWSER_FORM
*Form
,
2239 IN BROWSER_SETTING_SCOPE SettingScope
2244 EFI_STRING ConfigResp
;
2245 EFI_STRING Progress
;
2246 FORMSET_STORAGE
*Storage
;
2249 FORM_BROWSER_FORMSET
*LocalFormSet
;
2250 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2253 // Check the supported setting level.
2255 if (SettingScope
>= MaxLevel
) {
2256 return EFI_UNSUPPORTED
;
2260 // Validate the Form by NoSubmit check
2262 Status
= EFI_SUCCESS
;
2263 if (SettingScope
== FormLevel
) {
2264 Status
= NoSubmitCheck (FormSet
, Form
);
2265 } else if (SettingScope
== FormSetLevel
) {
2266 Status
= NoSubmitCheck (FormSet
, NULL
);
2268 if (EFI_ERROR (Status
)) {
2272 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2274 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2275 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2276 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2277 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2279 Storage
= ConfigInfo
->Storage
;
2280 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2285 // Skip if there is no RequestElement
2287 if (ConfigInfo
->ElementCount
== 0) {
2292 // 1. Prepare <ConfigResp>
2294 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2295 if (EFI_ERROR (Status
)) {
2300 // 2. Set value to hii driver or efi variable.
2302 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2303 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2305 // Send <ConfigResp> to Configuration Driver
2307 if (FormSet
->ConfigAccess
!= NULL
) {
2308 Status
= FormSet
->ConfigAccess
->RouteConfig (
2309 FormSet
->ConfigAccess
,
2313 if (EFI_ERROR (Status
)) {
2314 FreePool (ConfigResp
);
2318 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2320 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2321 if (TmpBuf
== NULL
) {
2322 Status
= EFI_OUT_OF_RESOURCES
;
2326 BufferSize
= Storage
->Size
;
2327 Status
= gRT
->GetVariable (
2334 if (EFI_ERROR (Status
)) {
2336 FreePool (ConfigResp
);
2339 ASSERT (BufferSize
== Storage
->Size
);
2340 Status
= mHiiConfigRouting
->ConfigToBlock (
2347 if (EFI_ERROR (Status
)) {
2349 FreePool (ConfigResp
);
2353 Status
= gRT
->SetVariable (
2356 Storage
->Attributes
,
2361 if (EFI_ERROR (Status
)) {
2362 FreePool (ConfigResp
);
2366 FreePool (ConfigResp
);
2368 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2370 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2374 // 4. Update the NV flag.
2376 Form
->NvUpdateRequired
= FALSE
;
2377 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2379 // Submit Buffer storage or Name/Value storage
2381 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2382 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2383 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2384 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2386 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2391 // Skip if there is no RequestElement
2393 if (Storage
->ElementCount
== 0) {
2398 // 1. Prepare <ConfigResp>
2400 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2401 if (EFI_ERROR (Status
)) {
2405 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2406 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2409 // 2. Send <ConfigResp> to Configuration Driver
2411 if (FormSet
->ConfigAccess
!= NULL
) {
2412 Status
= FormSet
->ConfigAccess
->RouteConfig (
2413 FormSet
->ConfigAccess
,
2417 if (EFI_ERROR (Status
)) {
2418 FreePool (ConfigResp
);
2422 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2424 // 1&2. Set the edit data to the variable.
2427 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2428 if (TmpBuf
== NULL
) {
2429 Status
= EFI_OUT_OF_RESOURCES
;
2432 BufferSize
= Storage
->Size
;
2433 Status
= gRT
->GetVariable (
2440 ASSERT (BufferSize
== Storage
->Size
);
2441 Status
= mHiiConfigRouting
->ConfigToBlock (
2448 if (EFI_ERROR (Status
)) {
2450 FreePool (ConfigResp
);
2454 Status
= gRT
->SetVariable (
2457 Storage
->Attributes
,
2461 if (EFI_ERROR (Status
)) {
2463 FreePool (ConfigResp
);
2468 FreePool (ConfigResp
);
2470 // 3. Config success, update storage shadow Buffer
2472 SynchronizeStorage (Storage
, TRUE
);
2476 // 4. Update the NV flag.
2478 UpdateNvInfoInForm (FormSet
, FALSE
);
2479 } else if (SettingScope
== SystemLevel
) {
2481 // System Level Save.
2485 // Save changed value for each FormSet in the maintain list.
2487 Link
= GetFirstNode (&gBrowserFormSetList
);
2488 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2489 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2490 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2491 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2492 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2494 // Remove maintain backup list after save except for the current using FormSet.
2496 RemoveEntryList (&LocalFormSet
->Link
);
2497 DestroyFormSet (LocalFormSet
);
2506 Get Question default value from AltCfg string.
2508 @param FormSet The form set.
2509 @param Question The question.
2510 @param DefaultId The default Id.
2512 @retval EFI_SUCCESS Question is reset to default value.
2516 GetDefaultValueFromAltCfg (
2517 IN FORM_BROWSER_FORMSET
*FormSet
,
2518 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2522 BOOLEAN IsBufferStorage
;
2525 FORMSET_STORAGE
*Storage
;
2526 CHAR16
*ConfigRequest
;
2539 Status
= EFI_NOT_FOUND
;
2542 ConfigRequest
= NULL
;
2546 Storage
= Question
->Storage
;
2548 if ((Storage
== NULL
) ||
2549 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2550 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2555 // Question Value is provided by Buffer Storage or NameValue Storage
2557 if (Question
->BufferValue
!= NULL
) {
2559 // This Question is password or orderedlist
2561 Dst
= Question
->BufferValue
;
2564 // Other type of Questions
2566 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2569 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2570 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2573 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2574 // <ConfigHdr> + "&" + <VariableName>
2576 if (IsBufferStorage
) {
2577 Length
= StrLen (Storage
->ConfigHdr
);
2578 Length
+= StrLen (Question
->BlockName
);
2580 Length
= StrLen (Storage
->ConfigHdr
);
2581 Length
+= StrLen (Question
->VariableName
) + 1;
2583 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2584 ASSERT (ConfigRequest
!= NULL
);
2586 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2587 if (IsBufferStorage
) {
2588 StrCat (ConfigRequest
, Question
->BlockName
);
2590 StrCat (ConfigRequest
, L
"&");
2591 StrCat (ConfigRequest
, Question
->VariableName
);
2594 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2595 FormSet
->ConfigAccess
,
2600 if (EFI_ERROR (Status
)) {
2605 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2606 // Get the default configuration string according to the default ID.
2608 Status
= mHiiConfigRouting
->GetAltConfig (
2614 &DefaultId
, // it can be NULL to get the current setting.
2619 // The required setting can't be found. So, it is not required to be validated and set.
2621 if (EFI_ERROR (Status
)) {
2626 // Skip <ConfigRequest>
2628 if (IsBufferStorage
) {
2629 Value
= StrStr (ConfigResp
, L
"&VALUE");
2630 ASSERT (Value
!= NULL
);
2636 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2637 ASSERT (Value
!= NULL
);
2639 Value
= Value
+ StrLen (Question
->VariableName
);
2641 if (*Value
!= '=') {
2642 Status
= EFI_NOT_FOUND
;
2646 // Skip '=', point to value
2651 // Suppress <AltResp> if any
2654 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2659 LengthStr
= StrLen (Value
);
2660 if (!IsBufferStorage
&& IsString
) {
2661 StringPtr
= (CHAR16
*) Dst
;
2662 ZeroMem (TemStr
, sizeof (TemStr
));
2663 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2664 StrnCpy (TemStr
, Value
+ Index
, 4);
2665 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2668 // Add tailing L'\0' character
2670 StringPtr
[Index
/4] = L
'\0';
2672 ZeroMem (TemStr
, sizeof (TemStr
));
2673 for (Index
= 0; Index
< LengthStr
; Index
++) {
2674 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2675 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2676 if ((Index
& 1) == 0) {
2677 Dst
[Index
/2] = DigitUint8
;
2679 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2685 if (ConfigRequest
!= NULL
){
2686 FreePool (ConfigRequest
);
2689 if (ConfigResp
!= NULL
) {
2690 FreePool (ConfigResp
);
2693 if (Result
!= NULL
) {
2701 Get default Id value used for browser.
2703 @param DefaultId The default id value used by hii.
2705 @retval Browser used default value.
2709 GetDefaultIdForCallBack (
2713 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2714 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2715 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2716 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2717 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2718 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2719 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2720 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2721 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2722 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2723 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2724 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2731 Reset Question to its default value.
2733 @param FormSet The form set.
2734 @param Form The form.
2735 @param Question The question.
2736 @param DefaultId The Class of the default.
2738 @retval EFI_SUCCESS Question is reset to default value.
2742 GetQuestionDefault (
2743 IN FORM_BROWSER_FORMSET
*FormSet
,
2744 IN FORM_BROWSER_FORM
*Form
,
2745 IN FORM_BROWSER_STATEMENT
*Question
,
2751 QUESTION_DEFAULT
*Default
;
2752 QUESTION_OPTION
*Option
;
2753 EFI_HII_VALUE
*HiiValue
;
2755 EFI_STRING StrValue
;
2756 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2757 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2760 Status
= EFI_NOT_FOUND
;
2764 // Statement don't have storage, skip them
2766 if (Question
->QuestionId
== 0) {
2771 // There are Five ways to specify default value for a Question:
2772 // 1, use call back function (highest priority)
2773 // 2, use ExtractConfig function
2774 // 3, use nested EFI_IFR_DEFAULT
2775 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2776 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2778 HiiValue
= &Question
->HiiValue
;
2781 // Get Question defaut value from call back function.
2783 ConfigAccess
= FormSet
->ConfigAccess
;
2784 Action
= GetDefaultIdForCallBack (DefaultId
);
2785 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2786 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2787 Status
= ConfigAccess
->Callback (
2790 Question
->QuestionId
,
2795 if (!EFI_ERROR (Status
)) {
2801 // Get default value from altcfg string.
2803 if (ConfigAccess
!= NULL
) {
2804 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2805 if (!EFI_ERROR (Status
)) {
2811 // EFI_IFR_DEFAULT has highest priority
2813 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2814 Link
= GetFirstNode (&Question
->DefaultListHead
);
2815 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2816 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2818 if (Default
->DefaultId
== DefaultId
) {
2819 if (Default
->ValueExpression
!= NULL
) {
2821 // Default is provided by an Expression, evaluate it
2823 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2824 if (EFI_ERROR (Status
)) {
2828 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
2829 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
2830 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
2831 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
2832 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
2834 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
2835 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
2837 FreePool (Default
->ValueExpression
->Result
.Buffer
);
2839 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
2840 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2843 // Default value is embedded in EFI_IFR_DEFAULT
2845 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2848 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2849 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
2850 if (StrValue
== NULL
) {
2851 return EFI_NOT_FOUND
;
2853 if (Question
->StorageWidth
> StrSize (StrValue
)) {
2854 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
2856 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
2863 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
2868 // EFI_ONE_OF_OPTION
2870 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
2871 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2873 // OneOfOption could only provide Standard and Manufacturing default
2875 Link
= GetFirstNode (&Question
->OptionListHead
);
2876 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2877 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2879 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
2880 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
2882 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
2887 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2893 // EFI_IFR_CHECKBOX - lowest priority
2895 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
2896 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2898 // Checkbox could only provide Standard and Manufacturing default
2900 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
2901 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
2903 HiiValue
->Value
.b
= TRUE
;
2905 HiiValue
->Value
.b
= FALSE
;
2913 // For Questions without default
2915 Status
= EFI_NOT_FOUND
;
2916 switch (Question
->Operand
) {
2917 case EFI_IFR_NUMERIC_OP
:
2919 // Take minimum value as numeric default value
2921 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
2922 HiiValue
->Value
.u64
= Question
->Minimum
;
2923 Status
= EFI_SUCCESS
;
2927 case EFI_IFR_ONE_OF_OP
:
2929 // Take first oneof option as oneof's default value
2931 if (ValueToOption (Question
, HiiValue
) == NULL
) {
2932 Link
= GetFirstNode (&Question
->OptionListHead
);
2933 if (!IsNull (&Question
->OptionListHead
, Link
)) {
2934 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2935 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
2936 Status
= EFI_SUCCESS
;
2941 case EFI_IFR_ORDERED_LIST_OP
:
2943 // Take option sequence in IFR as ordered list's default value
2946 Link
= GetFirstNode (&Question
->OptionListHead
);
2947 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2948 Status
= EFI_SUCCESS
;
2949 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2951 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
2954 if (Index
>= Question
->MaxContainers
) {
2958 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2971 Reset Questions to their default value in a Form, Formset or System.
2973 GetDefaultValueScope parameter decides which questions will reset
2974 to its default value.
2976 @param FormSet FormSet data structure.
2977 @param Form Form data structure.
2978 @param DefaultId The Class of the default.
2979 @param SettingScope Setting Scope for Default action.
2980 @param GetDefaultValueScope Get default value scope.
2981 @param Storage Get default value only for this storage.
2983 @retval EFI_SUCCESS The function completed successfully.
2984 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2989 IN FORM_BROWSER_FORMSET
*FormSet
,
2990 IN FORM_BROWSER_FORM
*Form
,
2991 IN UINT16 DefaultId
,
2992 IN BROWSER_SETTING_SCOPE SettingScope
,
2993 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
2994 IN FORMSET_STORAGE
*Storage OPTIONAL
2998 LIST_ENTRY
*FormLink
;
3000 FORM_BROWSER_STATEMENT
*Question
;
3001 FORM_BROWSER_FORMSET
*BackUpFormSet
;
3002 FORM_BROWSER_FORMSET
*LocalFormSet
;
3003 EFI_HII_HANDLE
*HiiHandles
;
3008 // Check the supported setting level.
3010 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3011 return EFI_UNSUPPORTED
;
3014 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3015 return EFI_UNSUPPORTED
;
3018 if (SettingScope
== FormLevel
) {
3020 // Extract Form default
3022 Link
= GetFirstNode (&Form
->StatementListHead
);
3023 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3024 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3025 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3028 // If get default value only for this storage, check the storage first.
3030 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3035 // If get default value only for no storage question, just skip the question which has storage.
3037 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3042 // If Question is disabled, don't reset it to default
3044 if (Question
->Expression
!= NULL
) {
3045 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3051 // Reset Question to its default value
3053 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3054 if (EFI_ERROR (Status
)) {
3059 // Synchronize Buffer storage's Edit buffer
3061 if ((Question
->Storage
!= NULL
) &&
3062 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3063 SetQuestionValue (FormSet
, Form
, Question
, TRUE
);
3065 // Update Form NV flag.
3067 Form
->NvUpdateRequired
= TRUE
;
3070 } else if (SettingScope
== FormSetLevel
) {
3071 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3072 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3073 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3074 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
);
3075 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3077 } else if (SettingScope
== SystemLevel
) {
3079 // Open all FormSet by locate HII packages.
3080 // Initiliaze the maintain FormSet to store default data as back up data.
3082 BackUpFormSet
= gOldFormSet
;
3086 // Get all the Hii handles
3088 HiiHandles
= HiiGetHiiHandles (NULL
);
3089 ASSERT (HiiHandles
!= NULL
);
3092 // Search for formset of each class type
3094 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3096 // Check HiiHandles[Index] does exist in global maintain list.
3098 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3103 // Initilize FormSet Setting
3105 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3106 ASSERT (LocalFormSet
!= NULL
);
3107 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3108 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
, FALSE
);
3109 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3110 DestroyFormSet (LocalFormSet
);
3113 Status
= InitializeCurrentSetting (LocalFormSet
);
3114 if (EFI_ERROR (Status
)) {
3115 DestroyFormSet (LocalFormSet
);
3119 // Initilize Questions' Value
3121 LoadFormSetConfig (NULL
, LocalFormSet
);
3122 if (EFI_ERROR (Status
)) {
3123 DestroyFormSet (LocalFormSet
);
3128 // Add FormSet into the maintain list.
3130 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3134 // Free resources, and restore gOldFormSet and gClassOfVfr
3136 FreePool (HiiHandles
);
3137 gOldFormSet
= BackUpFormSet
;
3140 // Set Default Value for each FormSet in the maintain list.
3142 Link
= GetFirstNode (&gBrowserFormSetList
);
3143 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3144 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3145 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
);
3146 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3154 Initialize Question's Edit copy from Storage.
3156 @param Selection Selection contains the information about
3157 the Selection, form and formset to be displayed.
3158 Selection action may be updated in retrieve callback.
3159 If Selection is NULL, only initialize Question value.
3160 @param FormSet FormSet data structure.
3161 @param Form Form data structure.
3163 @retval EFI_SUCCESS The function completed successfully.
3168 IN OUT UI_MENU_SELECTION
*Selection
,
3169 IN FORM_BROWSER_FORMSET
*FormSet
,
3170 IN FORM_BROWSER_FORM
*Form
3175 FORM_BROWSER_STATEMENT
*Question
;
3179 Link
= GetFirstNode (&Form
->StatementListHead
);
3180 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3181 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3184 // Initialize local copy of Value for each Question
3186 Status
= GetQuestionValue (FormSet
, Form
, Question
, TRUE
);
3187 if (EFI_ERROR (Status
)) {
3191 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3192 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3196 // According the spec, ref opcode try to get value from call back with "retrieve" type.
3198 if ((Question
->Operand
== EFI_IFR_REF_OP
) && (FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
)) {
3199 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3200 if (EFI_ERROR (Status
)) {
3206 // Check whether EfiVarstore with CallBack can be got.
3208 if ((FormSet
->ConfigAccess
!= NULL
) &&
3209 (Selection
!= NULL
) &&
3210 (Selection
->Action
!= UI_ACTION_REFRESH_FORMSET
) &&
3211 (Question
->QuestionId
!= 0) &&
3212 (Question
->Storage
!= NULL
) &&
3213 (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) &&
3214 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3217 // Check QuestionValue does exist.
3219 StorageWidth
= Question
->StorageWidth
;
3220 if (Question
->BufferValue
!= NULL
) {
3221 BufferValue
= Question
->BufferValue
;
3223 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3225 Status
= gRT
->GetVariable (
3226 Question
->VariableName
,
3227 &Question
->Storage
->Guid
,
3233 if (!EFI_ERROR (Status
)) {
3234 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3238 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3245 Initialize Question's Edit copy from Storage for the whole Formset.
3247 @param Selection Selection contains the information about
3248 the Selection, form and formset to be displayed.
3249 Selection action may be updated in retrieve callback.
3250 If Selection is NULL, only initialize Question value.
3251 @param FormSet FormSet data structure.
3253 @retval EFI_SUCCESS The function completed successfully.
3258 IN OUT UI_MENU_SELECTION
*Selection
,
3259 IN FORM_BROWSER_FORMSET
*FormSet
3264 FORM_BROWSER_FORM
*Form
;
3266 Link
= GetFirstNode (&FormSet
->FormListHead
);
3267 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3268 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3271 // Initialize local copy of Value for each Form
3273 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3274 if (EFI_ERROR (Status
)) {
3278 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3285 Fill storage's edit copy with settings requested from Configuration Driver.
3287 @param FormSet FormSet data structure.
3288 @param Storage Buffer Storage.
3290 @retval EFI_SUCCESS The function completed successfully.
3295 IN FORM_BROWSER_FORMSET
*FormSet
,
3296 IN FORMSET_STORAGE
*Storage
3300 EFI_STRING Progress
;
3304 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3308 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3309 Status
= gRT
->GetVariable (
3313 (UINTN
*)&Storage
->Size
,
3319 if (FormSet
->ConfigAccess
== NULL
) {
3320 return EFI_NOT_FOUND
;
3323 if (Storage
->ElementCount
== 0) {
3325 // Skip if there is no RequestElement
3331 // Request current settings from Configuration Driver
3333 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3334 FormSet
->ConfigAccess
,
3335 Storage
->ConfigRequest
,
3339 if (EFI_ERROR (Status
)) {
3344 // Convert Result from <ConfigAltResp> to <ConfigResp>
3346 StrPtr
= StrStr (Result
, L
"ALTCFG");
3347 if (StrPtr
!= NULL
) {
3351 Status
= ConfigRespToStorage (Storage
, Result
);
3358 Copy uncommitted data from source Storage to destination Storage.
3360 @param Dst Target Storage for uncommitted data.
3361 @param Src Source Storage for uncommitted data.
3363 @retval EFI_SUCCESS The function completed successfully.
3364 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
3369 IN OUT FORMSET_STORAGE
*Dst
,
3370 IN FORMSET_STORAGE
*Src
3374 NAME_VALUE_NODE
*Node
;
3376 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
3377 return EFI_INVALID_PARAMETER
;
3380 switch (Src
->Type
) {
3381 case EFI_HII_VARSTORE_BUFFER
:
3382 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3383 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
3384 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
3387 case EFI_HII_VARSTORE_NAME_VALUE
:
3388 Link
= GetFirstNode (&Src
->NameValueListHead
);
3389 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
3390 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3392 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, TRUE
);
3393 SetValueByName (Dst
, Node
->Name
, Node
->Value
, FALSE
);
3395 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
3399 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3409 Get current setting of Questions.
3411 @param FormSet FormSet data structure.
3413 @retval EFI_SUCCESS The function completed successfully.
3417 InitializeCurrentSetting (
3418 IN OUT FORM_BROWSER_FORMSET
*FormSet
3423 FORMSET_STORAGE
*Storage
;
3424 FORMSET_STORAGE
*StorageSrc
;
3425 FORMSET_STORAGE
*OldStorage
;
3426 FORM_BROWSER_FORM
*Form
;
3427 FORM_BROWSER_FORM
*Form2
;
3431 // Extract default from IFR binary for no storage questions.
3433 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
);
3436 // Request current settings from Configuration Driver
3438 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3439 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3440 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3443 if (gOldFormSet
!= NULL
) {
3445 // Try to find the Storage in backup formset gOldFormSet
3447 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3448 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3449 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3451 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3452 OldStorage
= StorageSrc
;
3456 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3460 if (OldStorage
== NULL
) {
3462 // Storage is not found in backup formset, request it from ConfigDriver
3464 Status
= LoadStorage (FormSet
, Storage
);
3466 if (EFI_ERROR (Status
)) {
3468 // If get last time changed value failed, extract default from IFR binary
3470 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
);
3472 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3473 // in current situation.
3475 UpdateNvInfoInForm (FormSet
, FALSE
);
3479 // Now Edit Buffer is filled with default values(lower priority) or current
3480 // settings(higher priority), sychronize it to shadow Buffer
3482 SynchronizeStorage (Storage
, TRUE
);
3485 // Storage found in backup formset, use it
3487 Status
= CopyStorage (Storage
, OldStorage
);
3490 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3494 // If has old formset, get the old nv update status.
3496 if (gOldFormSet
!= NULL
) {
3497 Link
= GetFirstNode (&FormSet
->FormListHead
);
3498 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3499 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3501 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3502 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3503 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3505 if (Form
->FormId
== Form2
->FormId
) {
3506 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3510 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3512 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3521 Fetch the Ifr binary data of a FormSet.
3523 @param Handle PackageList Handle
3524 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3525 specified (NULL or zero GUID), take the first
3526 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3527 found in package list.
3528 On output, GUID of the formset found(if not NULL).
3529 @param BinaryLength The length of the FormSet IFR binary.
3530 @param BinaryData The buffer designed to receive the FormSet.
3532 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3533 BufferLength was updated.
3534 @retval EFI_INVALID_PARAMETER The handle is unknown.
3535 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3536 be found with the requested FormId.
3541 IN EFI_HII_HANDLE Handle
,
3542 IN OUT EFI_GUID
*FormSetGuid
,
3543 OUT UINTN
*BinaryLength
,
3544 OUT UINT8
**BinaryData
3548 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3554 UINT32 PackageListLength
;
3555 EFI_HII_PACKAGE_HEADER PackageHeader
;
3557 UINT8 NumberOfClassGuid
;
3558 BOOLEAN ClassGuidMatch
;
3559 EFI_GUID
*ClassGuid
;
3560 EFI_GUID
*ComparingGuid
;
3564 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3567 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3569 if (FormSetGuid
== NULL
) {
3570 ComparingGuid
= &gZeroGuid
;
3572 ComparingGuid
= FormSetGuid
;
3576 // Get HII PackageList
3579 HiiPackageList
= NULL
;
3580 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3581 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3582 HiiPackageList
= AllocatePool (BufferSize
);
3583 ASSERT (HiiPackageList
!= NULL
);
3585 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3587 if (EFI_ERROR (Status
)) {
3590 ASSERT (HiiPackageList
!= NULL
);
3593 // Get Form package from this HII package List
3595 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3597 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3599 ClassGuidMatch
= FALSE
;
3600 while (Offset
< PackageListLength
) {
3601 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3602 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3604 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3606 // Search FormSet in this Form Package
3608 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3609 while (Offset2
< PackageHeader
.Length
) {
3610 OpCodeData
= Package
+ Offset2
;
3612 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3614 // Try to compare against formset GUID
3616 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3617 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3621 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3623 // Try to compare against formset class GUID
3625 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3626 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3627 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3628 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3629 ClassGuidMatch
= TRUE
;
3633 if (ClassGuidMatch
) {
3636 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3637 ClassGuidMatch
= TRUE
;
3642 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3645 if (Offset2
< PackageHeader
.Length
) {
3647 // Target formset found
3653 Offset
+= PackageHeader
.Length
;
3656 if (Offset
>= PackageListLength
) {
3658 // Form package not found in this Package List
3660 FreePool (HiiPackageList
);
3661 return EFI_NOT_FOUND
;
3664 if (FormSetGuid
!= NULL
) {
3666 // Return the FormSet GUID
3668 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3672 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3673 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3674 // of the Form Package.
3676 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3677 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3679 FreePool (HiiPackageList
);
3681 if (*BinaryData
== NULL
) {
3682 return EFI_OUT_OF_RESOURCES
;
3690 Initialize the internal data structure of a FormSet.
3692 @param Handle PackageList Handle
3693 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3694 specified (NULL or zero GUID), take the first
3695 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3696 found in package list.
3697 On output, GUID of the formset found(if not NULL).
3698 @param FormSet FormSet data structure.
3699 @param UpdateGlobalVar Whether need to update the global variable.
3701 @retval EFI_SUCCESS The function completed successfully.
3702 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3707 IN EFI_HII_HANDLE Handle
,
3708 IN OUT EFI_GUID
*FormSetGuid
,
3709 OUT FORM_BROWSER_FORMSET
*FormSet
,
3710 IN BOOLEAN UpdateGlobalVar
3714 EFI_HANDLE DriverHandle
;
3717 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3718 if (EFI_ERROR (Status
)) {
3722 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3723 FormSet
->HiiHandle
= Handle
;
3724 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3727 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3729 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3730 if (EFI_ERROR (Status
)) {
3733 FormSet
->DriverHandle
= DriverHandle
;
3734 Status
= gBS
->HandleProtocol (
3736 &gEfiHiiConfigAccessProtocolGuid
,
3737 (VOID
**) &FormSet
->ConfigAccess
3739 if (EFI_ERROR (Status
)) {
3741 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3742 // list, then there will be no configuration action required
3744 FormSet
->ConfigAccess
= NULL
;
3748 // Parse the IFR binary OpCodes
3750 Status
= ParseOpCodes (FormSet
);
3751 if (EFI_ERROR (Status
)) {
3756 // If not need to update the global variable, just return.
3758 if (!UpdateGlobalVar
) {
3763 // Set VFR type by FormSet SubClass field
3765 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
3766 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
3767 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
3771 // Set VFR type by FormSet class guid
3773 for (Index
= 0; Index
< 3; Index
++) {
3774 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
3775 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
3780 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
3781 gFrontPageHandle
= FormSet
->HiiHandle
;
3782 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
3786 // Match GUID to find out the function key setting. If match fail, use the default setting.
3788 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
3789 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
3791 // Update the function key setting.
3793 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
3802 Save globals used by previous call to SendForm(). SendForm() may be called from
3803 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
3804 So, save globals of previous call to SendForm() and restore them upon exit.
3808 SaveBrowserContext (
3812 BROWSER_CONTEXT
*Context
;
3814 gBrowserContextCount
++;
3815 if (gBrowserContextCount
== 1) {
3817 // This is not reentry of SendForm(), no context to save
3822 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
3823 ASSERT (Context
!= NULL
);
3825 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
3828 // Save FormBrowser context
3830 Context
->BannerData
= gBannerData
;
3831 Context
->ClassOfVfr
= gClassOfVfr
;
3832 Context
->FunctionKeySetting
= gFunctionKeySetting
;
3833 Context
->ResetRequired
= gResetRequired
;
3834 Context
->Direction
= gDirection
;
3835 Context
->EnterString
= gEnterString
;
3836 Context
->EnterCommitString
= gEnterCommitString
;
3837 Context
->EnterEscapeString
= gEnterEscapeString
;
3838 Context
->EscapeString
= gEscapeString
;
3839 Context
->MoveHighlight
= gMoveHighlight
;
3840 Context
->MakeSelection
= gMakeSelection
;
3841 Context
->DecNumericInput
= gDecNumericInput
;
3842 Context
->HexNumericInput
= gHexNumericInput
;
3843 Context
->ToggleCheckBox
= gToggleCheckBox
;
3844 Context
->PromptForData
= gPromptForData
;
3845 Context
->PromptForPassword
= gPromptForPassword
;
3846 Context
->PromptForNewPassword
= gPromptForNewPassword
;
3847 Context
->ConfirmPassword
= gConfirmPassword
;
3848 Context
->ConfirmError
= gConfirmError
;
3849 Context
->PassowordInvalid
= gPassowordInvalid
;
3850 Context
->PressEnter
= gPressEnter
;
3851 Context
->EmptyString
= gEmptyString
;
3852 Context
->AreYouSure
= gAreYouSure
;
3853 Context
->YesResponse
= gYesResponse
;
3854 Context
->NoResponse
= gNoResponse
;
3855 Context
->MiniString
= gMiniString
;
3856 Context
->PlusString
= gPlusString
;
3857 Context
->MinusString
= gMinusString
;
3858 Context
->AdjustNumber
= gAdjustNumber
;
3859 Context
->SaveChanges
= gSaveChanges
;
3860 Context
->OptionMismatch
= gOptionMismatch
;
3861 Context
->FormSuppress
= gFormSuppress
;
3862 Context
->PromptBlockWidth
= gPromptBlockWidth
;
3863 Context
->OptionBlockWidth
= gOptionBlockWidth
;
3864 Context
->HelpBlockWidth
= gHelpBlockWidth
;
3865 Context
->OldFormSet
= gOldFormSet
;
3866 Context
->MenuRefreshHead
= gMenuRefreshHead
;
3868 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
3869 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
3872 // Insert to FormBrowser context list
3874 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
3879 Restore globals used by previous call to SendForm().
3883 RestoreBrowserContext (
3888 BROWSER_CONTEXT
*Context
;
3890 ASSERT (gBrowserContextCount
!= 0);
3891 gBrowserContextCount
--;
3892 if (gBrowserContextCount
== 0) {
3894 // This is not reentry of SendForm(), no context to restore
3899 ASSERT (!IsListEmpty (&gBrowserContextList
));
3901 Link
= GetFirstNode (&gBrowserContextList
);
3902 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
3905 // Restore FormBrowser context
3907 gBannerData
= Context
->BannerData
;
3908 gClassOfVfr
= Context
->ClassOfVfr
;
3909 gFunctionKeySetting
= Context
->FunctionKeySetting
;
3910 gResetRequired
= Context
->ResetRequired
;
3911 gDirection
= Context
->Direction
;
3912 gEnterString
= Context
->EnterString
;
3913 gEnterCommitString
= Context
->EnterCommitString
;
3914 gEnterEscapeString
= Context
->EnterEscapeString
;
3915 gEscapeString
= Context
->EscapeString
;
3916 gMoveHighlight
= Context
->MoveHighlight
;
3917 gMakeSelection
= Context
->MakeSelection
;
3918 gDecNumericInput
= Context
->DecNumericInput
;
3919 gHexNumericInput
= Context
->HexNumericInput
;
3920 gToggleCheckBox
= Context
->ToggleCheckBox
;
3921 gPromptForData
= Context
->PromptForData
;
3922 gPromptForPassword
= Context
->PromptForPassword
;
3923 gPromptForNewPassword
= Context
->PromptForNewPassword
;
3924 gConfirmPassword
= Context
->ConfirmPassword
;
3925 gConfirmError
= Context
->ConfirmError
;
3926 gPassowordInvalid
= Context
->PassowordInvalid
;
3927 gPressEnter
= Context
->PressEnter
;
3928 gEmptyString
= Context
->EmptyString
;
3929 gAreYouSure
= Context
->AreYouSure
;
3930 gYesResponse
= Context
->YesResponse
;
3931 gNoResponse
= Context
->NoResponse
;
3932 gMiniString
= Context
->MiniString
;
3933 gPlusString
= Context
->PlusString
;
3934 gMinusString
= Context
->MinusString
;
3935 gAdjustNumber
= Context
->AdjustNumber
;
3936 gSaveChanges
= Context
->SaveChanges
;
3937 gOptionMismatch
= Context
->OptionMismatch
;
3938 gFormSuppress
= Context
->FormSuppress
;
3939 gPromptBlockWidth
= Context
->PromptBlockWidth
;
3940 gOptionBlockWidth
= Context
->OptionBlockWidth
;
3941 gHelpBlockWidth
= Context
->HelpBlockWidth
;
3942 gOldFormSet
= Context
->OldFormSet
;
3943 gMenuRefreshHead
= Context
->MenuRefreshHead
;
3945 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
3946 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
3949 // Remove from FormBrowser context list
3951 RemoveEntryList (&Context
->Link
);
3952 gBS
->FreePool (Context
);
3956 Find the matched FormSet context in the backup maintain list based on HiiHandle.
3958 @param Handle The Hii Handle.
3960 @return the found FormSet context. If no found, NULL will return.
3963 FORM_BROWSER_FORMSET
*
3964 GetFormSetFromHiiHandle (
3965 EFI_HII_HANDLE Handle
3969 FORM_BROWSER_FORMSET
*FormSet
;
3971 Link
= GetFirstNode (&gBrowserFormSetList
);
3972 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3973 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3974 if (FormSet
->HiiHandle
== Handle
) {
3977 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3984 Check whether the input HII handle is the FormSet that is being used.
3986 @param Handle The Hii Handle.
3988 @retval TRUE HII handle is being used.
3989 @retval FALSE HII handle is not being used.
3993 IsHiiHandleInBrowserContext (
3994 EFI_HII_HANDLE Handle
3998 BROWSER_CONTEXT
*Context
;
4001 // HiiHandle is Current FormSet.
4003 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
4008 // Check whether HiiHandle is in BrowserContext.
4010 Link
= GetFirstNode (&gBrowserContextList
);
4011 while (!IsNull (&gBrowserContextList
, Link
)) {
4012 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4013 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
4015 // HiiHandle is in BrowserContext
4019 Link
= GetNextNode (&gBrowserContextList
, Link
);
4026 Find the registered HotKey based on KeyData.
4028 @param[in] KeyData A pointer to a buffer that describes the keystroke
4029 information for the hot key.
4031 @return The registered HotKey context. If no found, NULL will return.
4034 GetHotKeyFromRegisterList (
4035 IN EFI_INPUT_KEY
*KeyData
4039 BROWSER_HOT_KEY
*HotKey
;
4041 Link
= GetFirstNode (&gBrowserHotKeyList
);
4042 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4043 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4044 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4047 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4054 Configure what scope the hot key will impact.
4055 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4056 If no scope is set, the default scope will be FormSet level.
4057 After all registered hot keys are removed, previous Scope can reset to another level.
4059 @param[in] Scope Scope level to be set.
4061 @retval EFI_SUCCESS Scope is set correctly.
4062 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4063 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4069 IN BROWSER_SETTING_SCOPE Scope
4072 if (Scope
>= MaxLevel
) {
4073 return EFI_INVALID_PARAMETER
;
4077 // When no hot key registered in system or on the first setting,
4078 // Scope can be set.
4080 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4081 gBrowserSettingScope
= Scope
;
4082 mBrowserScopeFirstSet
= FALSE
;
4083 } else if (Scope
!= gBrowserSettingScope
) {
4084 return EFI_UNSUPPORTED
;
4091 Register the hot key with its browser action, or unregistered the hot key.
4092 Only support hot key that is not printable character (control key, function key, etc.).
4093 If the action value is zero, the hot key will be unregistered if it has been registered.
4094 If the same hot key has been registered, the new action and help string will override the previous ones.
4096 @param[in] KeyData A pointer to a buffer that describes the keystroke
4097 information for the hot key. Its type is EFI_INPUT_KEY to
4098 be supported by all ConsoleIn devices.
4099 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4100 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4101 @param[in] HelpString Help string that describes the hot key information.
4102 Its value may be NULL for the unregistered hot key.
4104 @retval EFI_SUCCESS Hot key is registered or unregistered.
4105 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4106 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4107 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4112 IN EFI_INPUT_KEY
*KeyData
,
4114 IN UINT16 DefaultId
,
4115 IN EFI_STRING HelpString OPTIONAL
4118 BROWSER_HOT_KEY
*HotKey
;
4121 // Check input parameters.
4123 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4124 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4125 return EFI_INVALID_PARAMETER
;
4129 // Check whether the input KeyData is in BrowserHotKeyList.
4131 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4134 // Unregister HotKey
4136 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4137 if (HotKey
!= NULL
) {
4139 // The registered HotKey is found.
4140 // Remove it from List, and free its resource.
4142 RemoveEntryList (&HotKey
->Link
);
4143 FreePool (HotKey
->KeyData
);
4144 FreePool (HotKey
->HelpString
);
4148 // The registered HotKey is not found.
4150 return EFI_NOT_FOUND
;
4155 // Register HotKey into List.
4157 if (HotKey
== NULL
) {
4159 // Create new Key, and add it into List.
4161 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4162 ASSERT (HotKey
!= NULL
);
4163 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4164 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4165 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4169 // Fill HotKey information.
4171 HotKey
->Action
= Action
;
4172 HotKey
->DefaultId
= DefaultId
;
4173 if (HotKey
->HelpString
!= NULL
) {
4174 FreePool (HotKey
->HelpString
);
4176 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4182 Register Exit handler function.
4183 When more than one handler function is registered, the latter one will override the previous one.
4184 When NULL handler is specified, the previous Exit handler will be unregistered.
4186 @param[in] Handler Pointer to handler function.
4191 RegiserExitHandler (
4192 IN EXIT_HANDLER Handler
4195 ExitHandlerFunction
= Handler
;
4200 Create reminder to let user to choose save or discard the changed browser data.
4201 Caller can use it to actively check the changed browser data.
4203 @retval BROWSER_NO_CHANGES No browser data is changed.
4204 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4205 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4215 FORM_BROWSER_FORMSET
*FormSet
;
4216 BOOLEAN IsDataChanged
;
4217 UINT32 DataSavedAction
;
4218 CHAR16
*YesResponse
;
4220 CHAR16
*EmptyString
;
4221 CHAR16
*ChangeReminderString
;
4222 CHAR16
*SaveConfirmString
;
4225 DataSavedAction
= BROWSER_NO_CHANGES
;
4226 IsDataChanged
= FALSE
;
4227 Link
= GetFirstNode (&gBrowserFormSetList
);
4228 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4229 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4230 if (IsNvUpdateRequired (FormSet
)) {
4231 IsDataChanged
= TRUE
;
4234 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4238 // No data is changed. No save is required.
4240 if (!IsDataChanged
) {
4241 return DataSavedAction
;
4245 // If data is changed, prompt user
4247 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4249 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4250 ASSERT (YesResponse
!= NULL
);
4251 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4252 ASSERT (NoResponse
!= NULL
);
4253 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4254 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4255 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4258 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4260 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4261 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4265 // If the user hits the YesResponse key
4267 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4268 SubmitForm (NULL
, NULL
, SystemLevel
);
4269 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4271 DiscardForm (NULL
, NULL
, SystemLevel
);
4272 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4273 gResetRequired
= FALSE
;
4276 FreePool (YesResponse
);
4277 FreePool (NoResponse
);
4278 FreePool (EmptyString
);
4279 FreePool (SaveConfirmString
);
4280 FreePool (ChangeReminderString
);
4282 return DataSavedAction
;