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 (StrSize (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.
936 @param GetValueFrom Where to get source value, from EditValue or Value.
938 @retval EFI_SUCCESS Value found for given Name.
939 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
944 IN FORMSET_STORAGE
*Storage
,
946 IN OUT CHAR16
**Value
,
947 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
951 NAME_VALUE_NODE
*Node
;
953 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
954 return EFI_INVALID_PARAMETER
;
959 Link
= GetFirstNode (&Storage
->NameValueListHead
);
960 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
961 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
963 if (StrCmp (Name
, Node
->Name
) == 0) {
964 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
965 NewStringCpy (Value
, Node
->EditValue
);
967 NewStringCpy (Value
, Node
->Value
);
972 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
975 return EFI_NOT_FOUND
;
980 Set Value of given Name in a NameValue Storage.
982 @param Storage The NameValue Storage.
983 @param Name The Name.
984 @param Value The Value to set.
985 @param SetValueTo Whether update editValue or Value.
987 @retval EFI_SUCCESS Value found for given Name.
988 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
993 IN FORMSET_STORAGE
*Storage
,
996 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1000 NAME_VALUE_NODE
*Node
;
1003 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1004 return EFI_INVALID_PARAMETER
;
1007 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1008 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1009 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1011 if (StrCmp (Name
, Node
->Name
) == 0) {
1012 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1013 Buffer
= Node
->EditValue
;
1015 Buffer
= Node
->Value
;
1017 if (Buffer
!= NULL
) {
1020 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1021 ASSERT (Buffer
!= NULL
);
1022 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1023 Node
->EditValue
= Buffer
;
1025 Node
->Value
= Buffer
;
1030 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1033 return EFI_NOT_FOUND
;
1038 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1040 @param Buffer The Storage to be conveted.
1041 @param ConfigResp The returned <ConfigResp>.
1042 @param SingleForm Whether update data for single form or formset level.
1044 @retval EFI_SUCCESS Convert success.
1045 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1049 StorageToConfigResp (
1051 IN CHAR16
**ConfigResp
,
1052 IN BOOLEAN SingleForm
1056 EFI_STRING Progress
;
1058 NAME_VALUE_NODE
*Node
;
1059 CHAR16
*ConfigRequest
;
1060 FORMSET_STORAGE
*Storage
;
1061 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
1063 Status
= EFI_SUCCESS
;
1065 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
1066 Storage
= ConfigInfo
->Storage
;
1067 ConfigRequest
= ConfigInfo
->ConfigRequest
;
1069 Storage
= (FORMSET_STORAGE
*) Buffer
;
1070 ConfigRequest
= Storage
->ConfigRequest
;
1073 switch (Storage
->Type
) {
1074 case EFI_HII_VARSTORE_BUFFER
:
1075 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1076 Status
= mHiiConfigRouting
->BlockToConfig (
1079 Storage
->EditBuffer
,
1086 case EFI_HII_VARSTORE_NAME_VALUE
:
1088 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1090 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1091 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1092 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1094 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1095 NewStringCat (ConfigResp
, L
"&");
1096 NewStringCat (ConfigResp
, Node
->Name
);
1097 NewStringCat (ConfigResp
, L
"=");
1098 NewStringCat (ConfigResp
, Node
->EditValue
);
1100 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1104 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1106 Status
= EFI_INVALID_PARAMETER
;
1115 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1117 @param Storage The Storage to receive the settings.
1118 @param ConfigResp The <ConfigResp> to be converted.
1120 @retval EFI_SUCCESS Convert success.
1121 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1125 ConfigRespToStorage (
1126 IN FORMSET_STORAGE
*Storage
,
1127 IN CHAR16
*ConfigResp
1131 EFI_STRING Progress
;
1137 Status
= EFI_SUCCESS
;
1139 switch (Storage
->Type
) {
1140 case EFI_HII_VARSTORE_BUFFER
:
1141 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1142 BufferSize
= Storage
->Size
;
1143 Status
= mHiiConfigRouting
->ConfigToBlock (
1146 Storage
->EditBuffer
,
1152 case EFI_HII_VARSTORE_NAME_VALUE
:
1153 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1154 if (StrPtr
== NULL
) {
1157 StrPtr
= StrStr (ConfigResp
, L
"&");
1158 while (StrPtr
!= NULL
) {
1162 StrPtr
= StrPtr
+ 1;
1164 StrPtr
= StrStr (StrPtr
, L
"=");
1165 if (StrPtr
== NULL
) {
1173 StrPtr
= StrPtr
+ 1;
1175 StrPtr
= StrStr (StrPtr
, L
"&");
1176 if (StrPtr
!= NULL
) {
1179 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
);
1183 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1185 Status
= EFI_INVALID_PARAMETER
;
1194 Get Question's current Value.
1196 @param FormSet FormSet data structure.
1197 @param Form Form data structure.
1198 @param Question Question to be initialized.
1199 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1201 @retval EFI_SUCCESS The function completed successfully.
1206 IN FORM_BROWSER_FORMSET
*FormSet
,
1207 IN FORM_BROWSER_FORM
*Form
,
1208 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1209 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1218 FORMSET_STORAGE
*Storage
;
1219 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1220 CHAR16
*ConfigRequest
;
1228 BOOLEAN IsBufferStorage
;
1234 Status
= EFI_SUCCESS
;
1238 if (GetValueFrom
>= GetSetValueWithMax
) {
1239 return EFI_INVALID_PARAMETER
;
1243 // Statement don't have storage, skip them
1245 if (Question
->QuestionId
== 0) {
1250 // Question value is provided by an Expression, evaluate it
1252 if (Question
->ValueExpression
!= NULL
) {
1253 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1254 if (!EFI_ERROR (Status
)) {
1255 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1256 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1257 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1258 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1259 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1261 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1262 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1264 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1266 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1267 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1273 // Get question value by read expression.
1275 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1276 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1277 if (!EFI_ERROR (Status
) &&
1278 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1280 // Only update question value to the valid result.
1282 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1283 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1284 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1285 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1286 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1288 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1289 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1291 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1293 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1294 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1300 // Question value is provided by RTC
1302 Storage
= Question
->Storage
;
1303 QuestionValue
= &Question
->HiiValue
.Value
;
1304 if (Storage
== NULL
) {
1306 // It's a Question without storage, or RTC date/time
1308 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1310 // Date and time define the same Flags bit
1312 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1313 case QF_DATE_STORAGE_TIME
:
1314 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1317 case QF_DATE_STORAGE_WAKEUP
:
1318 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1321 case QF_DATE_STORAGE_NORMAL
:
1324 // For date/time without storage
1329 if (EFI_ERROR (Status
)) {
1333 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1334 QuestionValue
->date
.Year
= EfiTime
.Year
;
1335 QuestionValue
->date
.Month
= EfiTime
.Month
;
1336 QuestionValue
->date
.Day
= EfiTime
.Day
;
1338 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1339 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1340 QuestionValue
->time
.Second
= EfiTime
.Second
;
1348 // Question value is provided by EFI variable
1350 StorageWidth
= Question
->StorageWidth
;
1351 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1352 if (Question
->BufferValue
!= NULL
) {
1353 Dst
= Question
->BufferValue
;
1355 Dst
= (UINT8
*) QuestionValue
;
1358 Status
= gRT
->GetVariable (
1359 Question
->VariableName
,
1366 // Always return success, even this EFI variable doesn't exist
1372 // Question Value is provided by Buffer Storage or NameValue Storage
1374 if (Question
->BufferValue
!= NULL
) {
1376 // This Question is password or orderedlist
1378 Dst
= Question
->BufferValue
;
1381 // Other type of Questions
1383 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1386 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1387 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1388 IsBufferStorage
= TRUE
;
1390 IsBufferStorage
= FALSE
;
1392 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1393 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1394 if (IsBufferStorage
) {
1395 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1397 // Copy from storage Edit buffer
1399 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1402 // Copy from storage Edit buffer
1404 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1408 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1409 if (EFI_ERROR (Status
)) {
1413 ASSERT (Value
!= NULL
);
1414 LengthStr
= StrLen (Value
);
1415 Status
= EFI_SUCCESS
;
1418 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1419 // Add string tail char L'\0' into Length
1421 Length
= StorageWidth
+ sizeof (CHAR16
);
1422 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1423 Status
= EFI_BUFFER_TOO_SMALL
;
1425 StringPtr
= (CHAR16
*) Dst
;
1426 ZeroMem (TemStr
, sizeof (TemStr
));
1427 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1428 StrnCpy (TemStr
, Value
+ Index
, 4);
1429 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1432 // Add tailing L'\0' character
1434 StringPtr
[Index
/4] = L
'\0';
1437 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1438 Status
= EFI_BUFFER_TOO_SMALL
;
1440 ZeroMem (TemStr
, sizeof (TemStr
));
1441 for (Index
= 0; Index
< LengthStr
; Index
++) {
1442 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1443 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1444 if ((Index
& 1) == 0) {
1445 Dst
[Index
/2] = DigitUint8
;
1447 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1456 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1458 // Request current settings from Configuration Driver
1460 if (FormSet
->ConfigAccess
== NULL
) {
1461 return EFI_NOT_FOUND
;
1465 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1466 // <ConfigHdr> + "&" + <VariableName>
1468 if (IsBufferStorage
) {
1469 Length
= StrLen (Storage
->ConfigHdr
);
1470 Length
+= StrLen (Question
->BlockName
);
1472 Length
= StrLen (Storage
->ConfigHdr
);
1473 Length
+= StrLen (Question
->VariableName
) + 1;
1475 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1476 ASSERT (ConfigRequest
!= NULL
);
1478 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1479 if (IsBufferStorage
) {
1480 StrCat (ConfigRequest
, Question
->BlockName
);
1482 StrCat (ConfigRequest
, L
"&");
1483 StrCat (ConfigRequest
, Question
->VariableName
);
1486 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1487 FormSet
->ConfigAccess
,
1492 FreePool (ConfigRequest
);
1493 if (EFI_ERROR (Status
)) {
1498 // Skip <ConfigRequest>
1500 if (IsBufferStorage
) {
1501 Value
= StrStr (Result
, L
"&VALUE");
1502 if (Value
== NULL
) {
1504 return EFI_NOT_FOUND
;
1511 Value
= Result
+ Length
;
1513 if (*Value
!= '=') {
1515 return EFI_NOT_FOUND
;
1518 // Skip '=', point to value
1523 // Suppress <AltResp> if any
1526 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1531 LengthStr
= StrLen (Value
);
1532 Status
= EFI_SUCCESS
;
1533 if (!IsBufferStorage
&& IsString
) {
1535 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1536 // Add string tail char L'\0' into Length
1538 Length
= StorageWidth
+ sizeof (CHAR16
);
1539 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1540 Status
= EFI_BUFFER_TOO_SMALL
;
1542 StringPtr
= (CHAR16
*) Dst
;
1543 ZeroMem (TemStr
, sizeof (TemStr
));
1544 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1545 StrnCpy (TemStr
, Value
+ Index
, 4);
1546 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1549 // Add tailing L'\0' character
1551 StringPtr
[Index
/4] = L
'\0';
1554 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1555 Status
= EFI_BUFFER_TOO_SMALL
;
1557 ZeroMem (TemStr
, sizeof (TemStr
));
1558 for (Index
= 0; Index
< LengthStr
; Index
++) {
1559 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1560 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1561 if ((Index
& 1) == 0) {
1562 Dst
[Index
/2] = DigitUint8
;
1564 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1570 if (EFI_ERROR (Status
)) {
1574 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1576 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1577 if (TemBuffer
== NULL
) {
1578 Status
= EFI_OUT_OF_RESOURCES
;
1581 Length
= Storage
->Size
;
1582 Status
= gRT
->GetVariable (
1589 if (EFI_ERROR (Status
)) {
1590 FreePool (TemBuffer
);
1594 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1596 FreePool (TemBuffer
);
1600 // Synchronize Edit Buffer
1602 if (IsBufferStorage
) {
1603 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1605 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
);
1608 if (Result
!= NULL
) {
1618 Save Question Value to edit copy(cached) or Storage(uncached).
1620 @param FormSet FormSet data structure.
1621 @param Form Form data structure.
1622 @param Question Pointer to the Question.
1623 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1625 @retval EFI_SUCCESS The function completed successfully.
1630 IN FORM_BROWSER_FORMSET
*FormSet
,
1631 IN FORM_BROWSER_FORM
*Form
,
1632 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1633 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1643 FORMSET_STORAGE
*Storage
;
1644 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1649 BOOLEAN IsBufferStorage
;
1656 Status
= EFI_SUCCESS
;
1658 if (SetValueTo
>= GetSetValueWithMax
) {
1659 return EFI_INVALID_PARAMETER
;
1663 // Statement don't have storage, skip them
1665 if (Question
->QuestionId
== 0) {
1670 // If Question value is provided by an Expression, then it is read only
1672 if (Question
->ValueExpression
!= NULL
) {
1677 // Before set question value, evaluate its write expression.
1679 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1680 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1681 if (EFI_ERROR (Status
)) {
1687 // Question value is provided by RTC
1689 Storage
= Question
->Storage
;
1690 QuestionValue
= &Question
->HiiValue
.Value
;
1691 if (Storage
== NULL
) {
1693 // It's a Question without storage, or RTC date/time
1695 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1697 // Date and time define the same Flags bit
1699 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1700 case QF_DATE_STORAGE_TIME
:
1701 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1704 case QF_DATE_STORAGE_WAKEUP
:
1705 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1708 case QF_DATE_STORAGE_NORMAL
:
1711 // For date/time without storage
1716 if (EFI_ERROR (Status
)) {
1720 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1721 EfiTime
.Year
= QuestionValue
->date
.Year
;
1722 EfiTime
.Month
= QuestionValue
->date
.Month
;
1723 EfiTime
.Day
= QuestionValue
->date
.Day
;
1725 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1726 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1727 EfiTime
.Second
= QuestionValue
->time
.Second
;
1730 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1731 Status
= gRT
->SetTime (&EfiTime
);
1733 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1741 // Question value is provided by EFI variable
1743 StorageWidth
= Question
->StorageWidth
;
1744 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1745 if (Question
->BufferValue
!= NULL
) {
1746 Src
= Question
->BufferValue
;
1748 Src
= (UINT8
*) QuestionValue
;
1751 Status
= gRT
->SetVariable (
1752 Question
->VariableName
,
1754 Storage
->Attributes
,
1762 // Question Value is provided by Buffer Storage or NameValue Storage
1764 if (Question
->BufferValue
!= NULL
) {
1765 Src
= Question
->BufferValue
;
1767 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1770 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1771 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1772 IsBufferStorage
= TRUE
;
1774 IsBufferStorage
= FALSE
;
1776 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1778 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1779 if (IsBufferStorage
) {
1780 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1782 // Copy to storage edit buffer
1784 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1785 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1787 // Copy to storage edit buffer
1789 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1794 // Allocate enough string buffer.
1797 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1798 Value
= AllocateZeroPool (BufferLen
);
1799 ASSERT (Value
!= NULL
);
1801 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1803 TemName
= (CHAR16
*) Src
;
1805 for (; *TemName
!= L
'\0'; TemName
++) {
1806 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1809 BufferLen
= StorageWidth
* 2 + 1;
1810 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1811 ASSERT (Value
!= NULL
);
1813 // Convert Buffer to Hex String
1815 TemBuffer
= Src
+ StorageWidth
- 1;
1817 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1818 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1822 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
);
1825 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1826 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1828 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1829 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1831 if (IsBufferStorage
) {
1832 Length
= StrLen (Question
->BlockName
) + 7;
1834 Length
= StrLen (Question
->VariableName
) + 2;
1836 if (!IsBufferStorage
&& IsString
) {
1837 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1839 Length
+= (StorageWidth
* 2);
1841 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1842 ASSERT (ConfigResp
!= NULL
);
1844 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1845 if (IsBufferStorage
) {
1846 StrCat (ConfigResp
, Question
->BlockName
);
1847 StrCat (ConfigResp
, L
"&VALUE=");
1849 StrCat (ConfigResp
, L
"&");
1850 StrCat (ConfigResp
, Question
->VariableName
);
1851 StrCat (ConfigResp
, L
"=");
1854 Value
= ConfigResp
+ StrLen (ConfigResp
);
1856 if (!IsBufferStorage
&& IsString
) {
1858 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1860 TemName
= (CHAR16
*) Src
;
1862 for (; *TemName
!= L
'\0'; TemName
++) {
1863 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1867 // Convert Buffer to Hex String
1869 TemBuffer
= Src
+ StorageWidth
- 1;
1871 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1872 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1877 // Convert to lower char.
1879 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1880 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1881 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1886 // Submit Question Value to Configuration Driver
1888 if (FormSet
->ConfigAccess
!= NULL
) {
1889 Status
= FormSet
->ConfigAccess
->RouteConfig (
1890 FormSet
->ConfigAccess
,
1894 if (EFI_ERROR (Status
)) {
1895 FreePool (ConfigResp
);
1899 FreePool (ConfigResp
);
1901 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1903 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1904 if (TemBuffer
== NULL
) {
1905 Status
= EFI_OUT_OF_RESOURCES
;
1908 Length
= Storage
->Size
;
1909 Status
= gRT
->GetVariable (
1917 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1919 Status
= gRT
->SetVariable (
1922 Storage
->Attributes
,
1926 FreePool (TemBuffer
);
1927 if (EFI_ERROR (Status
)){
1932 // Sync storage, from editbuffer to buffer.
1934 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1942 Perform inconsistent check for a Form.
1944 @param FormSet FormSet data structure.
1945 @param Form Form data structure.
1946 @param Question The Question to be validated.
1947 @param Type Validation type: InConsistent or NoSubmit
1949 @retval EFI_SUCCESS Form validation pass.
1950 @retval other Form validation failed.
1955 IN FORM_BROWSER_FORMSET
*FormSet
,
1956 IN FORM_BROWSER_FORM
*Form
,
1957 IN FORM_BROWSER_STATEMENT
*Question
,
1963 LIST_ENTRY
*ListHead
;
1966 FORM_EXPRESSION
*Expression
;
1968 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1969 ListHead
= &Question
->InconsistentListHead
;
1970 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1971 ListHead
= &Question
->NoSubmitListHead
;
1973 return EFI_UNSUPPORTED
;
1976 Link
= GetFirstNode (ListHead
);
1977 while (!IsNull (ListHead
, Link
)) {
1978 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1981 // Evaluate the expression
1983 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1984 if (EFI_ERROR (Status
)) {
1988 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1990 // Condition meet, show up error message
1992 if (Expression
->Error
!= 0) {
1993 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1995 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1996 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
2000 return EFI_NOT_READY
;
2003 Link
= GetNextNode (ListHead
, Link
);
2011 Perform NoSubmit check for each Form in FormSet.
2013 @param FormSet FormSet data structure.
2014 @param CurrentForm Current input form data structure.
2016 @retval EFI_SUCCESS Form validation pass.
2017 @retval other Form validation failed.
2022 IN FORM_BROWSER_FORMSET
*FormSet
,
2023 IN FORM_BROWSER_FORM
*CurrentForm
2028 FORM_BROWSER_STATEMENT
*Question
;
2029 FORM_BROWSER_FORM
*Form
;
2030 LIST_ENTRY
*LinkForm
;
2032 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2033 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2034 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2035 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2037 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2041 Link
= GetFirstNode (&Form
->StatementListHead
);
2042 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2043 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2045 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2046 if (EFI_ERROR (Status
)) {
2050 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2058 Fill storage's edit copy with settings requested from Configuration Driver.
2060 @param FormSet FormSet data structure.
2061 @param ConfigInfo The config info related to this form.
2062 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2063 editbuffer to buffer
2064 if TRUE, copy the editbuffer to the buffer.
2065 if FALSE, copy the buffer to the editbuffer.
2067 @retval EFI_SUCCESS The function completed successfully.
2071 SynchronizeStorageForForm (
2072 IN FORM_BROWSER_FORMSET
*FormSet
,
2073 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2074 IN BOOLEAN SyncOrRestore
2078 EFI_STRING Progress
;
2082 NAME_VALUE_NODE
*Node
;
2086 Status
= EFI_SUCCESS
;
2088 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2089 return EFI_NOT_FOUND
;
2092 if (ConfigInfo
->ElementCount
== 0) {
2094 // Skip if there is no RequestElement
2099 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2100 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2101 BufferSize
= ConfigInfo
->Storage
->Size
;
2103 if (SyncOrRestore
) {
2104 Src
= ConfigInfo
->Storage
->EditBuffer
;
2105 Dst
= ConfigInfo
->Storage
->Buffer
;
2107 Src
= ConfigInfo
->Storage
->Buffer
;
2108 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2111 Status
= mHiiConfigRouting
->BlockToConfig(
2113 ConfigInfo
->ConfigRequest
,
2119 if (EFI_ERROR (Status
)) {
2123 Status
= mHiiConfigRouting
->ConfigToBlock (
2130 if (Result
!= NULL
) {
2133 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2134 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2135 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2136 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2138 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2139 if (SyncOrRestore
) {
2140 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2142 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2146 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2154 When discard the question value, call the callback function with Changed type
2155 to inform the hii driver.
2157 @param FormSet FormSet data structure.
2158 @param Form Form data structure.
2162 SendDiscardInfoToDriver (
2163 IN FORM_BROWSER_FORMSET
*FormSet
,
2164 IN FORM_BROWSER_FORM
*Form
2168 FORM_BROWSER_STATEMENT
*Question
;
2170 EFI_HII_VALUE HiiValue
;
2172 BOOLEAN ValueChanged
;
2173 EFI_IFR_TYPE_VALUE
*TypeValue
;
2174 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2176 ValueChanged
= FALSE
;
2179 if(!Form
->NvUpdateRequired
) {
2183 Link
= GetFirstNode (&Form
->StatementListHead
);
2184 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2185 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2186 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2188 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2192 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2196 if (Question
->BufferValue
!= NULL
) {
2197 BufferValue
= AllocateZeroPool (Question
->StorageWidth
);
2198 ASSERT (BufferValue
!= NULL
);
2199 CopyMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
);
2201 HiiValue
.Type
= Question
->HiiValue
.Type
;
2202 CopyMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2205 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
2206 if (EFI_ERROR (Status
)) {
2207 if (BufferValue
!= NULL
) {
2208 FreePool (BufferValue
);
2214 if (Question
->BufferValue
!= NULL
) {
2215 if (CompareMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
)) {
2216 ValueChanged
= TRUE
;
2219 if (CompareMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
))) {
2220 ValueChanged
= TRUE
;
2224 if (BufferValue
!= NULL
) {
2225 FreePool (BufferValue
);
2229 if (!ValueChanged
) {
2233 ValueChanged
= FALSE
;
2235 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2236 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2238 TypeValue
= &Question
->HiiValue
.Value
;
2241 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2242 FormSet
->ConfigAccess
->Callback (
2243 FormSet
->ConfigAccess
,
2244 EFI_BROWSER_ACTION_CHANGED
,
2245 Question
->QuestionId
,
2246 Question
->HiiValue
.Type
,
2254 Discard data based on the input setting scope (Form, FormSet or System).
2256 @param FormSet FormSet data structure.
2257 @param Form Form data structure.
2258 @param SettingScope Setting Scope for Discard action.
2260 @retval EFI_SUCCESS The function completed successfully.
2261 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2266 IN FORM_BROWSER_FORMSET
*FormSet
,
2267 IN FORM_BROWSER_FORM
*Form
,
2268 IN BROWSER_SETTING_SCOPE SettingScope
2272 FORMSET_STORAGE
*Storage
;
2273 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2274 FORM_BROWSER_FORMSET
*LocalFormSet
;
2277 // Check the supported setting level.
2279 if (SettingScope
>= MaxLevel
) {
2280 return EFI_UNSUPPORTED
;
2283 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2285 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2286 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2287 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2288 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2290 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2295 // Skip if there is no RequestElement
2297 if (ConfigInfo
->ElementCount
== 0) {
2302 // Prepare <ConfigResp>
2304 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2307 // Call callback with Changed type to inform the driver.
2309 SendDiscardInfoToDriver (FormSet
, Form
);
2312 Form
->NvUpdateRequired
= FALSE
;
2313 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2316 // Discard Buffer storage or Name/Value storage
2318 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2319 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2320 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2321 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2323 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2328 // Skip if there is no RequestElement
2330 if (Storage
->ElementCount
== 0) {
2334 SynchronizeStorage(Storage
, FALSE
);
2337 Link
= GetFirstNode (&FormSet
->FormListHead
);
2338 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2339 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2340 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2343 // Call callback with Changed type to inform the driver.
2345 SendDiscardInfoToDriver (FormSet
, Form
);
2348 UpdateNvInfoInForm (FormSet
, FALSE
);
2349 } else if (SettingScope
== SystemLevel
) {
2351 // System Level Discard.
2355 // Discard changed value for each FormSet in the maintain list.
2357 Link
= GetFirstNode (&gBrowserFormSetList
);
2358 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2359 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2360 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2361 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2362 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2364 // Remove maintain backup list after discard except for the current using FormSet.
2366 RemoveEntryList (&LocalFormSet
->Link
);
2367 DestroyFormSet (LocalFormSet
);
2376 Submit data based on the input Setting level (Form, FormSet or System).
2378 @param FormSet FormSet data structure.
2379 @param Form Form data structure.
2380 @param SettingScope Setting Scope for Submit action.
2382 @retval EFI_SUCCESS The function completed successfully.
2383 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2388 IN FORM_BROWSER_FORMSET
*FormSet
,
2389 IN FORM_BROWSER_FORM
*Form
,
2390 IN BROWSER_SETTING_SCOPE SettingScope
2395 EFI_STRING ConfigResp
;
2396 EFI_STRING Progress
;
2397 FORMSET_STORAGE
*Storage
;
2400 FORM_BROWSER_FORMSET
*LocalFormSet
;
2401 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2404 // Check the supported setting level.
2406 if (SettingScope
>= MaxLevel
) {
2407 return EFI_UNSUPPORTED
;
2411 // Validate the Form by NoSubmit check
2413 Status
= EFI_SUCCESS
;
2414 if (SettingScope
== FormLevel
) {
2415 Status
= NoSubmitCheck (FormSet
, Form
);
2416 } else if (SettingScope
== FormSetLevel
) {
2417 Status
= NoSubmitCheck (FormSet
, NULL
);
2419 if (EFI_ERROR (Status
)) {
2423 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2425 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2426 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2427 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2428 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2430 Storage
= ConfigInfo
->Storage
;
2431 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2436 // Skip if there is no RequestElement
2438 if (ConfigInfo
->ElementCount
== 0) {
2443 // 1. Prepare <ConfigResp>
2445 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2446 if (EFI_ERROR (Status
)) {
2451 // 2. Set value to hii driver or efi variable.
2453 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2454 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2456 // Send <ConfigResp> to Configuration Driver
2458 if (FormSet
->ConfigAccess
!= NULL
) {
2459 Status
= FormSet
->ConfigAccess
->RouteConfig (
2460 FormSet
->ConfigAccess
,
2464 if (EFI_ERROR (Status
)) {
2465 FreePool (ConfigResp
);
2469 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2471 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2472 if (TmpBuf
== NULL
) {
2473 Status
= EFI_OUT_OF_RESOURCES
;
2477 BufferSize
= Storage
->Size
;
2478 Status
= gRT
->GetVariable (
2485 if (EFI_ERROR (Status
)) {
2487 FreePool (ConfigResp
);
2490 ASSERT (BufferSize
== Storage
->Size
);
2491 Status
= mHiiConfigRouting
->ConfigToBlock (
2498 if (EFI_ERROR (Status
)) {
2500 FreePool (ConfigResp
);
2504 Status
= gRT
->SetVariable (
2507 Storage
->Attributes
,
2512 if (EFI_ERROR (Status
)) {
2513 FreePool (ConfigResp
);
2517 FreePool (ConfigResp
);
2519 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2521 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2525 // 4. Update the NV flag.
2527 Form
->NvUpdateRequired
= FALSE
;
2528 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2530 // Submit Buffer storage or Name/Value storage
2532 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2533 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2534 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2535 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2537 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2542 // Skip if there is no RequestElement
2544 if (Storage
->ElementCount
== 0) {
2549 // 1. Prepare <ConfigResp>
2551 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2552 if (EFI_ERROR (Status
)) {
2556 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2557 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2560 // 2. Send <ConfigResp> to Configuration Driver
2562 if (FormSet
->ConfigAccess
!= NULL
) {
2563 Status
= FormSet
->ConfigAccess
->RouteConfig (
2564 FormSet
->ConfigAccess
,
2568 if (EFI_ERROR (Status
)) {
2569 FreePool (ConfigResp
);
2573 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2575 // 1&2. Set the edit data to the variable.
2578 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2579 if (TmpBuf
== NULL
) {
2580 Status
= EFI_OUT_OF_RESOURCES
;
2583 BufferSize
= Storage
->Size
;
2584 Status
= gRT
->GetVariable (
2591 ASSERT (BufferSize
== Storage
->Size
);
2592 Status
= mHiiConfigRouting
->ConfigToBlock (
2599 if (EFI_ERROR (Status
)) {
2601 FreePool (ConfigResp
);
2605 Status
= gRT
->SetVariable (
2608 Storage
->Attributes
,
2612 if (EFI_ERROR (Status
)) {
2614 FreePool (ConfigResp
);
2619 FreePool (ConfigResp
);
2621 // 3. Config success, update storage shadow Buffer
2623 SynchronizeStorage (Storage
, TRUE
);
2627 // 4. Update the NV flag.
2629 UpdateNvInfoInForm (FormSet
, FALSE
);
2630 } else if (SettingScope
== SystemLevel
) {
2632 // System Level Save.
2636 // Save changed value for each FormSet in the maintain list.
2638 Link
= GetFirstNode (&gBrowserFormSetList
);
2639 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2640 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2641 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2642 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2643 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2645 // Remove maintain backup list after save except for the current using FormSet.
2647 RemoveEntryList (&LocalFormSet
->Link
);
2648 DestroyFormSet (LocalFormSet
);
2657 Get Question default value from AltCfg string.
2659 @param FormSet The form set.
2660 @param Question The question.
2661 @param DefaultId The default Id.
2663 @retval EFI_SUCCESS Question is reset to default value.
2667 GetDefaultValueFromAltCfg (
2668 IN FORM_BROWSER_FORMSET
*FormSet
,
2669 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2673 BOOLEAN IsBufferStorage
;
2676 FORMSET_STORAGE
*Storage
;
2677 CHAR16
*ConfigRequest
;
2690 Status
= EFI_NOT_FOUND
;
2693 ConfigRequest
= NULL
;
2697 Storage
= Question
->Storage
;
2699 if ((Storage
== NULL
) ||
2700 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2701 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2706 // Question Value is provided by Buffer Storage or NameValue Storage
2708 if (Question
->BufferValue
!= NULL
) {
2710 // This Question is password or orderedlist
2712 Dst
= Question
->BufferValue
;
2715 // Other type of Questions
2717 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2720 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2721 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2724 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2725 // <ConfigHdr> + "&" + <VariableName>
2727 if (IsBufferStorage
) {
2728 Length
= StrLen (Storage
->ConfigHdr
);
2729 Length
+= StrLen (Question
->BlockName
);
2731 Length
= StrLen (Storage
->ConfigHdr
);
2732 Length
+= StrLen (Question
->VariableName
) + 1;
2734 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2735 ASSERT (ConfigRequest
!= NULL
);
2737 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2738 if (IsBufferStorage
) {
2739 StrCat (ConfigRequest
, Question
->BlockName
);
2741 StrCat (ConfigRequest
, L
"&");
2742 StrCat (ConfigRequest
, Question
->VariableName
);
2745 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2746 FormSet
->ConfigAccess
,
2751 if (EFI_ERROR (Status
)) {
2756 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2757 // Get the default configuration string according to the default ID.
2759 Status
= mHiiConfigRouting
->GetAltConfig (
2765 &DefaultId
, // it can be NULL to get the current setting.
2770 // The required setting can't be found. So, it is not required to be validated and set.
2772 if (EFI_ERROR (Status
)) {
2777 // Skip <ConfigRequest>
2779 if (IsBufferStorage
) {
2780 Value
= StrStr (ConfigResp
, L
"&VALUE");
2781 ASSERT (Value
!= NULL
);
2787 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2788 ASSERT (Value
!= NULL
);
2790 Value
= Value
+ StrLen (Question
->VariableName
);
2792 if (*Value
!= '=') {
2793 Status
= EFI_NOT_FOUND
;
2797 // Skip '=', point to value
2802 // Suppress <AltResp> if any
2805 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2810 LengthStr
= StrLen (Value
);
2811 if (!IsBufferStorage
&& IsString
) {
2812 StringPtr
= (CHAR16
*) Dst
;
2813 ZeroMem (TemStr
, sizeof (TemStr
));
2814 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2815 StrnCpy (TemStr
, Value
+ Index
, 4);
2816 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2819 // Add tailing L'\0' character
2821 StringPtr
[Index
/4] = L
'\0';
2823 ZeroMem (TemStr
, sizeof (TemStr
));
2824 for (Index
= 0; Index
< LengthStr
; Index
++) {
2825 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2826 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2827 if ((Index
& 1) == 0) {
2828 Dst
[Index
/2] = DigitUint8
;
2830 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2836 if (ConfigRequest
!= NULL
){
2837 FreePool (ConfigRequest
);
2840 if (ConfigResp
!= NULL
) {
2841 FreePool (ConfigResp
);
2844 if (Result
!= NULL
) {
2852 Get default Id value used for browser.
2854 @param DefaultId The default id value used by hii.
2856 @retval Browser used default value.
2860 GetDefaultIdForCallBack (
2864 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2865 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2866 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2867 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2868 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2869 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2870 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2871 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2872 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2873 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2874 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2875 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2882 Reset Question to its default value.
2884 @param FormSet The form set.
2885 @param Form The form.
2886 @param Question The question.
2887 @param DefaultId The Class of the default.
2889 @retval EFI_SUCCESS Question is reset to default value.
2893 GetQuestionDefault (
2894 IN FORM_BROWSER_FORMSET
*FormSet
,
2895 IN FORM_BROWSER_FORM
*Form
,
2896 IN FORM_BROWSER_STATEMENT
*Question
,
2902 QUESTION_DEFAULT
*Default
;
2903 QUESTION_OPTION
*Option
;
2904 EFI_HII_VALUE
*HiiValue
;
2906 EFI_STRING StrValue
;
2907 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2908 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2911 Status
= EFI_NOT_FOUND
;
2915 // Statement don't have storage, skip them
2917 if (Question
->QuestionId
== 0) {
2922 // There are Five ways to specify default value for a Question:
2923 // 1, use call back function (highest priority)
2924 // 2, use ExtractConfig function
2925 // 3, use nested EFI_IFR_DEFAULT
2926 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2927 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2929 HiiValue
= &Question
->HiiValue
;
2932 // Get Question defaut value from call back function.
2934 ConfigAccess
= FormSet
->ConfigAccess
;
2935 Action
= GetDefaultIdForCallBack (DefaultId
);
2936 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2937 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2938 Status
= ConfigAccess
->Callback (
2941 Question
->QuestionId
,
2946 if (!EFI_ERROR (Status
)) {
2952 // Get default value from altcfg string.
2954 if (ConfigAccess
!= NULL
) {
2955 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2956 if (!EFI_ERROR (Status
)) {
2962 // EFI_IFR_DEFAULT has highest priority
2964 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2965 Link
= GetFirstNode (&Question
->DefaultListHead
);
2966 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2967 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2969 if (Default
->DefaultId
== DefaultId
) {
2970 if (Default
->ValueExpression
!= NULL
) {
2972 // Default is provided by an Expression, evaluate it
2974 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2975 if (EFI_ERROR (Status
)) {
2979 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
2980 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
2981 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
2982 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
2983 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
2985 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
2986 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
2988 FreePool (Default
->ValueExpression
->Result
.Buffer
);
2990 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
2991 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2994 // Default value is embedded in EFI_IFR_DEFAULT
2996 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2999 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3000 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3001 if (StrValue
== NULL
) {
3002 return EFI_NOT_FOUND
;
3004 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3005 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3007 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3014 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3019 // EFI_ONE_OF_OPTION
3021 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3022 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3024 // OneOfOption could only provide Standard and Manufacturing default
3026 Link
= GetFirstNode (&Question
->OptionListHead
);
3027 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3028 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3029 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3031 if ((Option
->SuppressExpression
!= NULL
) &&
3032 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3036 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3037 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3039 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3048 // EFI_IFR_CHECKBOX - lowest priority
3050 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3051 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3053 // Checkbox could only provide Standard and Manufacturing default
3055 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3056 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3058 HiiValue
->Value
.b
= TRUE
;
3060 HiiValue
->Value
.b
= FALSE
;
3068 // For Questions without default
3070 Status
= EFI_NOT_FOUND
;
3071 switch (Question
->Operand
) {
3072 case EFI_IFR_NUMERIC_OP
:
3074 // Take minimum value as numeric default value
3076 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3077 HiiValue
->Value
.u64
= Question
->Minimum
;
3078 Status
= EFI_SUCCESS
;
3082 case EFI_IFR_ONE_OF_OP
:
3084 // Take first oneof option as oneof's default value
3086 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3087 Link
= GetFirstNode (&Question
->OptionListHead
);
3088 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3089 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3090 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3092 if ((Option
->SuppressExpression
!= NULL
) &&
3093 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3097 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3098 Status
= EFI_SUCCESS
;
3104 case EFI_IFR_ORDERED_LIST_OP
:
3106 // Take option sequence in IFR as ordered list's default value
3109 Link
= GetFirstNode (&Question
->OptionListHead
);
3110 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3111 Status
= EFI_SUCCESS
;
3112 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3113 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3115 if ((Option
->SuppressExpression
!= NULL
) &&
3116 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3120 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3123 if (Index
>= Question
->MaxContainers
) {
3138 Reset Questions to their initial value or default value in a Form, Formset or System.
3140 GetDefaultValueScope parameter decides which questions will reset
3141 to its default value.
3143 @param FormSet FormSet data structure.
3144 @param Form Form data structure.
3145 @param DefaultId The Class of the default.
3146 @param SettingScope Setting Scope for Default action.
3147 @param GetDefaultValueScope Get default value scope.
3148 @param Storage Get default value only for this storage.
3149 @param RetrieveValueFirst Whether call the retrieve call back to
3150 get the initial value before get default
3153 @retval EFI_SUCCESS The function completed successfully.
3154 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3159 IN FORM_BROWSER_FORMSET
*FormSet
,
3160 IN FORM_BROWSER_FORM
*Form
,
3161 IN UINT16 DefaultId
,
3162 IN BROWSER_SETTING_SCOPE SettingScope
,
3163 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3164 IN FORMSET_STORAGE
*Storage OPTIONAL
,
3165 IN BOOLEAN RetrieveValueFirst
3169 LIST_ENTRY
*FormLink
;
3171 FORM_BROWSER_STATEMENT
*Question
;
3172 FORM_BROWSER_FORMSET
*BackUpFormSet
;
3173 FORM_BROWSER_FORMSET
*LocalFormSet
;
3174 EFI_HII_HANDLE
*HiiHandles
;
3178 Status
= EFI_SUCCESS
;
3181 // Check the supported setting level.
3183 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3184 return EFI_UNSUPPORTED
;
3187 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3188 return EFI_UNSUPPORTED
;
3191 if (SettingScope
== FormLevel
) {
3193 // Extract Form default
3195 Link
= GetFirstNode (&Form
->StatementListHead
);
3196 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3197 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3198 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3201 // If get default value only for this storage, check the storage first.
3203 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3208 // If get default value only for no storage question, just skip the question which has storage.
3210 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3215 // If Question is disabled, don't reset it to default
3217 if (Question
->Expression
!= NULL
) {
3218 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3223 if (RetrieveValueFirst
) {
3225 // Call the Retrieve call back to get the initial question value.
3227 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3231 // If not request to get the initial value or get initial value fail, then get default value.
3233 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3234 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3235 if (EFI_ERROR (Status
)) {
3241 // Synchronize Buffer storage's Edit buffer
3243 if ((Question
->Storage
!= NULL
) &&
3244 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3245 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3247 // Update Form NV flag.
3249 Form
->NvUpdateRequired
= TRUE
;
3252 } else if (SettingScope
== FormSetLevel
) {
3253 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3254 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3255 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3256 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3257 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3259 } else if (SettingScope
== SystemLevel
) {
3261 // Open all FormSet by locate HII packages.
3262 // Initiliaze the maintain FormSet to store default data as back up data.
3264 BackUpFormSet
= gOldFormSet
;
3268 // Get all the Hii handles
3270 HiiHandles
= HiiGetHiiHandles (NULL
);
3271 ASSERT (HiiHandles
!= NULL
);
3274 // Search for formset of each class type
3276 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3278 // Check HiiHandles[Index] does exist in global maintain list.
3280 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3285 // Initilize FormSet Setting
3287 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3288 ASSERT (LocalFormSet
!= NULL
);
3289 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3290 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
, FALSE
);
3291 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3292 DestroyFormSet (LocalFormSet
);
3295 Status
= InitializeCurrentSetting (LocalFormSet
);
3296 if (EFI_ERROR (Status
)) {
3297 DestroyFormSet (LocalFormSet
);
3301 // Initilize Questions' Value
3303 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
3304 if (EFI_ERROR (Status
)) {
3305 DestroyFormSet (LocalFormSet
);
3310 // Add FormSet into the maintain list.
3312 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3316 // Free resources, and restore gOldFormSet and gClassOfVfr
3318 FreePool (HiiHandles
);
3319 gOldFormSet
= BackUpFormSet
;
3322 // Set Default Value for each FormSet in the maintain list.
3324 Link
= GetFirstNode (&gBrowserFormSetList
);
3325 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3326 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3327 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3328 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3336 Initialize Question's Edit copy from Storage.
3338 @param Selection Selection contains the information about
3339 the Selection, form and formset to be displayed.
3340 Selection action may be updated in retrieve callback.
3341 If Selection is NULL, only initialize Question value.
3342 @param FormSet FormSet data structure.
3343 @param Form Form data structure.
3345 @retval EFI_SUCCESS The function completed successfully.
3350 IN OUT UI_MENU_SELECTION
*Selection
,
3351 IN FORM_BROWSER_FORMSET
*FormSet
,
3352 IN FORM_BROWSER_FORM
*Form
3357 FORM_BROWSER_STATEMENT
*Question
;
3361 Link
= GetFirstNode (&Form
->StatementListHead
);
3362 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3363 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3366 // Initialize local copy of Value for each Question
3368 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3369 if (EFI_ERROR (Status
)) {
3373 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3374 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3378 // Call the Retrieve call back function for all questions.
3380 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3381 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3383 // Check QuestionValue does exist.
3385 StorageWidth
= Question
->StorageWidth
;
3386 if (Question
->BufferValue
!= NULL
) {
3387 BufferValue
= Question
->BufferValue
;
3389 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3393 // For efivarstore storage, initial question value first.
3395 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3396 Status
= gRT
->GetVariable (
3397 Question
->VariableName
,
3398 &Question
->Storage
->Guid
,
3405 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3408 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3415 Initialize Question's Edit copy from Storage for the whole Formset.
3417 @param Selection Selection contains the information about
3418 the Selection, form and formset to be displayed.
3419 Selection action may be updated in retrieve callback.
3420 If Selection is NULL, only initialize Question value.
3421 @param FormSet FormSet data structure.
3423 @retval EFI_SUCCESS The function completed successfully.
3428 IN OUT UI_MENU_SELECTION
*Selection
,
3429 IN FORM_BROWSER_FORMSET
*FormSet
3434 FORM_BROWSER_FORM
*Form
;
3436 Link
= GetFirstNode (&FormSet
->FormListHead
);
3437 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3438 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3441 // Initialize local copy of Value for each Form
3443 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3444 if (EFI_ERROR (Status
)) {
3448 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3455 Fill storage's edit copy with settings requested from Configuration Driver.
3457 @param FormSet FormSet data structure.
3458 @param Storage Buffer Storage.
3460 @retval EFI_SUCCESS The function completed successfully.
3465 IN FORM_BROWSER_FORMSET
*FormSet
,
3466 IN FORMSET_STORAGE
*Storage
3470 EFI_STRING Progress
;
3474 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3478 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3479 Status
= gRT
->GetVariable (
3483 (UINTN
*)&Storage
->Size
,
3489 if (FormSet
->ConfigAccess
== NULL
) {
3490 return EFI_NOT_FOUND
;
3493 if (Storage
->ElementCount
== 0) {
3495 // Skip if there is no RequestElement
3501 // Request current settings from Configuration Driver
3503 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3504 FormSet
->ConfigAccess
,
3505 Storage
->ConfigRequest
,
3509 if (EFI_ERROR (Status
)) {
3514 // Convert Result from <ConfigAltResp> to <ConfigResp>
3516 StrPtr
= StrStr (Result
, L
"ALTCFG");
3517 if (StrPtr
!= NULL
) {
3521 Status
= ConfigRespToStorage (Storage
, Result
);
3528 Copy uncommitted data from source Storage to destination Storage.
3530 @param Dst Target Storage for uncommitted data.
3531 @param Src Source Storage for uncommitted data.
3533 @retval EFI_SUCCESS The function completed successfully.
3534 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
3539 IN OUT FORMSET_STORAGE
*Dst
,
3540 IN FORMSET_STORAGE
*Src
3544 NAME_VALUE_NODE
*Node
;
3546 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
3547 return EFI_INVALID_PARAMETER
;
3550 switch (Src
->Type
) {
3551 case EFI_HII_VARSTORE_BUFFER
:
3552 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3553 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
3554 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
3557 case EFI_HII_VARSTORE_NAME_VALUE
:
3558 Link
= GetFirstNode (&Src
->NameValueListHead
);
3559 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
3560 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3562 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, GetSetValueWithEditBuffer
);
3563 SetValueByName (Dst
, Node
->Name
, Node
->Value
, GetSetValueWithBuffer
);
3565 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
3569 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3578 Get old question value from the saved formset.
3580 @param Statement The question which need to get old question value.
3581 @param OldFormSet FormSet data structure saved in the list.
3585 GetOldQuestionValue (
3586 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
3587 IN FORM_BROWSER_FORMSET
*OldFormSet
3590 LIST_ENTRY
*FormLink
;
3592 FORM_BROWSER_STATEMENT
*Question
;
3593 FORM_BROWSER_FORM
*Form
;
3595 FormLink
= GetFirstNode (&OldFormSet
->FormListHead
);
3596 while (!IsNull (&OldFormSet
->FormListHead
, FormLink
)) {
3597 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3598 FormLink
= GetNextNode (&OldFormSet
->FormListHead
, FormLink
);
3600 Link
= GetFirstNode (&Form
->StatementListHead
);
3601 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3602 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3603 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3605 if (Question
->QuestionId
!= Statement
->QuestionId
) {
3609 CopyMem (&Statement
->HiiValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3616 Get old question value from the saved formset, all these questions not have
3619 @param FormSet FormSet data structure which is used now.
3620 @param OldFormSet FormSet data structure saved in the list.
3624 CopyOldValueForNoStorageQst (
3625 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
3626 IN FORM_BROWSER_FORMSET
*OldFormSet
3629 LIST_ENTRY
*FormLink
;
3631 FORM_BROWSER_STATEMENT
*Question
;
3632 FORM_BROWSER_FORM
*Form
;
3634 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3635 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3636 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3637 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3639 Link
= GetFirstNode (&Form
->StatementListHead
);
3640 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3641 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3642 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3644 if (Question
->Storage
== NULL
) {
3645 GetOldQuestionValue (Question
, OldFormSet
);
3652 Get current setting of Questions.
3654 @param FormSet FormSet data structure.
3656 @retval EFI_SUCCESS The function completed successfully.
3660 InitializeCurrentSetting (
3661 IN OUT FORM_BROWSER_FORMSET
*FormSet
3666 FORMSET_STORAGE
*Storage
;
3667 FORMSET_STORAGE
*StorageSrc
;
3668 FORMSET_STORAGE
*OldStorage
;
3669 FORM_BROWSER_FORM
*Form
;
3670 FORM_BROWSER_FORM
*Form2
;
3674 // Extract default from IFR binary for no storage questions.
3676 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
3679 // Request current settings from Configuration Driver
3681 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3682 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3683 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3686 if (gOldFormSet
!= NULL
) {
3688 // Try to find the Storage in backup formset gOldFormSet
3690 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3691 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3692 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3694 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3695 OldStorage
= StorageSrc
;
3699 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3703 if (OldStorage
== NULL
) {
3705 // Storage is not found in backup formset, request it from ConfigDriver
3707 Status
= LoadStorage (FormSet
, Storage
);
3709 if (EFI_ERROR (Status
)) {
3711 // If get last time changed value failed, extract default from IFR binary
3713 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3715 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3716 // in current situation.
3718 UpdateNvInfoInForm (FormSet
, FALSE
);
3722 // Now Edit Buffer is filled with default values(lower priority) or current
3723 // settings(higher priority), sychronize it to shadow Buffer
3725 SynchronizeStorage (Storage
, TRUE
);
3728 // Storage found in backup formset, use it
3730 Status
= CopyStorage (Storage
, OldStorage
);
3733 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3737 // If has old formset, get the old nv update status.
3739 if (gOldFormSet
!= NULL
) {
3740 Link
= GetFirstNode (&FormSet
->FormListHead
);
3741 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3742 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3744 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3745 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3746 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3748 if (Form
->FormId
== Form2
->FormId
) {
3749 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3753 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3755 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3764 Fetch the Ifr binary data of a FormSet.
3766 @param Handle PackageList Handle
3767 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3768 specified (NULL or zero GUID), take the first
3769 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3770 found in package list.
3771 On output, GUID of the formset found(if not NULL).
3772 @param BinaryLength The length of the FormSet IFR binary.
3773 @param BinaryData The buffer designed to receive the FormSet.
3775 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3776 BufferLength was updated.
3777 @retval EFI_INVALID_PARAMETER The handle is unknown.
3778 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3779 be found with the requested FormId.
3784 IN EFI_HII_HANDLE Handle
,
3785 IN OUT EFI_GUID
*FormSetGuid
,
3786 OUT UINTN
*BinaryLength
,
3787 OUT UINT8
**BinaryData
3791 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3797 UINT32 PackageListLength
;
3798 EFI_HII_PACKAGE_HEADER PackageHeader
;
3800 UINT8 NumberOfClassGuid
;
3801 BOOLEAN ClassGuidMatch
;
3802 EFI_GUID
*ClassGuid
;
3803 EFI_GUID
*ComparingGuid
;
3807 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3810 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3812 if (FormSetGuid
== NULL
) {
3813 ComparingGuid
= &gZeroGuid
;
3815 ComparingGuid
= FormSetGuid
;
3819 // Get HII PackageList
3822 HiiPackageList
= NULL
;
3823 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3824 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3825 HiiPackageList
= AllocatePool (BufferSize
);
3826 ASSERT (HiiPackageList
!= NULL
);
3828 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3830 if (EFI_ERROR (Status
)) {
3833 ASSERT (HiiPackageList
!= NULL
);
3836 // Get Form package from this HII package List
3838 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3840 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3842 ClassGuidMatch
= FALSE
;
3843 while (Offset
< PackageListLength
) {
3844 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3845 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3847 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3849 // Search FormSet in this Form Package
3851 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3852 while (Offset2
< PackageHeader
.Length
) {
3853 OpCodeData
= Package
+ Offset2
;
3855 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3857 // Try to compare against formset GUID
3859 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3860 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3864 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3866 // Try to compare against formset class GUID
3868 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3869 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3870 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3871 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3872 ClassGuidMatch
= TRUE
;
3876 if (ClassGuidMatch
) {
3879 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3880 ClassGuidMatch
= TRUE
;
3885 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3888 if (Offset2
< PackageHeader
.Length
) {
3890 // Target formset found
3896 Offset
+= PackageHeader
.Length
;
3899 if (Offset
>= PackageListLength
) {
3901 // Form package not found in this Package List
3903 FreePool (HiiPackageList
);
3904 return EFI_NOT_FOUND
;
3907 if (FormSetGuid
!= NULL
) {
3909 // Return the FormSet GUID
3911 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3915 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3916 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3917 // of the Form Package.
3919 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3920 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3922 FreePool (HiiPackageList
);
3924 if (*BinaryData
== NULL
) {
3925 return EFI_OUT_OF_RESOURCES
;
3933 Initialize the internal data structure of a FormSet.
3935 @param Handle PackageList Handle
3936 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3937 specified (NULL or zero GUID), take the first
3938 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3939 found in package list.
3940 On output, GUID of the formset found(if not NULL).
3941 @param FormSet FormSet data structure.
3942 @param UpdateGlobalVar Whether need to update the global variable.
3944 @retval EFI_SUCCESS The function completed successfully.
3945 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3950 IN EFI_HII_HANDLE Handle
,
3951 IN OUT EFI_GUID
*FormSetGuid
,
3952 OUT FORM_BROWSER_FORMSET
*FormSet
,
3953 IN BOOLEAN UpdateGlobalVar
3957 EFI_HANDLE DriverHandle
;
3960 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3961 if (EFI_ERROR (Status
)) {
3965 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3966 FormSet
->HiiHandle
= Handle
;
3967 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3970 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3972 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3973 if (EFI_ERROR (Status
)) {
3976 FormSet
->DriverHandle
= DriverHandle
;
3977 Status
= gBS
->HandleProtocol (
3979 &gEfiHiiConfigAccessProtocolGuid
,
3980 (VOID
**) &FormSet
->ConfigAccess
3982 if (EFI_ERROR (Status
)) {
3984 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3985 // list, then there will be no configuration action required
3987 FormSet
->ConfigAccess
= NULL
;
3991 // Parse the IFR binary OpCodes
3993 Status
= ParseOpCodes (FormSet
);
3994 if (EFI_ERROR (Status
)) {
3999 // If not need to update the global variable, just return.
4001 if (!UpdateGlobalVar
) {
4006 // Set VFR type by FormSet SubClass field
4008 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
4009 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
4010 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
4014 // Set VFR type by FormSet class guid
4016 for (Index
= 0; Index
< 3; Index
++) {
4017 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
4018 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
4023 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
4024 gFrontPageHandle
= FormSet
->HiiHandle
;
4025 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
4029 // Match GUID to find out the function key setting. If match fail, use the default setting.
4031 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
4032 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
4034 // Update the function key setting.
4036 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
4045 Save globals used by previous call to SendForm(). SendForm() may be called from
4046 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4047 So, save globals of previous call to SendForm() and restore them upon exit.
4051 SaveBrowserContext (
4055 BROWSER_CONTEXT
*Context
;
4057 gBrowserContextCount
++;
4058 if (gBrowserContextCount
== 1) {
4060 // This is not reentry of SendForm(), no context to save
4065 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4066 ASSERT (Context
!= NULL
);
4068 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4071 // Save FormBrowser context
4073 Context
->BannerData
= gBannerData
;
4074 Context
->ClassOfVfr
= gClassOfVfr
;
4075 Context
->FunctionKeySetting
= gFunctionKeySetting
;
4076 Context
->ResetRequired
= gResetRequired
;
4077 Context
->Direction
= gDirection
;
4078 Context
->EnterString
= gEnterString
;
4079 Context
->EnterCommitString
= gEnterCommitString
;
4080 Context
->EnterEscapeString
= gEnterEscapeString
;
4081 Context
->EscapeString
= gEscapeString
;
4082 Context
->MoveHighlight
= gMoveHighlight
;
4083 Context
->MakeSelection
= gMakeSelection
;
4084 Context
->DecNumericInput
= gDecNumericInput
;
4085 Context
->HexNumericInput
= gHexNumericInput
;
4086 Context
->ToggleCheckBox
= gToggleCheckBox
;
4087 Context
->PromptForData
= gPromptForData
;
4088 Context
->PromptForPassword
= gPromptForPassword
;
4089 Context
->PromptForNewPassword
= gPromptForNewPassword
;
4090 Context
->ConfirmPassword
= gConfirmPassword
;
4091 Context
->ConfirmError
= gConfirmError
;
4092 Context
->PassowordInvalid
= gPassowordInvalid
;
4093 Context
->PressEnter
= gPressEnter
;
4094 Context
->EmptyString
= gEmptyString
;
4095 Context
->AreYouSure
= gAreYouSure
;
4096 Context
->YesResponse
= gYesResponse
;
4097 Context
->NoResponse
= gNoResponse
;
4098 Context
->MiniString
= gMiniString
;
4099 Context
->PlusString
= gPlusString
;
4100 Context
->MinusString
= gMinusString
;
4101 Context
->AdjustNumber
= gAdjustNumber
;
4102 Context
->SaveChanges
= gSaveChanges
;
4103 Context
->OptionMismatch
= gOptionMismatch
;
4104 Context
->FormSuppress
= gFormSuppress
;
4105 Context
->PromptBlockWidth
= gPromptBlockWidth
;
4106 Context
->OptionBlockWidth
= gOptionBlockWidth
;
4107 Context
->HelpBlockWidth
= gHelpBlockWidth
;
4108 Context
->OldFormSet
= gOldFormSet
;
4109 Context
->MenuRefreshHead
= gMenuRefreshHead
;
4111 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
4112 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
4115 // Insert to FormBrowser context list
4117 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4122 Restore globals used by previous call to SendForm().
4126 RestoreBrowserContext (
4131 BROWSER_CONTEXT
*Context
;
4133 ASSERT (gBrowserContextCount
!= 0);
4134 gBrowserContextCount
--;
4135 if (gBrowserContextCount
== 0) {
4137 // This is not reentry of SendForm(), no context to restore
4142 ASSERT (!IsListEmpty (&gBrowserContextList
));
4144 Link
= GetFirstNode (&gBrowserContextList
);
4145 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4148 // Restore FormBrowser context
4150 gBannerData
= Context
->BannerData
;
4151 gClassOfVfr
= Context
->ClassOfVfr
;
4152 gFunctionKeySetting
= Context
->FunctionKeySetting
;
4153 gResetRequired
= Context
->ResetRequired
;
4154 gDirection
= Context
->Direction
;
4155 gEnterString
= Context
->EnterString
;
4156 gEnterCommitString
= Context
->EnterCommitString
;
4157 gEnterEscapeString
= Context
->EnterEscapeString
;
4158 gEscapeString
= Context
->EscapeString
;
4159 gMoveHighlight
= Context
->MoveHighlight
;
4160 gMakeSelection
= Context
->MakeSelection
;
4161 gDecNumericInput
= Context
->DecNumericInput
;
4162 gHexNumericInput
= Context
->HexNumericInput
;
4163 gToggleCheckBox
= Context
->ToggleCheckBox
;
4164 gPromptForData
= Context
->PromptForData
;
4165 gPromptForPassword
= Context
->PromptForPassword
;
4166 gPromptForNewPassword
= Context
->PromptForNewPassword
;
4167 gConfirmPassword
= Context
->ConfirmPassword
;
4168 gConfirmError
= Context
->ConfirmError
;
4169 gPassowordInvalid
= Context
->PassowordInvalid
;
4170 gPressEnter
= Context
->PressEnter
;
4171 gEmptyString
= Context
->EmptyString
;
4172 gAreYouSure
= Context
->AreYouSure
;
4173 gYesResponse
= Context
->YesResponse
;
4174 gNoResponse
= Context
->NoResponse
;
4175 gMiniString
= Context
->MiniString
;
4176 gPlusString
= Context
->PlusString
;
4177 gMinusString
= Context
->MinusString
;
4178 gAdjustNumber
= Context
->AdjustNumber
;
4179 gSaveChanges
= Context
->SaveChanges
;
4180 gOptionMismatch
= Context
->OptionMismatch
;
4181 gFormSuppress
= Context
->FormSuppress
;
4182 gPromptBlockWidth
= Context
->PromptBlockWidth
;
4183 gOptionBlockWidth
= Context
->OptionBlockWidth
;
4184 gHelpBlockWidth
= Context
->HelpBlockWidth
;
4185 gOldFormSet
= Context
->OldFormSet
;
4186 gMenuRefreshHead
= Context
->MenuRefreshHead
;
4188 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
4189 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
4192 // Remove from FormBrowser context list
4194 RemoveEntryList (&Context
->Link
);
4195 gBS
->FreePool (Context
);
4199 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4201 @param Handle The Hii Handle.
4203 @return the found FormSet context. If no found, NULL will return.
4206 FORM_BROWSER_FORMSET
*
4207 GetFormSetFromHiiHandle (
4208 EFI_HII_HANDLE Handle
4212 FORM_BROWSER_FORMSET
*FormSet
;
4214 Link
= GetFirstNode (&gBrowserFormSetList
);
4215 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4216 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4217 if (FormSet
->HiiHandle
== Handle
) {
4220 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4227 Check whether the input HII handle is the FormSet that is being used.
4229 @param Handle The Hii Handle.
4231 @retval TRUE HII handle is being used.
4232 @retval FALSE HII handle is not being used.
4236 IsHiiHandleInBrowserContext (
4237 EFI_HII_HANDLE Handle
4241 BROWSER_CONTEXT
*Context
;
4244 // HiiHandle is Current FormSet.
4246 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
4251 // Check whether HiiHandle is in BrowserContext.
4253 Link
= GetFirstNode (&gBrowserContextList
);
4254 while (!IsNull (&gBrowserContextList
, Link
)) {
4255 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4256 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
4258 // HiiHandle is in BrowserContext
4262 Link
= GetNextNode (&gBrowserContextList
, Link
);
4269 Find the registered HotKey based on KeyData.
4271 @param[in] KeyData A pointer to a buffer that describes the keystroke
4272 information for the hot key.
4274 @return The registered HotKey context. If no found, NULL will return.
4277 GetHotKeyFromRegisterList (
4278 IN EFI_INPUT_KEY
*KeyData
4282 BROWSER_HOT_KEY
*HotKey
;
4284 Link
= GetFirstNode (&gBrowserHotKeyList
);
4285 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4286 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4287 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4290 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4297 Configure what scope the hot key will impact.
4298 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4299 If no scope is set, the default scope will be FormSet level.
4300 After all registered hot keys are removed, previous Scope can reset to another level.
4302 @param[in] Scope Scope level to be set.
4304 @retval EFI_SUCCESS Scope is set correctly.
4305 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4306 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4312 IN BROWSER_SETTING_SCOPE Scope
4315 if (Scope
>= MaxLevel
) {
4316 return EFI_INVALID_PARAMETER
;
4320 // When no hot key registered in system or on the first setting,
4321 // Scope can be set.
4323 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4324 gBrowserSettingScope
= Scope
;
4325 mBrowserScopeFirstSet
= FALSE
;
4326 } else if (Scope
!= gBrowserSettingScope
) {
4327 return EFI_UNSUPPORTED
;
4334 Register the hot key with its browser action, or unregistered the hot key.
4335 Only support hot key that is not printable character (control key, function key, etc.).
4336 If the action value is zero, the hot key will be unregistered if it has been registered.
4337 If the same hot key has been registered, the new action and help string will override the previous ones.
4339 @param[in] KeyData A pointer to a buffer that describes the keystroke
4340 information for the hot key. Its type is EFI_INPUT_KEY to
4341 be supported by all ConsoleIn devices.
4342 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4343 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4344 @param[in] HelpString Help string that describes the hot key information.
4345 Its value may be NULL for the unregistered hot key.
4347 @retval EFI_SUCCESS Hot key is registered or unregistered.
4348 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4349 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4350 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4355 IN EFI_INPUT_KEY
*KeyData
,
4357 IN UINT16 DefaultId
,
4358 IN EFI_STRING HelpString OPTIONAL
4361 BROWSER_HOT_KEY
*HotKey
;
4364 // Check input parameters.
4366 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4367 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4368 return EFI_INVALID_PARAMETER
;
4372 // Check whether the input KeyData is in BrowserHotKeyList.
4374 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4377 // Unregister HotKey
4379 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4380 if (HotKey
!= NULL
) {
4382 // The registered HotKey is found.
4383 // Remove it from List, and free its resource.
4385 RemoveEntryList (&HotKey
->Link
);
4386 FreePool (HotKey
->KeyData
);
4387 FreePool (HotKey
->HelpString
);
4391 // The registered HotKey is not found.
4393 return EFI_NOT_FOUND
;
4398 // Register HotKey into List.
4400 if (HotKey
== NULL
) {
4402 // Create new Key, and add it into List.
4404 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4405 ASSERT (HotKey
!= NULL
);
4406 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4407 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4408 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4412 // Fill HotKey information.
4414 HotKey
->Action
= Action
;
4415 HotKey
->DefaultId
= DefaultId
;
4416 if (HotKey
->HelpString
!= NULL
) {
4417 FreePool (HotKey
->HelpString
);
4419 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4425 Register Exit handler function.
4426 When more than one handler function is registered, the latter one will override the previous one.
4427 When NULL handler is specified, the previous Exit handler will be unregistered.
4429 @param[in] Handler Pointer to handler function.
4434 RegiserExitHandler (
4435 IN EXIT_HANDLER Handler
4438 ExitHandlerFunction
= Handler
;
4443 Create reminder to let user to choose save or discard the changed browser data.
4444 Caller can use it to actively check the changed browser data.
4446 @retval BROWSER_NO_CHANGES No browser data is changed.
4447 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4448 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4458 FORM_BROWSER_FORMSET
*FormSet
;
4459 BOOLEAN IsDataChanged
;
4460 UINT32 DataSavedAction
;
4461 CHAR16
*YesResponse
;
4463 CHAR16
*EmptyString
;
4464 CHAR16
*ChangeReminderString
;
4465 CHAR16
*SaveConfirmString
;
4468 DataSavedAction
= BROWSER_NO_CHANGES
;
4469 IsDataChanged
= FALSE
;
4470 Link
= GetFirstNode (&gBrowserFormSetList
);
4471 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4472 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4473 if (IsNvUpdateRequired (FormSet
)) {
4474 IsDataChanged
= TRUE
;
4477 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4481 // No data is changed. No save is required.
4483 if (!IsDataChanged
) {
4484 return DataSavedAction
;
4488 // If data is changed, prompt user
4490 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4492 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4493 ASSERT (YesResponse
!= NULL
);
4494 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4495 ASSERT (NoResponse
!= NULL
);
4496 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4497 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4498 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4501 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4503 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4504 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4508 // If the user hits the YesResponse key
4510 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4511 SubmitForm (NULL
, NULL
, SystemLevel
);
4512 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4514 DiscardForm (NULL
, NULL
, SystemLevel
);
4515 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4516 gResetRequired
= FALSE
;
4519 FreePool (YesResponse
);
4520 FreePool (NoResponse
);
4521 FreePool (EmptyString
);
4522 FreePool (SaveConfirmString
);
4523 FreePool (ChangeReminderString
);
4525 return DataSavedAction
;