2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2011, 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 // Try to find pre FormSet in the maintain backup list.
328 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
331 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
332 ASSERT (FormSet
!= NULL
);
335 // Initialize internal data structures of FormSet
337 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
338 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
339 DestroyFormSet (FormSet
);
342 Selection
->FormSet
= FormSet
;
345 // Display this formset
347 gCurrentSelection
= Selection
;
349 Status
= SetupBrowser (Selection
);
351 gCurrentSelection
= NULL
;
353 if (EFI_ERROR (Status
)) {
357 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
359 if (gOldFormSet
!= NULL
) {
361 // If no data is changed, don't need to save current FormSet into the maintain list.
363 if (!IsNvUpdateRequired (gOldFormSet
)) {
364 RemoveEntryList (&gOldFormSet
->Link
);
365 DestroyFormSet (gOldFormSet
);
370 FreePool (Selection
);
373 if (ActionRequest
!= NULL
) {
374 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
375 if (gResetRequired
) {
376 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
380 FreeBrowserStrings ();
382 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
383 gST
->ConOut
->ClearScreen (gST
->ConOut
);
387 // Restore globals used by SendForm()
389 RestoreBrowserContext ();
396 This function is called by a callback handler to retrieve uncommitted state
397 data from the browser.
399 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
401 @param ResultsDataSize A pointer to the size of the buffer associated
403 @param ResultsData A string returned from an IFR browser or
404 equivalent. The results string will have no
405 routing information in them.
406 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
407 (if RetrieveData = TRUE) data from the uncommitted
408 browser state information or set (if RetrieveData
409 = FALSE) data in the uncommitted browser state
411 @param VariableGuid An optional field to indicate the target variable
413 @param VariableName An optional field to indicate the target
414 human-readable variable name.
416 @retval EFI_SUCCESS The results have been distributed or are awaiting
418 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
419 contain the results data.
425 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
426 IN OUT UINTN
*ResultsDataSize
,
427 IN OUT EFI_STRING ResultsData
,
428 IN BOOLEAN RetrieveData
,
429 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
430 IN CONST CHAR16
*VariableName OPTIONAL
435 FORMSET_STORAGE
*Storage
;
436 FORM_BROWSER_FORMSET
*FormSet
;
443 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
444 return EFI_INVALID_PARAMETER
;
447 if (gCurrentSelection
== NULL
) {
448 return EFI_NOT_READY
;
453 FormSet
= gCurrentSelection
->FormSet
;
456 // Find target storage
458 Link
= GetFirstNode (&FormSet
->StorageListHead
);
459 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
460 return EFI_UNSUPPORTED
;
463 if (VariableGuid
!= NULL
) {
465 // Try to find target storage
468 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
469 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
470 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
472 if (CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
473 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
474 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
476 // Buffer storage require both GUID and Name
478 if (VariableName
== NULL
) {
479 return EFI_NOT_FOUND
;
482 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
492 return EFI_NOT_FOUND
;
496 // GUID/Name is not specified, take the first storage in FormSet
498 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
503 // Skip if there is no RequestElement
505 if (Storage
->ElementCount
== 0) {
510 // Generate <ConfigResp>
512 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
513 if (EFI_ERROR (Status
)) {
518 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
520 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
522 BufferSize
= StrSize (StrPtr
);
523 if (*ResultsDataSize
< BufferSize
) {
524 *ResultsDataSize
= BufferSize
;
526 FreePool (ConfigResp
);
527 return EFI_BUFFER_TOO_SMALL
;
530 *ResultsDataSize
= BufferSize
;
531 CopyMem (ResultsData
, StrPtr
, BufferSize
);
533 FreePool (ConfigResp
);
536 // Prepare <ConfigResp>
538 TmpSize
= StrLen (ResultsData
);
539 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
540 ConfigResp
= AllocateZeroPool (BufferSize
);
541 ASSERT (ConfigResp
!= NULL
);
543 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
544 StrCat (ConfigResp
, L
"&");
545 StrCat (ConfigResp
, ResultsData
);
548 // Update Browser uncommited data
550 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
551 if (EFI_ERROR (Status
)) {
560 Notify function will remove the formset in the maintain list
561 once this formset is removed.
563 Functions which are registered to receive notification of
564 database events have this prototype. The actual event is encoded
565 in NotifyType. The following table describes how PackageType,
566 PackageGuid, Handle, and Package are used for each of the
569 @param PackageType Package type of the notification.
571 @param PackageGuid If PackageType is
572 EFI_HII_PACKAGE_TYPE_GUID, then this is
573 the pointer to the GUID from the Guid
574 field of EFI_HII_PACKAGE_GUID_HEADER.
575 Otherwise, it must be NULL.
577 @param Package Points to the package referred to by the
578 notification Handle The handle of the package
579 list which contains the specified package.
581 @param Handle The HII handle.
583 @param NotifyType The type of change concerning the
585 EFI_HII_DATABASE_NOTIFY_TYPE.
590 FormsetRemoveNotify (
591 IN UINT8 PackageType
,
592 IN CONST EFI_GUID
*PackageGuid
,
593 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
594 IN EFI_HII_HANDLE Handle
,
595 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
598 FORM_BROWSER_FORMSET
*FormSet
;
601 // Ignore the update for current using formset, which is handled by another notify function.
603 if (IsHiiHandleInBrowserContext (Handle
)) {
608 // Remove the backup FormSet data when the Form Package is removed.
610 FormSet
= GetFormSetFromHiiHandle (Handle
);
611 if (FormSet
!= NULL
) {
612 RemoveEntryList (&FormSet
->Link
);
613 DestroyFormSet (FormSet
);
620 Initialize Setup Browser driver.
622 @param ImageHandle The image handle.
623 @param SystemTable The system table.
625 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
626 @return Other value if failed to initialize the Setup Browser module.
632 IN EFI_HANDLE ImageHandle
,
633 IN EFI_SYSTEM_TABLE
*SystemTable
637 EFI_HANDLE NotifyHandle
;
638 EFI_INPUT_KEY DefaultHotKey
;
639 EFI_STRING HelpString
;
642 // Locate required Hii relative protocols
644 Status
= gBS
->LocateProtocol (
645 &gEfiHiiDatabaseProtocolGuid
,
647 (VOID
**) &mHiiDatabase
649 ASSERT_EFI_ERROR (Status
);
651 Status
= gBS
->LocateProtocol (
652 &gEfiHiiStringProtocolGuid
,
654 (VOID
**) &mHiiString
656 ASSERT_EFI_ERROR (Status
);
658 Status
= gBS
->LocateProtocol (
659 &gEfiHiiConfigRoutingProtocolGuid
,
661 (VOID
**) &mHiiConfigRouting
663 ASSERT_EFI_ERROR (Status
);
666 // Publish our HII data
668 gHiiHandle
= HiiAddPackages (
674 ASSERT (gHiiHandle
!= NULL
);
677 // Initialize Driver private data
679 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
680 ASSERT (gBannerData
!= NULL
);
683 // Initialize generic help strings.
685 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
686 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
687 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
690 // Install FormBrowser2 protocol
692 mPrivateData
.Handle
= NULL
;
693 Status
= gBS
->InstallProtocolInterface (
694 &mPrivateData
.Handle
,
695 &gEfiFormBrowser2ProtocolGuid
,
696 EFI_NATIVE_INTERFACE
,
697 &mPrivateData
.FormBrowser2
699 ASSERT_EFI_ERROR (Status
);
702 // Install default HotKey F10 for Save
704 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
705 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
706 DefaultHotKey
.ScanCode
= SCAN_F10
;
707 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
708 FreePool (HelpString
);
710 // Install default HotKey F9 for Reset To Defaults
712 DefaultHotKey
.ScanCode
= SCAN_F9
;
713 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
714 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
715 FreePool (HelpString
);
718 // Install FormBrowserEx protocol
720 mPrivateData
.Handle
= NULL
;
721 Status
= gBS
->InstallProtocolInterface (
722 &mPrivateData
.Handle
,
723 &gEfiFormBrowserExProtocolGuid
,
724 EFI_NATIVE_INTERFACE
,
725 &mPrivateData
.FormBrowserEx
727 ASSERT_EFI_ERROR (Status
);
730 // Register notify for Form package remove
732 Status
= mHiiDatabase
->RegisterPackageNotify (
734 EFI_HII_PACKAGE_FORMS
,
737 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
740 ASSERT_EFI_ERROR (Status
);
747 Create a new string in HII Package List.
749 @param String The String to be added
750 @param HiiHandle The package list in the HII database to insert the
753 @return The output string.
759 IN EFI_HII_HANDLE HiiHandle
762 EFI_STRING_ID StringId
;
764 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
765 ASSERT (StringId
!= 0);
772 Delete a string from HII Package List.
774 @param StringId Id of the string in HII database.
775 @param HiiHandle The HII package list handle.
777 @retval EFI_SUCCESS The string was deleted successfully.
782 IN EFI_STRING_ID StringId
,
783 IN EFI_HII_HANDLE HiiHandle
788 NullChar
= CHAR_NULL
;
789 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
795 Get the string based on the StringId and HII Package List Handle.
797 @param Token The String's ID.
798 @param HiiHandle The package list in the HII database to search for
799 the specified string.
801 @return The output string.
806 IN EFI_STRING_ID Token
,
807 IN EFI_HII_HANDLE HiiHandle
812 if (HiiHandle
== NULL
) {
816 String
= HiiGetString (HiiHandle
, Token
, NULL
);
817 if (String
== NULL
) {
818 String
= AllocateCopyPool (sizeof (mUnknownString
), mUnknownString
);
819 ASSERT (String
!= NULL
);
821 return (CHAR16
*) String
;
826 Allocate new memory and then copy the Unicode string Source to Destination.
828 @param Dest Location to copy string
829 @param Src String to copy
834 IN OUT CHAR16
**Dest
,
841 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
842 ASSERT (*Dest
!= NULL
);
847 Allocate new memory and concatinate Source on the end of Destination.
849 @param Dest String to added to the end of.
850 @param Src String to concatinate.
855 IN OUT CHAR16
**Dest
,
863 NewStringCpy (Dest
, Src
);
867 TmpSize
= StrSize (*Dest
);
868 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
869 ASSERT (NewString
!= NULL
);
871 StrCpy (NewString
, *Dest
);
872 StrCat (NewString
, Src
);
880 Synchronize or restore Storage's Edit copy and Shadow copy.
882 @param Storage The Storage to be synchronized.
883 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
885 if TRUE, copy the editbuffer to the buffer.
886 if FALSE, copy the buffer to the editbuffer.
891 IN FORMSET_STORAGE
*Storage
,
892 IN BOOLEAN SyncOrRestore
896 NAME_VALUE_NODE
*Node
;
898 switch (Storage
->Type
) {
899 case EFI_HII_VARSTORE_BUFFER
:
900 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
902 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
904 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
908 case EFI_HII_VARSTORE_NAME_VALUE
:
909 Link
= GetFirstNode (&Storage
->NameValueListHead
);
910 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
911 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
914 NewStringCpy (&Node
->Value
, Node
->EditValue
);
916 NewStringCpy (&Node
->EditValue
, Node
->Value
);
919 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
923 case EFI_HII_VARSTORE_EFI_VARIABLE
:
931 Get Value for given Name from a NameValue Storage.
933 @param Storage The NameValue Storage.
934 @param Name The Name.
935 @param Value The retured Value.
937 @retval EFI_SUCCESS Value found for given Name.
938 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
943 IN FORMSET_STORAGE
*Storage
,
945 IN OUT CHAR16
**Value
949 NAME_VALUE_NODE
*Node
;
953 Link
= GetFirstNode (&Storage
->NameValueListHead
);
954 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
955 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
957 if (StrCmp (Name
, Node
->Name
) == 0) {
958 NewStringCpy (Value
, Node
->EditValue
);
962 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
965 return EFI_NOT_FOUND
;
970 Set Value of given Name in a NameValue Storage.
972 @param Storage The NameValue Storage.
973 @param Name The Name.
974 @param Value The Value to set.
975 @param Edit Whether update editValue or Value.
977 @retval EFI_SUCCESS Value found for given Name.
978 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
983 IN FORMSET_STORAGE
*Storage
,
990 NAME_VALUE_NODE
*Node
;
993 Link
= GetFirstNode (&Storage
->NameValueListHead
);
994 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
995 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
997 if (StrCmp (Name
, Node
->Name
) == 0) {
999 Buffer
= Node
->EditValue
;
1001 Buffer
= Node
->Value
;
1003 if (Buffer
!= NULL
) {
1006 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1007 ASSERT (Buffer
!= NULL
);
1009 Node
->EditValue
= Buffer
;
1011 Node
->Value
= Buffer
;
1016 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1019 return EFI_NOT_FOUND
;
1024 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1026 @param Buffer The Storage to be conveted.
1027 @param ConfigResp The returned <ConfigResp>.
1028 @param SingleForm Whether update data for single form or formset level.
1030 @retval EFI_SUCCESS Convert success.
1031 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1035 StorageToConfigResp (
1037 IN CHAR16
**ConfigResp
,
1038 IN BOOLEAN SingleForm
1042 EFI_STRING Progress
;
1044 NAME_VALUE_NODE
*Node
;
1045 CHAR16
*ConfigRequest
;
1046 FORMSET_STORAGE
*Storage
;
1047 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
1049 Status
= EFI_SUCCESS
;
1051 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
1052 Storage
= ConfigInfo
->Storage
;
1053 ConfigRequest
= ConfigInfo
->ConfigRequest
;
1055 Storage
= (FORMSET_STORAGE
*) Buffer
;
1056 ConfigRequest
= Storage
->ConfigRequest
;
1059 switch (Storage
->Type
) {
1060 case EFI_HII_VARSTORE_BUFFER
:
1061 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1062 Status
= mHiiConfigRouting
->BlockToConfig (
1065 Storage
->EditBuffer
,
1072 case EFI_HII_VARSTORE_NAME_VALUE
:
1074 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1076 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1077 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1078 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1080 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1081 NewStringCat (ConfigResp
, L
"&");
1082 NewStringCat (ConfigResp
, Node
->Name
);
1083 NewStringCat (ConfigResp
, L
"=");
1084 NewStringCat (ConfigResp
, Node
->EditValue
);
1086 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1090 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1092 Status
= EFI_INVALID_PARAMETER
;
1101 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1103 @param Storage The Storage to receive the settings.
1104 @param ConfigResp The <ConfigResp> to be converted.
1106 @retval EFI_SUCCESS Convert success.
1107 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1111 ConfigRespToStorage (
1112 IN FORMSET_STORAGE
*Storage
,
1113 IN CHAR16
*ConfigResp
1117 EFI_STRING Progress
;
1123 Status
= EFI_SUCCESS
;
1125 switch (Storage
->Type
) {
1126 case EFI_HII_VARSTORE_BUFFER
:
1127 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1128 BufferSize
= Storage
->Size
;
1129 Status
= mHiiConfigRouting
->ConfigToBlock (
1132 Storage
->EditBuffer
,
1138 case EFI_HII_VARSTORE_NAME_VALUE
:
1139 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1140 if (StrPtr
== NULL
) {
1143 StrPtr
= StrStr (ConfigResp
, L
"&");
1144 while (StrPtr
!= NULL
) {
1148 StrPtr
= StrPtr
+ 1;
1150 StrPtr
= StrStr (StrPtr
, L
"=");
1151 if (StrPtr
== NULL
) {
1159 StrPtr
= StrPtr
+ 1;
1161 StrPtr
= StrStr (StrPtr
, L
"&");
1162 if (StrPtr
!= NULL
) {
1165 SetValueByName (Storage
, Name
, Value
, TRUE
);
1169 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1171 Status
= EFI_INVALID_PARAMETER
;
1180 Get Question's current Value.
1182 @param FormSet FormSet data structure.
1183 @param Form Form data structure.
1184 @param Question Question to be initialized.
1185 @param Cached TRUE: get from Edit copy FALSE: get from original
1188 @retval EFI_SUCCESS The function completed successfully.
1193 IN FORM_BROWSER_FORMSET
*FormSet
,
1194 IN FORM_BROWSER_FORM
*Form
,
1195 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1205 FORMSET_STORAGE
*Storage
;
1206 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1207 CHAR16
*ConfigRequest
;
1215 BOOLEAN IsBufferStorage
;
1221 Status
= EFI_SUCCESS
;
1225 // Statement don't have storage, skip them
1227 if (Question
->QuestionId
== 0) {
1232 // Question value is provided by an Expression, evaluate it
1234 if (Question
->ValueExpression
!= NULL
) {
1235 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1236 if (!EFI_ERROR (Status
)) {
1237 CopyMem (&Question
->HiiValue
, &Question
->ValueExpression
->Result
, sizeof (EFI_HII_VALUE
));
1243 // Get question value by read expression.
1245 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1246 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1247 if (!EFI_ERROR (Status
) && (Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
)) {
1249 // Only update question value to the valid result.
1251 CopyMem (&Question
->HiiValue
, &Question
->ReadExpression
->Result
, sizeof (EFI_HII_VALUE
));
1257 // Question value is provided by RTC
1259 Storage
= Question
->Storage
;
1260 QuestionValue
= &Question
->HiiValue
.Value
;
1261 if (Storage
== NULL
) {
1263 // It's a Question without storage, or RTC date/time
1265 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1267 // Date and time define the same Flags bit
1269 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1270 case QF_DATE_STORAGE_TIME
:
1271 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1274 case QF_DATE_STORAGE_WAKEUP
:
1275 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1278 case QF_DATE_STORAGE_NORMAL
:
1281 // For date/time without storage
1286 if (EFI_ERROR (Status
)) {
1290 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1291 QuestionValue
->date
.Year
= EfiTime
.Year
;
1292 QuestionValue
->date
.Month
= EfiTime
.Month
;
1293 QuestionValue
->date
.Day
= EfiTime
.Day
;
1295 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1296 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1297 QuestionValue
->time
.Second
= EfiTime
.Second
;
1305 // Question value is provided by EFI variable
1307 StorageWidth
= Question
->StorageWidth
;
1308 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1309 if (Question
->BufferValue
!= NULL
) {
1310 Dst
= Question
->BufferValue
;
1312 Dst
= (UINT8
*) QuestionValue
;
1315 Status
= gRT
->GetVariable (
1316 Question
->VariableName
,
1323 // Always return success, even this EFI variable doesn't exist
1329 // Question Value is provided by Buffer Storage or NameValue Storage
1331 if (Question
->BufferValue
!= NULL
) {
1333 // This Question is password or orderedlist
1335 Dst
= Question
->BufferValue
;
1338 // Other type of Questions
1340 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1343 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1344 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1345 IsBufferStorage
= TRUE
;
1347 IsBufferStorage
= FALSE
;
1349 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1351 if (IsBufferStorage
) {
1353 // Copy from storage Edit buffer
1355 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1358 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
);
1359 if (EFI_ERROR (Status
)) {
1363 ASSERT (Value
!= NULL
);
1364 LengthStr
= StrLen (Value
);
1365 Status
= EFI_SUCCESS
;
1368 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1369 // Add string tail char L'\0' into Length
1371 Length
= StorageWidth
+ sizeof (CHAR16
);
1372 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1373 Status
= EFI_BUFFER_TOO_SMALL
;
1375 StringPtr
= (CHAR16
*) Dst
;
1376 ZeroMem (TemStr
, sizeof (TemStr
));
1377 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1378 StrnCpy (TemStr
, Value
+ Index
, 4);
1379 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1382 // Add tailing L'\0' character
1384 StringPtr
[Index
/4] = L
'\0';
1387 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1388 Status
= EFI_BUFFER_TOO_SMALL
;
1390 ZeroMem (TemStr
, sizeof (TemStr
));
1391 for (Index
= 0; Index
< LengthStr
; Index
++) {
1392 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1393 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1394 if ((Index
& 1) == 0) {
1395 Dst
[Index
/2] = DigitUint8
;
1397 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1406 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
1408 // Request current settings from Configuration Driver
1410 if (FormSet
->ConfigAccess
== NULL
) {
1411 return EFI_NOT_FOUND
;
1415 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1416 // <ConfigHdr> + "&" + <VariableName>
1418 if (IsBufferStorage
) {
1419 Length
= StrLen (Storage
->ConfigHdr
);
1420 Length
+= StrLen (Question
->BlockName
);
1422 Length
= StrLen (Storage
->ConfigHdr
);
1423 Length
+= StrLen (Question
->VariableName
) + 1;
1425 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1426 ASSERT (ConfigRequest
!= NULL
);
1428 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1429 if (IsBufferStorage
) {
1430 StrCat (ConfigRequest
, Question
->BlockName
);
1432 StrCat (ConfigRequest
, L
"&");
1433 StrCat (ConfigRequest
, Question
->VariableName
);
1436 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1437 FormSet
->ConfigAccess
,
1442 FreePool (ConfigRequest
);
1443 if (EFI_ERROR (Status
)) {
1448 // Skip <ConfigRequest>
1450 Value
= Result
+ Length
;
1451 if (IsBufferStorage
) {
1457 if (*Value
!= '=') {
1459 return EFI_NOT_FOUND
;
1462 // Skip '=', point to value
1467 // Suppress <AltResp> if any
1470 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1475 LengthStr
= StrLen (Value
);
1476 Status
= EFI_SUCCESS
;
1477 if (!IsBufferStorage
&& IsString
) {
1479 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1480 // Add string tail char L'\0' into Length
1482 Length
= StorageWidth
+ sizeof (CHAR16
);
1483 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1484 Status
= EFI_BUFFER_TOO_SMALL
;
1486 StringPtr
= (CHAR16
*) Dst
;
1487 ZeroMem (TemStr
, sizeof (TemStr
));
1488 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1489 StrnCpy (TemStr
, Value
+ Index
, 4);
1490 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1493 // Add tailing L'\0' character
1495 StringPtr
[Index
/4] = L
'\0';
1498 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1499 Status
= EFI_BUFFER_TOO_SMALL
;
1501 ZeroMem (TemStr
, sizeof (TemStr
));
1502 for (Index
= 0; Index
< LengthStr
; Index
++) {
1503 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1504 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1505 if ((Index
& 1) == 0) {
1506 Dst
[Index
/2] = DigitUint8
;
1508 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1515 if (EFI_ERROR (Status
)) {
1518 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1520 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1521 if (TemBuffer
== NULL
) {
1522 Status
= EFI_OUT_OF_RESOURCES
;
1525 Length
= Storage
->Size
;
1526 Status
= gRT
->GetVariable (
1533 if (EFI_ERROR (Status
)) {
1534 FreePool (TemBuffer
);
1538 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1540 FreePool (TemBuffer
);
1544 // Synchronize Edit Buffer
1546 if (IsBufferStorage
) {
1547 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1549 SetValueByName (Storage
, Question
->VariableName
, Value
, TRUE
);
1558 Save Question Value to edit copy(cached) or Storage(uncached).
1560 @param FormSet FormSet data structure.
1561 @param Form Form data structure.
1562 @param Question Pointer to the Question.
1563 @param Cached TRUE: set to Edit copy FALSE: set to original
1566 @retval EFI_SUCCESS The function completed successfully.
1571 IN FORM_BROWSER_FORMSET
*FormSet
,
1572 IN FORM_BROWSER_FORM
*Form
,
1573 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1584 FORMSET_STORAGE
*Storage
;
1585 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1590 BOOLEAN IsBufferStorage
;
1597 Status
= EFI_SUCCESS
;
1600 // Statement don't have storage, skip them
1602 if (Question
->QuestionId
== 0) {
1607 // If Question value is provided by an Expression, then it is read only
1609 if (Question
->ValueExpression
!= NULL
) {
1614 // Before set question value, evaluate its write expression.
1616 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1617 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1618 if (EFI_ERROR (Status
)) {
1624 // Question value is provided by RTC
1626 Storage
= Question
->Storage
;
1627 QuestionValue
= &Question
->HiiValue
.Value
;
1628 if (Storage
== NULL
) {
1630 // It's a Question without storage, or RTC date/time
1632 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1634 // Date and time define the same Flags bit
1636 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1637 case QF_DATE_STORAGE_TIME
:
1638 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1641 case QF_DATE_STORAGE_WAKEUP
:
1642 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1645 case QF_DATE_STORAGE_NORMAL
:
1648 // For date/time without storage
1653 if (EFI_ERROR (Status
)) {
1657 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1658 EfiTime
.Year
= QuestionValue
->date
.Year
;
1659 EfiTime
.Month
= QuestionValue
->date
.Month
;
1660 EfiTime
.Day
= QuestionValue
->date
.Day
;
1662 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1663 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1664 EfiTime
.Second
= QuestionValue
->time
.Second
;
1667 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1668 Status
= gRT
->SetTime (&EfiTime
);
1670 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1678 // Question value is provided by EFI variable
1680 StorageWidth
= Question
->StorageWidth
;
1681 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1682 if (Question
->BufferValue
!= NULL
) {
1683 Src
= Question
->BufferValue
;
1685 Src
= (UINT8
*) QuestionValue
;
1688 Status
= gRT
->SetVariable (
1689 Question
->VariableName
,
1691 Storage
->Attributes
,
1699 // Question Value is provided by Buffer Storage or NameValue Storage
1701 if (Question
->BufferValue
!= NULL
) {
1702 Src
= Question
->BufferValue
;
1704 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1707 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1708 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1709 IsBufferStorage
= TRUE
;
1711 IsBufferStorage
= FALSE
;
1713 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1714 if (IsBufferStorage
) {
1716 // Copy to storage edit buffer
1718 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1722 // Allocate enough string buffer.
1725 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1726 Value
= AllocateZeroPool (BufferLen
);
1727 ASSERT (Value
!= NULL
);
1729 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1731 TemName
= (CHAR16
*) Src
;
1733 for (; *TemName
!= L
'\0'; TemName
++) {
1734 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1737 BufferLen
= StorageWidth
* 2 + 1;
1738 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1739 ASSERT (Value
!= NULL
);
1741 // Convert Buffer to Hex String
1743 TemBuffer
= Src
+ StorageWidth
- 1;
1745 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1746 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1750 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, TRUE
);
1755 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
1757 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1758 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1760 if (IsBufferStorage
) {
1761 Length
= StrLen (Question
->BlockName
) + 7;
1763 Length
= StrLen (Question
->VariableName
) + 2;
1765 if (!IsBufferStorage
&& IsString
) {
1766 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1768 Length
+= (StorageWidth
* 2);
1770 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1771 ASSERT (ConfigResp
!= NULL
);
1773 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1774 if (IsBufferStorage
) {
1775 StrCat (ConfigResp
, Question
->BlockName
);
1776 StrCat (ConfigResp
, L
"&VALUE=");
1778 StrCat (ConfigResp
, L
"&");
1779 StrCat (ConfigResp
, Question
->VariableName
);
1780 StrCat (ConfigResp
, L
"=");
1783 Value
= ConfigResp
+ StrLen (ConfigResp
);
1785 if (!IsBufferStorage
&& IsString
) {
1787 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1789 TemName
= (CHAR16
*) Src
;
1791 for (; *TemName
!= L
'\0'; TemName
++) {
1792 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1796 // Convert Buffer to Hex String
1798 TemBuffer
= Src
+ StorageWidth
- 1;
1800 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1801 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1806 // Convert to lower char.
1808 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1809 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1810 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1815 // Submit Question Value to Configuration Driver
1817 if (FormSet
->ConfigAccess
!= NULL
) {
1818 Status
= FormSet
->ConfigAccess
->RouteConfig (
1819 FormSet
->ConfigAccess
,
1823 if (EFI_ERROR (Status
)) {
1824 FreePool (ConfigResp
);
1828 FreePool (ConfigResp
);
1830 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1832 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1833 if (TemBuffer
== NULL
) {
1834 Status
= EFI_OUT_OF_RESOURCES
;
1837 Length
= Storage
->Size
;
1838 Status
= gRT
->GetVariable (
1846 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1848 Status
= gRT
->SetVariable (
1851 Storage
->Attributes
,
1855 FreePool (TemBuffer
);
1856 if (EFI_ERROR (Status
)){
1861 // Sync storage, from editbuffer to buffer.
1863 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1871 Perform inconsistent check for a Form.
1873 @param FormSet FormSet data structure.
1874 @param Form Form data structure.
1875 @param Question The Question to be validated.
1876 @param Type Validation type: InConsistent or NoSubmit
1878 @retval EFI_SUCCESS Form validation pass.
1879 @retval other Form validation failed.
1884 IN FORM_BROWSER_FORMSET
*FormSet
,
1885 IN FORM_BROWSER_FORM
*Form
,
1886 IN FORM_BROWSER_STATEMENT
*Question
,
1892 LIST_ENTRY
*ListHead
;
1895 FORM_EXPRESSION
*Expression
;
1897 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1898 ListHead
= &Question
->InconsistentListHead
;
1899 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1900 ListHead
= &Question
->NoSubmitListHead
;
1902 return EFI_UNSUPPORTED
;
1905 Link
= GetFirstNode (ListHead
);
1906 while (!IsNull (ListHead
, Link
)) {
1907 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1910 // Evaluate the expression
1912 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1913 if (EFI_ERROR (Status
)) {
1917 if (Expression
->Result
.Value
.b
) {
1919 // Condition meet, show up error message
1921 if (Expression
->Error
!= 0) {
1922 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1924 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1925 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1929 return EFI_NOT_READY
;
1932 Link
= GetNextNode (ListHead
, Link
);
1940 Perform NoSubmit check for each Form in FormSet.
1942 @param FormSet FormSet data structure.
1943 @param CurrentForm Current input form data structure.
1945 @retval EFI_SUCCESS Form validation pass.
1946 @retval other Form validation failed.
1951 IN FORM_BROWSER_FORMSET
*FormSet
,
1952 IN FORM_BROWSER_FORM
*CurrentForm
1957 FORM_BROWSER_STATEMENT
*Question
;
1958 FORM_BROWSER_FORM
*Form
;
1959 LIST_ENTRY
*LinkForm
;
1961 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1962 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1963 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1964 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1966 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
1970 Link
= GetFirstNode (&Form
->StatementListHead
);
1971 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1972 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1974 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
1975 if (EFI_ERROR (Status
)) {
1979 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1987 Fill storage's edit copy with settings requested from Configuration Driver.
1989 @param FormSet FormSet data structure.
1990 @param ConfigInfo The config info related to this form.
1991 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
1992 editbuffer to buffer
1993 if TRUE, copy the editbuffer to the buffer.
1994 if FALSE, copy the buffer to the editbuffer.
1996 @retval EFI_SUCCESS The function completed successfully.
2000 SynchronizeStorageForForm (
2001 IN FORM_BROWSER_FORMSET
*FormSet
,
2002 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2003 IN BOOLEAN SyncOrRestore
2007 EFI_STRING Progress
;
2011 NAME_VALUE_NODE
*Node
;
2015 Status
= EFI_SUCCESS
;
2017 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2018 return EFI_NOT_FOUND
;
2021 if (ConfigInfo
->ElementCount
== 0) {
2023 // Skip if there is no RequestElement
2028 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2029 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2030 BufferSize
= ConfigInfo
->Storage
->Size
;
2032 if (SyncOrRestore
) {
2033 Src
= ConfigInfo
->Storage
->EditBuffer
;
2034 Dst
= ConfigInfo
->Storage
->Buffer
;
2036 Src
= ConfigInfo
->Storage
->Buffer
;
2037 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2040 Status
= mHiiConfigRouting
->BlockToConfig(
2042 ConfigInfo
->ConfigRequest
,
2048 if (EFI_ERROR (Status
)) {
2052 Status
= mHiiConfigRouting
->ConfigToBlock (
2059 if (Result
!= NULL
) {
2062 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2063 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2064 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2065 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2067 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2068 if (SyncOrRestore
) {
2069 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2071 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2075 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2084 Discard data based on the input setting scope (Form, FormSet or System).
2086 @param FormSet FormSet data structure.
2087 @param Form Form data structure.
2088 @param SettingScope Setting Scope for Discard action.
2090 @retval EFI_SUCCESS The function completed successfully.
2091 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2096 IN FORM_BROWSER_FORMSET
*FormSet
,
2097 IN FORM_BROWSER_FORM
*Form
,
2098 IN BROWSER_SETTING_SCOPE SettingScope
2102 FORMSET_STORAGE
*Storage
;
2103 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2104 FORM_BROWSER_FORMSET
*LocalFormSet
;
2107 // Check the supported setting level.
2109 if (SettingScope
>= MaxLevel
) {
2110 return EFI_UNSUPPORTED
;
2113 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2115 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2116 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2117 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2118 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2120 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2125 // Skip if there is no RequestElement
2127 if (ConfigInfo
->ElementCount
== 0) {
2132 // Prepare <ConfigResp>
2134 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2137 Form
->NvUpdateRequired
= FALSE
;
2138 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2140 // Discard Buffer storage or Name/Value storage
2142 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2143 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2144 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2145 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2147 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2152 // Skip if there is no RequestElement
2154 if (Storage
->ElementCount
== 0) {
2158 SynchronizeStorage(Storage
, FALSE
);
2161 UpdateNvInfoInForm (FormSet
, FALSE
);
2162 } else if (SettingScope
== SystemLevel
) {
2164 // System Level Discard.
2168 // Discard changed value for each FormSet in the maintain list.
2170 Link
= GetFirstNode (&gBrowserFormSetList
);
2171 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2172 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2173 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2174 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2175 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2177 // Remove maintain backup list after discard except for the current using FormSet.
2179 RemoveEntryList (&LocalFormSet
->Link
);
2180 DestroyFormSet (LocalFormSet
);
2189 Submit data based on the input Setting level (Form, FormSet or System).
2191 @param FormSet FormSet data structure.
2192 @param Form Form data structure.
2193 @param SettingScope Setting Scope for Submit action.
2195 @retval EFI_SUCCESS The function completed successfully.
2196 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2201 IN FORM_BROWSER_FORMSET
*FormSet
,
2202 IN FORM_BROWSER_FORM
*Form
,
2203 IN BROWSER_SETTING_SCOPE SettingScope
2208 EFI_STRING ConfigResp
;
2209 EFI_STRING Progress
;
2210 FORMSET_STORAGE
*Storage
;
2213 FORM_BROWSER_FORMSET
*LocalFormSet
;
2214 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2217 // Check the supported setting level.
2219 if (SettingScope
>= MaxLevel
) {
2220 return EFI_UNSUPPORTED
;
2224 // Validate the Form by NoSubmit check
2226 Status
= EFI_SUCCESS
;
2227 if (SettingScope
== FormLevel
) {
2228 Status
= NoSubmitCheck (FormSet
, Form
);
2229 } else if (SettingScope
== FormSetLevel
) {
2230 Status
= NoSubmitCheck (FormSet
, NULL
);
2232 if (EFI_ERROR (Status
)) {
2236 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2238 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2239 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2240 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2241 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2243 Storage
= ConfigInfo
->Storage
;
2244 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2249 // Skip if there is no RequestElement
2251 if (ConfigInfo
->ElementCount
== 0) {
2256 // 1. Prepare <ConfigResp>
2258 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2259 if (EFI_ERROR (Status
)) {
2264 // 2. Set value to hii driver or efi variable.
2266 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2267 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2269 // Send <ConfigResp> to Configuration Driver
2271 if (FormSet
->ConfigAccess
!= NULL
) {
2272 Status
= FormSet
->ConfigAccess
->RouteConfig (
2273 FormSet
->ConfigAccess
,
2277 if (EFI_ERROR (Status
)) {
2278 FreePool (ConfigResp
);
2282 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2284 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2285 if (TmpBuf
== NULL
) {
2286 Status
= EFI_OUT_OF_RESOURCES
;
2290 BufferSize
= Storage
->Size
;
2291 Status
= gRT
->GetVariable (
2298 if (EFI_ERROR (Status
)) {
2300 FreePool (ConfigResp
);
2303 ASSERT (BufferSize
== Storage
->Size
);
2304 Status
= mHiiConfigRouting
->ConfigToBlock (
2311 if (EFI_ERROR (Status
)) {
2313 FreePool (ConfigResp
);
2317 Status
= gRT
->SetVariable (
2320 Storage
->Attributes
,
2325 if (EFI_ERROR (Status
)) {
2326 FreePool (ConfigResp
);
2330 FreePool (ConfigResp
);
2332 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2334 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2338 // 4. Update the NV flag.
2340 Form
->NvUpdateRequired
= FALSE
;
2341 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2343 // Submit Buffer storage or Name/Value storage
2345 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2346 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2347 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2348 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2350 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2355 // Skip if there is no RequestElement
2357 if (Storage
->ElementCount
== 0) {
2362 // 1. Prepare <ConfigResp>
2364 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2365 if (EFI_ERROR (Status
)) {
2369 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2370 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2373 // 2. Send <ConfigResp> to Configuration Driver
2375 if (FormSet
->ConfigAccess
!= NULL
) {
2376 Status
= FormSet
->ConfigAccess
->RouteConfig (
2377 FormSet
->ConfigAccess
,
2381 if (EFI_ERROR (Status
)) {
2382 FreePool (ConfigResp
);
2386 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2388 // 1&2. Set the edit data to the variable.
2391 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2392 if (TmpBuf
== NULL
) {
2393 Status
= EFI_OUT_OF_RESOURCES
;
2396 BufferSize
= Storage
->Size
;
2397 Status
= gRT
->GetVariable (
2404 ASSERT (BufferSize
== Storage
->Size
);
2405 Status
= mHiiConfigRouting
->ConfigToBlock (
2412 if (EFI_ERROR (Status
)) {
2414 FreePool (ConfigResp
);
2418 Status
= gRT
->SetVariable (
2421 Storage
->Attributes
,
2425 if (EFI_ERROR (Status
)) {
2427 FreePool (ConfigResp
);
2432 FreePool (ConfigResp
);
2434 // 3. Config success, update storage shadow Buffer
2436 SynchronizeStorage (Storage
, TRUE
);
2440 // 4. Update the NV flag.
2442 UpdateNvInfoInForm (FormSet
, FALSE
);
2443 } else if (SettingScope
== SystemLevel
) {
2445 // System Level Save.
2449 // Save changed value for each FormSet in the maintain list.
2451 Link
= GetFirstNode (&gBrowserFormSetList
);
2452 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2453 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2454 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2455 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2456 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2458 // Remove maintain backup list after save except for the current using FormSet.
2460 RemoveEntryList (&LocalFormSet
->Link
);
2461 DestroyFormSet (LocalFormSet
);
2470 Get Question default value from AltCfg string.
2472 @param FormSet The form set.
2473 @param Question The question.
2474 @param DefaultId The default Id.
2476 @retval EFI_SUCCESS Question is reset to default value.
2480 GetDefaultValueFromAltCfg (
2481 IN FORM_BROWSER_FORMSET
*FormSet
,
2482 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2486 BOOLEAN IsBufferStorage
;
2489 FORMSET_STORAGE
*Storage
;
2490 CHAR16
*ConfigRequest
;
2503 Status
= EFI_NOT_FOUND
;
2506 ConfigRequest
= NULL
;
2510 Storage
= Question
->Storage
;
2512 if ((Storage
== NULL
) ||
2513 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2514 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2519 // Question Value is provided by Buffer Storage or NameValue Storage
2521 if (Question
->BufferValue
!= NULL
) {
2523 // This Question is password or orderedlist
2525 Dst
= Question
->BufferValue
;
2528 // Other type of Questions
2530 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2533 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2534 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2537 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2538 // <ConfigHdr> + "&" + <VariableName>
2540 if (IsBufferStorage
) {
2541 Length
= StrLen (Storage
->ConfigHdr
);
2542 Length
+= StrLen (Question
->BlockName
);
2544 Length
= StrLen (Storage
->ConfigHdr
);
2545 Length
+= StrLen (Question
->VariableName
) + 1;
2547 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2548 ASSERT (ConfigRequest
!= NULL
);
2550 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2551 if (IsBufferStorage
) {
2552 StrCat (ConfigRequest
, Question
->BlockName
);
2554 StrCat (ConfigRequest
, L
"&");
2555 StrCat (ConfigRequest
, Question
->VariableName
);
2558 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2559 FormSet
->ConfigAccess
,
2564 if (EFI_ERROR (Status
)) {
2569 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2570 // Get the default configuration string according to the default ID.
2572 Status
= mHiiConfigRouting
->GetAltConfig (
2578 &DefaultId
, // it can be NULL to get the current setting.
2583 // The required setting can't be found. So, it is not required to be validated and set.
2585 if (EFI_ERROR (Status
)) {
2590 // Skip <ConfigRequest>
2592 if (IsBufferStorage
) {
2593 Value
= StrStr (ConfigResp
, L
"&VALUE");
2594 ASSERT (Value
!= NULL
);
2600 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2601 ASSERT (Value
!= NULL
);
2603 Value
= Value
+ StrLen (Question
->VariableName
);
2605 if (*Value
!= '=') {
2606 Status
= EFI_NOT_FOUND
;
2610 // Skip '=', point to value
2615 // Suppress <AltResp> if any
2618 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2623 LengthStr
= StrLen (Value
);
2624 if (!IsBufferStorage
&& IsString
) {
2625 StringPtr
= (CHAR16
*) Dst
;
2626 ZeroMem (TemStr
, sizeof (TemStr
));
2627 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2628 StrnCpy (TemStr
, Value
+ Index
, 4);
2629 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2632 // Add tailing L'\0' character
2634 StringPtr
[Index
/4] = L
'\0';
2636 ZeroMem (TemStr
, sizeof (TemStr
));
2637 for (Index
= 0; Index
< LengthStr
; Index
++) {
2638 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2639 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2640 if ((Index
& 1) == 0) {
2641 Dst
[Index
/2] = DigitUint8
;
2643 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2649 if (ConfigRequest
!= NULL
){
2650 FreePool (ConfigRequest
);
2653 if (ConfigResp
!= NULL
) {
2654 FreePool (ConfigResp
);
2657 if (Result
!= NULL
) {
2665 Get default Id value used for browser.
2667 @param DefaultId The default id value used by hii.
2669 @retval Browser used default value.
2673 GetDefaultIdForCallBack (
2677 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2678 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2679 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2680 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2681 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2682 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2683 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2684 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2685 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2686 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2687 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2688 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2695 Reset Question to its default value.
2697 @param FormSet The form set.
2698 @param Form The form.
2699 @param Question The question.
2700 @param DefaultId The Class of the default.
2702 @retval EFI_SUCCESS Question is reset to default value.
2706 GetQuestionDefault (
2707 IN FORM_BROWSER_FORMSET
*FormSet
,
2708 IN FORM_BROWSER_FORM
*Form
,
2709 IN FORM_BROWSER_STATEMENT
*Question
,
2715 QUESTION_DEFAULT
*Default
;
2716 QUESTION_OPTION
*Option
;
2717 EFI_HII_VALUE
*HiiValue
;
2719 EFI_STRING StrValue
;
2720 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2721 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2724 Status
= EFI_NOT_FOUND
;
2728 // Statement don't have storage, skip them
2730 if (Question
->QuestionId
== 0) {
2735 // There are Five ways to specify default value for a Question:
2736 // 1, use call back function (highest priority)
2737 // 2, use ExtractConfig function
2738 // 3, use nested EFI_IFR_DEFAULT
2739 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2740 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2742 HiiValue
= &Question
->HiiValue
;
2745 // Get Question defaut value from call back function.
2747 ConfigAccess
= FormSet
->ConfigAccess
;
2748 Action
= GetDefaultIdForCallBack (DefaultId
);
2749 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2750 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2751 Status
= ConfigAccess
->Callback (
2754 Question
->QuestionId
,
2759 if (!EFI_ERROR (Status
)) {
2765 // Get default value from altcfg string.
2767 if (ConfigAccess
!= NULL
) {
2768 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2769 if (!EFI_ERROR (Status
)) {
2775 // EFI_IFR_DEFAULT has highest priority
2777 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2778 Link
= GetFirstNode (&Question
->DefaultListHead
);
2779 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2780 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2782 if (Default
->DefaultId
== DefaultId
) {
2783 if (Default
->ValueExpression
!= NULL
) {
2785 // Default is provided by an Expression, evaluate it
2787 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2788 if (EFI_ERROR (Status
)) {
2792 CopyMem (HiiValue
, &Default
->ValueExpression
->Result
, sizeof (EFI_HII_VALUE
));
2795 // Default value is embedded in EFI_IFR_DEFAULT
2797 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2800 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2801 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
2802 if (StrValue
== NULL
) {
2803 return EFI_NOT_FOUND
;
2805 if (Question
->StorageWidth
> StrSize (StrValue
)) {
2806 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
2808 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
2815 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
2820 // EFI_ONE_OF_OPTION
2822 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
2823 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2825 // OneOfOption could only provide Standard and Manufacturing default
2827 Link
= GetFirstNode (&Question
->OptionListHead
);
2828 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2829 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2831 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
2832 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
2834 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
2839 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2845 // EFI_IFR_CHECKBOX - lowest priority
2847 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
2848 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2850 // Checkbox could only provide Standard and Manufacturing default
2852 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
2853 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
2855 HiiValue
->Value
.b
= TRUE
;
2857 HiiValue
->Value
.b
= FALSE
;
2865 // For Questions without default
2867 Status
= EFI_NOT_FOUND
;
2868 switch (Question
->Operand
) {
2869 case EFI_IFR_NUMERIC_OP
:
2871 // Take minimum value as numeric default value
2873 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
2874 HiiValue
->Value
.u64
= Question
->Minimum
;
2875 Status
= EFI_SUCCESS
;
2879 case EFI_IFR_ONE_OF_OP
:
2881 // Take first oneof option as oneof's default value
2883 if (ValueToOption (Question
, HiiValue
) == NULL
) {
2884 Link
= GetFirstNode (&Question
->OptionListHead
);
2885 if (!IsNull (&Question
->OptionListHead
, Link
)) {
2886 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2887 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
2888 Status
= EFI_SUCCESS
;
2893 case EFI_IFR_ORDERED_LIST_OP
:
2895 // Take option sequence in IFR as ordered list's default value
2898 Link
= GetFirstNode (&Question
->OptionListHead
);
2899 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2900 Status
= EFI_SUCCESS
;
2901 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2903 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
2906 if (Index
>= Question
->MaxContainers
) {
2910 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2923 Reset Questions to their default value in a Form, Formset or System.
2925 @param FormSet FormSet data structure.
2926 @param Form Form data structure.
2927 @param DefaultId The Class of the default.
2928 @param SettingScope Setting Scope for Default action.
2930 @retval EFI_SUCCESS The function completed successfully.
2931 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2936 IN FORM_BROWSER_FORMSET
*FormSet
,
2937 IN FORM_BROWSER_FORM
*Form
,
2938 IN UINT16 DefaultId
,
2939 IN BROWSER_SETTING_SCOPE SettingScope
2943 LIST_ENTRY
*FormLink
;
2945 FORM_BROWSER_STATEMENT
*Question
;
2946 FORM_BROWSER_FORMSET
*BackUpFormSet
;
2947 FORM_BROWSER_FORMSET
*LocalFormSet
;
2948 EFI_HII_HANDLE
*HiiHandles
;
2951 UINTN BackUpClassOfVfr
;
2954 // Check the supported setting level.
2956 if (SettingScope
>= MaxLevel
) {
2957 return EFI_UNSUPPORTED
;
2960 if (SettingScope
== FormLevel
) {
2962 // Extract Form default
2964 Link
= GetFirstNode (&Form
->StatementListHead
);
2965 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2966 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2967 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2970 // If Question is disabled, don't reset it to default
2972 if (Question
->DisableExpression
!= NULL
) {
2973 Status
= EvaluateExpression (FormSet
, Form
, Question
->DisableExpression
);
2974 if (!EFI_ERROR (Status
) && Question
->DisableExpression
->Result
.Value
.b
) {
2980 // Reset Question to its default value
2982 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
2983 if (EFI_ERROR (Status
)) {
2988 // Synchronize Buffer storage's Edit buffer
2990 if ((Question
->Storage
!= NULL
) &&
2991 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2992 SetQuestionValue (FormSet
, Form
, Question
, TRUE
);
2994 // Update Form NV flag.
2996 Form
->NvUpdateRequired
= TRUE
;
2999 } else if (SettingScope
== FormSetLevel
) {
3000 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3001 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3002 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3003 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
);
3004 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3006 } else if (SettingScope
== SystemLevel
) {
3008 // Open all FormSet by locate HII packages.
3009 // Initiliaze the maintain FormSet to store default data as back up data.
3011 BackUpClassOfVfr
= gClassOfVfr
;
3012 BackUpFormSet
= gOldFormSet
;
3016 // Get all the Hii handles
3018 HiiHandles
= HiiGetHiiHandles (NULL
);
3019 ASSERT (HiiHandles
!= NULL
);
3022 // Search for formset of each class type
3024 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3026 // Check HiiHandles[Index] does exist in global maintain list.
3028 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3033 // Initilize FormSet Setting
3035 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3036 ASSERT (LocalFormSet
!= NULL
);
3037 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3038 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
3039 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3040 DestroyFormSet (LocalFormSet
);
3043 Status
= InitializeCurrentSetting (LocalFormSet
);
3044 if (EFI_ERROR (Status
)) {
3045 DestroyFormSet (LocalFormSet
);
3050 // Add FormSet into the maintain list.
3052 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3056 // Free resources, and restore gOldFormSet and gClassOfVfr
3058 FreePool (HiiHandles
);
3059 gOldFormSet
= BackUpFormSet
;
3060 gClassOfVfr
= BackUpClassOfVfr
;
3063 // Set Default Value for each FormSet in the maintain list.
3065 Link
= GetFirstNode (&gBrowserFormSetList
);
3066 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3067 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3068 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
);
3069 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3077 Initialize Question's Edit copy from Storage.
3079 @param Selection Selection contains the information about
3080 the Selection, form and formset to be displayed.
3081 Selection action may be updated in retrieve callback.
3082 @param FormSet FormSet data structure.
3083 @param Form Form data structure.
3085 @retval EFI_SUCCESS The function completed successfully.
3090 IN OUT UI_MENU_SELECTION
*Selection
,
3091 IN FORM_BROWSER_FORMSET
*FormSet
,
3092 IN FORM_BROWSER_FORM
*Form
3097 FORM_BROWSER_STATEMENT
*Question
;
3101 Link
= GetFirstNode (&Form
->StatementListHead
);
3102 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3103 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3106 // Initialize local copy of Value for each Question
3108 Status
= GetQuestionValue (FormSet
, Form
, Question
, TRUE
);
3109 if (EFI_ERROR (Status
)) {
3113 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3114 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3118 // According the spec, ref opcode try to get value from call back with "retrieve" type.
3120 if ((Question
->Operand
== EFI_IFR_REF_OP
) && (FormSet
->ConfigAccess
!= NULL
)) {
3121 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3122 if (EFI_ERROR (Status
)) {
3128 // Check whether EfiVarstore with CallBack can be got.
3130 if ((FormSet
->ConfigAccess
!= NULL
) &&
3131 (Selection
->Action
!= UI_ACTION_REFRESH_FORMSET
) &&
3132 (Question
->QuestionId
!= 0) &&
3133 (Question
->Storage
!= NULL
) &&
3134 (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) &&
3135 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3138 // Check QuestionValue does exist.
3140 StorageWidth
= Question
->StorageWidth
;
3141 if (Question
->BufferValue
!= NULL
) {
3142 BufferValue
= Question
->BufferValue
;
3144 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3146 Status
= gRT
->GetVariable (
3147 Question
->VariableName
,
3148 &Question
->Storage
->Guid
,
3154 if (!EFI_ERROR (Status
)) {
3155 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3159 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3166 Initialize Question's Edit copy from Storage for the whole Formset.
3168 @param Selection Selection contains the information about
3169 the Selection, form and formset to be displayed.
3170 Selection action may be updated in retrieve callback.
3171 @param FormSet FormSet data structure.
3173 @retval EFI_SUCCESS The function completed successfully.
3178 IN OUT UI_MENU_SELECTION
*Selection
,
3179 IN FORM_BROWSER_FORMSET
*FormSet
3184 FORM_BROWSER_FORM
*Form
;
3186 Link
= GetFirstNode (&FormSet
->FormListHead
);
3187 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3188 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3191 // Initialize local copy of Value for each Form
3193 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3194 if (EFI_ERROR (Status
)) {
3198 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3205 Fill storage's edit copy with settings requested from Configuration Driver.
3207 @param FormSet FormSet data structure.
3208 @param Storage Buffer Storage.
3210 @retval EFI_SUCCESS The function completed successfully.
3215 IN FORM_BROWSER_FORMSET
*FormSet
,
3216 IN FORMSET_STORAGE
*Storage
3220 EFI_STRING Progress
;
3224 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3228 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3229 Status
= gRT
->GetVariable (
3233 (UINTN
*)&Storage
->Size
,
3239 if (FormSet
->ConfigAccess
== NULL
) {
3240 return EFI_NOT_FOUND
;
3243 if (Storage
->ElementCount
== 0) {
3245 // Skip if there is no RequestElement
3251 // Request current settings from Configuration Driver
3253 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3254 FormSet
->ConfigAccess
,
3255 Storage
->ConfigRequest
,
3259 if (EFI_ERROR (Status
)) {
3264 // Convert Result from <ConfigAltResp> to <ConfigResp>
3266 StrPtr
= StrStr (Result
, L
"ALTCFG");
3267 if (StrPtr
!= NULL
) {
3271 Status
= ConfigRespToStorage (Storage
, Result
);
3278 Copy uncommitted data from source Storage to destination Storage.
3280 @param Dst Target Storage for uncommitted data.
3281 @param Src Source Storage for uncommitted data.
3283 @retval EFI_SUCCESS The function completed successfully.
3284 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
3289 IN OUT FORMSET_STORAGE
*Dst
,
3290 IN FORMSET_STORAGE
*Src
3294 NAME_VALUE_NODE
*Node
;
3296 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
3297 return EFI_INVALID_PARAMETER
;
3300 switch (Src
->Type
) {
3301 case EFI_HII_VARSTORE_BUFFER
:
3302 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3303 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
3304 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
3307 case EFI_HII_VARSTORE_NAME_VALUE
:
3308 Link
= GetFirstNode (&Src
->NameValueListHead
);
3309 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
3310 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3312 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, TRUE
);
3313 SetValueByName (Dst
, Node
->Name
, Node
->Value
, FALSE
);
3315 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
3319 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3329 Get current setting of Questions.
3331 @param FormSet FormSet data structure.
3333 @retval EFI_SUCCESS The function completed successfully.
3337 InitializeCurrentSetting (
3338 IN OUT FORM_BROWSER_FORMSET
*FormSet
3343 FORMSET_STORAGE
*Storage
;
3344 FORMSET_STORAGE
*StorageSrc
;
3345 FORMSET_STORAGE
*OldStorage
;
3346 FORM_BROWSER_FORM
*Form
;
3347 FORM_BROWSER_FORM
*Form2
;
3351 // Extract default from IFR binary
3353 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
);
3354 UpdateNvInfoInForm (FormSet
, FALSE
);
3357 // Request current settings from Configuration Driver
3359 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3360 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3361 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3364 if (gOldFormSet
!= NULL
) {
3366 // Try to find the Storage in backup formset gOldFormSet
3368 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3369 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3370 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3372 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3373 OldStorage
= StorageSrc
;
3377 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3381 if (OldStorage
== NULL
) {
3383 // Storage is not found in backup formset, request it from ConfigDriver
3385 Status
= LoadStorage (FormSet
, Storage
);
3387 // Now Edit Buffer is filled with default values(lower priority) and current
3388 // settings(higher priority), sychronize it to shadow Buffer
3390 if (!EFI_ERROR (Status
)) {
3391 SynchronizeStorage (Storage
, TRUE
);
3395 // Storage found in backup formset, use it
3397 Status
= CopyStorage (Storage
, OldStorage
);
3400 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3404 // If has old formset, get the old nv update status.
3406 if (gOldFormSet
!= NULL
) {
3407 Link
= GetFirstNode (&FormSet
->FormListHead
);
3408 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3409 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3411 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3412 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3413 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3415 if (Form
->FormId
== Form2
->FormId
) {
3416 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3420 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3422 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3431 Fetch the Ifr binary data of a FormSet.
3433 @param Handle PackageList Handle
3434 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3435 specified (NULL or zero GUID), take the first
3436 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3437 found in package list.
3438 On output, GUID of the formset found(if not NULL).
3439 @param BinaryLength The length of the FormSet IFR binary.
3440 @param BinaryData The buffer designed to receive the FormSet.
3442 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3443 BufferLength was updated.
3444 @retval EFI_INVALID_PARAMETER The handle is unknown.
3445 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3446 be found with the requested FormId.
3451 IN EFI_HII_HANDLE Handle
,
3452 IN OUT EFI_GUID
*FormSetGuid
,
3453 OUT UINTN
*BinaryLength
,
3454 OUT UINT8
**BinaryData
3458 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3464 UINT32 PackageListLength
;
3465 EFI_HII_PACKAGE_HEADER PackageHeader
;
3467 UINT8 NumberOfClassGuid
;
3468 BOOLEAN ClassGuidMatch
;
3469 EFI_GUID
*ClassGuid
;
3470 EFI_GUID
*ComparingGuid
;
3474 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3477 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3479 if (FormSetGuid
== NULL
) {
3480 ComparingGuid
= &gZeroGuid
;
3482 ComparingGuid
= FormSetGuid
;
3486 // Get HII PackageList
3489 HiiPackageList
= NULL
;
3490 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3491 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3492 HiiPackageList
= AllocatePool (BufferSize
);
3493 ASSERT (HiiPackageList
!= NULL
);
3495 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3497 if (EFI_ERROR (Status
)) {
3500 ASSERT (HiiPackageList
!= NULL
);
3503 // Get Form package from this HII package List
3505 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3507 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3509 ClassGuidMatch
= FALSE
;
3510 while (Offset
< PackageListLength
) {
3511 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3512 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3514 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3516 // Search FormSet in this Form Package
3518 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3519 while (Offset2
< PackageHeader
.Length
) {
3520 OpCodeData
= Package
+ Offset2
;
3522 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3524 // Try to compare against formset GUID
3526 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3527 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3531 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3533 // Try to compare against formset class GUID
3535 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3536 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3537 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3538 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3539 ClassGuidMatch
= TRUE
;
3543 if (ClassGuidMatch
) {
3546 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3547 ClassGuidMatch
= TRUE
;
3552 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3555 if (Offset2
< PackageHeader
.Length
) {
3557 // Target formset found
3563 Offset
+= PackageHeader
.Length
;
3566 if (Offset
>= PackageListLength
) {
3568 // Form package not found in this Package List
3570 FreePool (HiiPackageList
);
3571 return EFI_NOT_FOUND
;
3574 if (FormSetGuid
!= NULL
) {
3576 // Return the FormSet GUID
3578 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3582 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3583 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3584 // of the Form Package.
3586 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3587 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3589 FreePool (HiiPackageList
);
3591 if (*BinaryData
== NULL
) {
3592 return EFI_OUT_OF_RESOURCES
;
3600 Initialize the internal data structure of a FormSet.
3602 @param Handle PackageList Handle
3603 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3604 specified (NULL or zero GUID), take the first
3605 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3606 found in package list.
3607 On output, GUID of the formset found(if not NULL).
3608 @param FormSet FormSet data structure.
3610 @retval EFI_SUCCESS The function completed successfully.
3611 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3616 IN EFI_HII_HANDLE Handle
,
3617 IN OUT EFI_GUID
*FormSetGuid
,
3618 OUT FORM_BROWSER_FORMSET
*FormSet
3622 EFI_HANDLE DriverHandle
;
3625 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3626 if (EFI_ERROR (Status
)) {
3630 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3631 FormSet
->HiiHandle
= Handle
;
3632 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3635 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3637 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3638 if (EFI_ERROR (Status
)) {
3641 FormSet
->DriverHandle
= DriverHandle
;
3642 Status
= gBS
->HandleProtocol (
3644 &gEfiHiiConfigAccessProtocolGuid
,
3645 (VOID
**) &FormSet
->ConfigAccess
3647 if (EFI_ERROR (Status
)) {
3649 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3650 // list, then there will be no configuration action required
3652 FormSet
->ConfigAccess
= NULL
;
3656 // Parse the IFR binary OpCodes
3658 Status
= ParseOpCodes (FormSet
);
3659 if (EFI_ERROR (Status
)) {
3664 // Set VFR type by FormSet SubClass field
3666 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
3667 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
3668 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
3672 // Set VFR type by FormSet class guid
3674 for (Index
= 0; Index
< 3; Index
++) {
3675 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
3676 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
3681 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
3682 gFrontPageHandle
= FormSet
->HiiHandle
;
3683 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
3687 // Match GUID to find out the function key setting. If match fail, use the default setting.
3689 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
3690 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
3692 // Update the function key setting.
3694 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
3703 Save globals used by previous call to SendForm(). SendForm() may be called from
3704 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
3705 So, save globals of previous call to SendForm() and restore them upon exit.
3709 SaveBrowserContext (
3713 BROWSER_CONTEXT
*Context
;
3715 gBrowserContextCount
++;
3716 if (gBrowserContextCount
== 1) {
3718 // This is not reentry of SendForm(), no context to save
3723 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
3724 ASSERT (Context
!= NULL
);
3726 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
3729 // Save FormBrowser context
3731 Context
->BannerData
= gBannerData
;
3732 Context
->ClassOfVfr
= gClassOfVfr
;
3733 Context
->FunctionKeySetting
= gFunctionKeySetting
;
3734 Context
->ResetRequired
= gResetRequired
;
3735 Context
->Direction
= gDirection
;
3736 Context
->EnterString
= gEnterString
;
3737 Context
->EnterCommitString
= gEnterCommitString
;
3738 Context
->EnterEscapeString
= gEnterEscapeString
;
3739 Context
->EscapeString
= gEscapeString
;
3740 Context
->MoveHighlight
= gMoveHighlight
;
3741 Context
->MakeSelection
= gMakeSelection
;
3742 Context
->DecNumericInput
= gDecNumericInput
;
3743 Context
->HexNumericInput
= gHexNumericInput
;
3744 Context
->ToggleCheckBox
= gToggleCheckBox
;
3745 Context
->PromptForData
= gPromptForData
;
3746 Context
->PromptForPassword
= gPromptForPassword
;
3747 Context
->PromptForNewPassword
= gPromptForNewPassword
;
3748 Context
->ConfirmPassword
= gConfirmPassword
;
3749 Context
->ConfirmError
= gConfirmError
;
3750 Context
->PassowordInvalid
= gPassowordInvalid
;
3751 Context
->PressEnter
= gPressEnter
;
3752 Context
->EmptyString
= gEmptyString
;
3753 Context
->AreYouSure
= gAreYouSure
;
3754 Context
->YesResponse
= gYesResponse
;
3755 Context
->NoResponse
= gNoResponse
;
3756 Context
->MiniString
= gMiniString
;
3757 Context
->PlusString
= gPlusString
;
3758 Context
->MinusString
= gMinusString
;
3759 Context
->AdjustNumber
= gAdjustNumber
;
3760 Context
->SaveChanges
= gSaveChanges
;
3761 Context
->OptionMismatch
= gOptionMismatch
;
3762 Context
->FormSuppress
= gFormSuppress
;
3763 Context
->PromptBlockWidth
= gPromptBlockWidth
;
3764 Context
->OptionBlockWidth
= gOptionBlockWidth
;
3765 Context
->HelpBlockWidth
= gHelpBlockWidth
;
3766 Context
->OldFormSet
= gOldFormSet
;
3767 Context
->MenuRefreshHead
= gMenuRefreshHead
;
3769 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
3770 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
3773 // Insert to FormBrowser context list
3775 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
3780 Restore globals used by previous call to SendForm().
3784 RestoreBrowserContext (
3789 BROWSER_CONTEXT
*Context
;
3791 ASSERT (gBrowserContextCount
!= 0);
3792 gBrowserContextCount
--;
3793 if (gBrowserContextCount
== 0) {
3795 // This is not reentry of SendForm(), no context to restore
3800 ASSERT (!IsListEmpty (&gBrowserContextList
));
3802 Link
= GetFirstNode (&gBrowserContextList
);
3803 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
3806 // Restore FormBrowser context
3808 gBannerData
= Context
->BannerData
;
3809 gClassOfVfr
= Context
->ClassOfVfr
;
3810 gFunctionKeySetting
= Context
->FunctionKeySetting
;
3811 gResetRequired
= Context
->ResetRequired
;
3812 gDirection
= Context
->Direction
;
3813 gEnterString
= Context
->EnterString
;
3814 gEnterCommitString
= Context
->EnterCommitString
;
3815 gEnterEscapeString
= Context
->EnterEscapeString
;
3816 gEscapeString
= Context
->EscapeString
;
3817 gMoveHighlight
= Context
->MoveHighlight
;
3818 gMakeSelection
= Context
->MakeSelection
;
3819 gDecNumericInput
= Context
->DecNumericInput
;
3820 gHexNumericInput
= Context
->HexNumericInput
;
3821 gToggleCheckBox
= Context
->ToggleCheckBox
;
3822 gPromptForData
= Context
->PromptForData
;
3823 gPromptForPassword
= Context
->PromptForPassword
;
3824 gPromptForNewPassword
= Context
->PromptForNewPassword
;
3825 gConfirmPassword
= Context
->ConfirmPassword
;
3826 gConfirmError
= Context
->ConfirmError
;
3827 gPassowordInvalid
= Context
->PassowordInvalid
;
3828 gPressEnter
= Context
->PressEnter
;
3829 gEmptyString
= Context
->EmptyString
;
3830 gAreYouSure
= Context
->AreYouSure
;
3831 gYesResponse
= Context
->YesResponse
;
3832 gNoResponse
= Context
->NoResponse
;
3833 gMiniString
= Context
->MiniString
;
3834 gPlusString
= Context
->PlusString
;
3835 gMinusString
= Context
->MinusString
;
3836 gAdjustNumber
= Context
->AdjustNumber
;
3837 gSaveChanges
= Context
->SaveChanges
;
3838 gOptionMismatch
= Context
->OptionMismatch
;
3839 gFormSuppress
= Context
->FormSuppress
;
3840 gPromptBlockWidth
= Context
->PromptBlockWidth
;
3841 gOptionBlockWidth
= Context
->OptionBlockWidth
;
3842 gHelpBlockWidth
= Context
->HelpBlockWidth
;
3843 gOldFormSet
= Context
->OldFormSet
;
3844 gMenuRefreshHead
= Context
->MenuRefreshHead
;
3846 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
3847 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
3850 // Remove from FormBrowser context list
3852 RemoveEntryList (&Context
->Link
);
3853 gBS
->FreePool (Context
);
3857 Find the matched FormSet context in the backup maintain list based on HiiHandle.
3859 @param Handle The Hii Handle.
3861 @return the found FormSet context. If no found, NULL will return.
3864 FORM_BROWSER_FORMSET
*
3865 GetFormSetFromHiiHandle (
3866 EFI_HII_HANDLE Handle
3870 FORM_BROWSER_FORMSET
*FormSet
;
3872 Link
= GetFirstNode (&gBrowserFormSetList
);
3873 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3874 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3875 if (FormSet
->HiiHandle
== Handle
) {
3878 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3885 Check whether the input HII handle is the FormSet that is being used.
3887 @param Handle The Hii Handle.
3889 @retval TRUE HII handle is being used.
3890 @retval FALSE HII handle is not being used.
3894 IsHiiHandleInBrowserContext (
3895 EFI_HII_HANDLE Handle
3899 BROWSER_CONTEXT
*Context
;
3902 // HiiHandle is Current FormSet.
3904 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
3909 // Check whether HiiHandle is in BrowserContext.
3911 Link
= GetFirstNode (&gBrowserContextList
);
3912 while (!IsNull (&gBrowserContextList
, Link
)) {
3913 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
3914 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
3916 // HiiHandle is in BrowserContext
3920 Link
= GetNextNode (&gBrowserContextList
, Link
);
3927 Find the registered HotKey based on KeyData.
3929 @param[in] KeyData A pointer to a buffer that describes the keystroke
3930 information for the hot key.
3932 @return The registered HotKey context. If no found, NULL will return.
3935 GetHotKeyFromRegisterList (
3936 IN EFI_INPUT_KEY
*KeyData
3940 BROWSER_HOT_KEY
*HotKey
;
3942 Link
= GetFirstNode (&gBrowserHotKeyList
);
3943 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
3944 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
3945 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
3948 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
3955 Configure what scope the hot key will impact.
3956 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
3957 If no scope is set, the default scope will be FormSet level.
3958 After all registered hot keys are removed, previous Scope can reset to another level.
3960 @param[in] Scope Scope level to be set.
3962 @retval EFI_SUCCESS Scope is set correctly.
3963 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
3964 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
3970 IN BROWSER_SETTING_SCOPE Scope
3973 if (Scope
>= MaxLevel
) {
3974 return EFI_INVALID_PARAMETER
;
3978 // When no hot key registered in system or on the first setting,
3979 // Scope can be set.
3981 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
3982 gBrowserSettingScope
= Scope
;
3983 mBrowserScopeFirstSet
= FALSE
;
3984 } else if (Scope
!= gBrowserSettingScope
) {
3985 return EFI_UNSUPPORTED
;
3992 Register the hot key with its browser action, or unregistered the hot key.
3993 Only support hot key that is not printable character (control key, function key, etc.).
3994 If the action value is zero, the hot key will be unregistered if it has been registered.
3995 If the same hot key has been registered, the new action and help string will override the previous ones.
3997 @param[in] KeyData A pointer to a buffer that describes the keystroke
3998 information for the hot key. Its type is EFI_INPUT_KEY to
3999 be supported by all ConsoleIn devices.
4000 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4001 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4002 @param[in] HelpString Help string that describes the hot key information.
4003 Its value may be NULL for the unregistered hot key.
4005 @retval EFI_SUCCESS Hot key is registered or unregistered.
4006 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4007 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4008 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4013 IN EFI_INPUT_KEY
*KeyData
,
4015 IN UINT16 DefaultId
,
4016 IN EFI_STRING HelpString OPTIONAL
4019 BROWSER_HOT_KEY
*HotKey
;
4022 // Check input parameters.
4024 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4025 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4026 return EFI_INVALID_PARAMETER
;
4030 // Check whether the input KeyData is in BrowserHotKeyList.
4032 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4035 // Unregister HotKey
4037 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4038 if (HotKey
!= NULL
) {
4040 // The registered HotKey is found.
4041 // Remove it from List, and free its resource.
4043 RemoveEntryList (&HotKey
->Link
);
4044 FreePool (HotKey
->KeyData
);
4045 FreePool (HotKey
->HelpString
);
4049 // The registered HotKey is not found.
4051 return EFI_NOT_FOUND
;
4056 // Register HotKey into List.
4058 if (HotKey
== NULL
) {
4060 // Create new Key, and add it into List.
4062 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4063 ASSERT (HotKey
!= NULL
);
4064 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4065 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4066 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4070 // Fill HotKey information.
4072 HotKey
->Action
= Action
;
4073 HotKey
->DefaultId
= DefaultId
;
4074 if (HotKey
->HelpString
!= NULL
) {
4075 FreePool (HotKey
->HelpString
);
4077 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4083 Register Exit handler function.
4084 When more than one handler function is registered, the latter one will override the previous one.
4085 When NULL handler is specified, the previous Exit handler will be unregistered.
4087 @param[in] Handler Pointer to handler function.
4092 RegiserExitHandler (
4093 IN EXIT_HANDLER Handler
4096 ExitHandlerFunction
= Handler
;
4101 Create reminder to let user to choose save or discard the changed browser data.
4102 Caller can use it to actively check the changed browser data.
4104 @retval BROWSER_NO_CHANGES No browser data is changed.
4105 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4106 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4116 FORM_BROWSER_FORMSET
*FormSet
;
4117 BOOLEAN IsDataChanged
;
4118 UINT32 DataSavedAction
;
4119 CHAR16
*YesResponse
;
4121 CHAR16
*EmptyString
;
4122 CHAR16
*ChangeReminderString
;
4123 CHAR16
*SaveConfirmString
;
4127 DataSavedAction
= BROWSER_NO_CHANGES
;
4128 IsDataChanged
= FALSE
;
4129 Link
= GetFirstNode (&gBrowserFormSetList
);
4130 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4131 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4132 if (IsNvUpdateRequired (FormSet
)) {
4133 IsDataChanged
= TRUE
;
4136 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4140 // No data is changed. No save is required.
4142 if (!IsDataChanged
) {
4143 return DataSavedAction
;
4147 // If data is changed, prompt user
4149 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4151 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4152 ASSERT (YesResponse
!= NULL
);
4153 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4154 ASSERT (NoResponse
!= NULL
);
4155 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4156 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4157 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4160 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4162 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4163 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4167 // If the user hits the YesResponse key
4169 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4170 SubmitForm (NULL
, NULL
, SystemLevel
);
4171 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4173 DiscardForm (NULL
, NULL
, SystemLevel
);
4174 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4175 gResetRequired
= FALSE
;
4178 FreePool (YesResponse
);
4179 FreePool (NoResponse
);
4180 FreePool (EmptyString
);
4181 FreePool (SaveConfirmString
);
4182 FreePool (ChangeReminderString
);
4184 return DataSavedAction
;