2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
32 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
33 EFI_HII_STRING_PROTOCOL
*mHiiString
;
34 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
35 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
37 UINTN gBrowserContextCount
= 0;
38 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
39 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
40 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
42 BANNER_DATA
*gBannerData
;
43 EFI_HII_HANDLE gFrontPageHandle
;
45 UINTN gFunctionKeySetting
;
46 BOOLEAN gResetRequired
;
47 EFI_HII_HANDLE gHiiHandle
;
49 EFI_SCREEN_DESCRIPTOR gScreenDimensions
;
50 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
51 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
52 EXIT_HANDLER ExitHandlerFunction
= NULL
;
56 // Browser Global Strings
59 CHAR16
*gDiscardFailed
;
60 CHAR16
*gDefaultFailed
;
62 CHAR16
*gEnterCommitString
;
63 CHAR16
*gEnterEscapeString
;
64 CHAR16
*gEscapeString
;
65 CHAR16
*gMoveHighlight
;
66 CHAR16
*gMakeSelection
;
67 CHAR16
*gDecNumericInput
;
68 CHAR16
*gHexNumericInput
;
69 CHAR16
*gToggleCheckBox
;
70 CHAR16
*gPromptForData
;
71 CHAR16
*gPromptForPassword
;
72 CHAR16
*gPromptForNewPassword
;
73 CHAR16
*gConfirmPassword
;
74 CHAR16
*gConfirmError
;
75 CHAR16
*gPassowordInvalid
;
84 CHAR16
*gAdjustNumber
;
86 CHAR16
*gOptionMismatch
;
87 CHAR16
*gFormSuppress
;
88 CHAR16
*gProtocolNotFound
;
90 CHAR16
*mUnknownString
= L
"!";
92 CHAR16 gPromptBlockWidth
;
93 CHAR16 gOptionBlockWidth
;
94 CHAR16 gHelpBlockWidth
;
96 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
97 EFI_GUID gSetupBrowserGuid
= {
98 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
101 FORM_BROWSER_FORMSET
*gOldFormSet
= NULL
;
103 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
123 NONE_FUNCTION_KEY_SETTING
144 NONE_FUNCTION_KEY_SETTING
165 NONE_FUNCTION_KEY_SETTING
168 // BMM File Explorer FormSet.
186 NONE_FUNCTION_KEY_SETTING
191 This is the routine which an external caller uses to direct the browser
192 where to obtain it's information.
195 @param This The Form Browser protocol instanse.
196 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
197 display a list of the formsets for the handles specified.
198 @param HandleCount The number of Handles specified in Handle.
199 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
200 field in the EFI_IFR_FORM_SET op-code for the specified
201 forms-based package. If FormSetGuid is NULL, then this
202 function will display the first found forms package.
203 @param FormId This field specifies which EFI_IFR_FORM to render as the first
204 displayable page. If this field has a value of 0x0000, then
205 the forms browser will render the specified forms in their encoded order.
206 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
208 @param ActionRequest Points to the action recommended by the form.
210 @retval EFI_SUCCESS The function completed successfully.
211 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
212 @retval EFI_NOT_FOUND No valid forms could be found to display.
218 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
219 IN EFI_HII_HANDLE
*Handles
,
220 IN UINTN HandleCount
,
221 IN EFI_GUID
*FormSetGuid
, OPTIONAL
222 IN UINT16 FormId
, OPTIONAL
223 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
224 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
228 UI_MENU_SELECTION
*Selection
;
230 FORM_BROWSER_FORMSET
*FormSet
;
234 // Calculate total number of Register HotKeys.
237 Link
= GetFirstNode (&gBrowserHotKeyList
);
238 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
239 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
243 // Show three HotKeys help information on one ROW.
245 gFooterHeight
= FOOTER_HEIGHT
+ (Index
/ 3);
248 // Save globals used by SendForm()
250 SaveBrowserContext ();
252 gResetRequired
= FALSE
;
253 Status
= EFI_SUCCESS
;
254 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
257 // Seed the dimensions in the global
259 gST
->ConOut
->QueryMode (
261 gST
->ConOut
->Mode
->Mode
,
262 &gScreenDimensions
.RightColumn
,
263 &gScreenDimensions
.BottomRow
266 if (ScreenDimensions
!= NULL
) {
268 // Check local dimension vs. global dimension.
270 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
271 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
273 Status
= EFI_INVALID_PARAMETER
;
277 // Local dimension validation.
279 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
280 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
281 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
283 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
284 SCROLL_ARROW_HEIGHT
*
286 FRONT_PAGE_HEADER_HEIGHT
+
291 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
293 Status
= EFI_INVALID_PARAMETER
;
299 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
300 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
301 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
304 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
306 InitializeBrowserStrings ();
309 // Ensure we are in Text mode
311 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
313 for (Index
= 0; Index
< HandleCount
; Index
++) {
314 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
315 ASSERT (Selection
!= NULL
);
317 Selection
->Handle
= Handles
[Index
];
318 if (FormSetGuid
!= NULL
) {
319 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
320 Selection
->FormId
= FormId
;
322 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
326 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
327 ASSERT (FormSet
!= NULL
);
330 // Initialize internal data structures of FormSet
332 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
, TRUE
);
333 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
334 DestroyFormSet (FormSet
);
337 Selection
->FormSet
= FormSet
;
340 // Try to find pre FormSet in the maintain backup list.
342 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
345 // Display this formset
347 gCurrentSelection
= Selection
;
349 Status
= SetupBrowser (Selection
);
351 gCurrentSelection
= NULL
;
353 if (EFI_ERROR (Status
)) {
357 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
359 if (gOldFormSet
!= NULL
) {
361 // If no data is changed, don't need to save current FormSet into the maintain list.
363 if (!IsNvUpdateRequired (gOldFormSet
)) {
364 RemoveEntryList (&gOldFormSet
->Link
);
365 DestroyFormSet (gOldFormSet
);
370 FreePool (Selection
);
373 if (ActionRequest
!= NULL
) {
374 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
375 if (gResetRequired
) {
376 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
380 FreeBrowserStrings ();
382 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
383 gST
->ConOut
->ClearScreen (gST
->ConOut
);
387 // Restore globals used by SendForm()
389 RestoreBrowserContext ();
396 This function is called by a callback handler to retrieve uncommitted state
397 data from the browser.
399 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
401 @param ResultsDataSize A pointer to the size of the buffer associated
403 @param ResultsData A string returned from an IFR browser or
404 equivalent. The results string will have no
405 routing information in them.
406 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
407 (if RetrieveData = TRUE) data from the uncommitted
408 browser state information or set (if RetrieveData
409 = FALSE) data in the uncommitted browser state
411 @param VariableGuid An optional field to indicate the target variable
413 @param VariableName An optional field to indicate the target
414 human-readable variable name.
416 @retval EFI_SUCCESS The results have been distributed or are awaiting
418 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
419 contain the results data.
425 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
426 IN OUT UINTN
*ResultsDataSize
,
427 IN OUT EFI_STRING ResultsData
,
428 IN BOOLEAN RetrieveData
,
429 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
430 IN CONST CHAR16
*VariableName OPTIONAL
435 FORMSET_STORAGE
*Storage
;
436 FORM_BROWSER_FORMSET
*FormSet
;
443 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
444 return EFI_INVALID_PARAMETER
;
447 if (gCurrentSelection
== NULL
) {
448 return EFI_NOT_READY
;
453 FormSet
= gCurrentSelection
->FormSet
;
456 // Find target storage
458 Link
= GetFirstNode (&FormSet
->StorageListHead
);
459 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
460 return EFI_UNSUPPORTED
;
463 if (VariableGuid
!= NULL
) {
465 // Try to find target storage
468 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
469 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
470 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
472 if (CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
473 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
474 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
476 // Buffer storage require both GUID and Name
478 if (VariableName
== NULL
) {
479 return EFI_NOT_FOUND
;
482 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
492 return EFI_NOT_FOUND
;
496 // GUID/Name is not specified, take the first storage in FormSet
498 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
503 // Skip if there is no RequestElement
505 if (Storage
->ElementCount
== 0) {
510 // Generate <ConfigResp>
512 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
513 if (EFI_ERROR (Status
)) {
518 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
520 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
522 BufferSize
= StrSize (StrPtr
);
523 if (*ResultsDataSize
< BufferSize
) {
524 *ResultsDataSize
= BufferSize
;
526 FreePool (ConfigResp
);
527 return EFI_BUFFER_TOO_SMALL
;
530 *ResultsDataSize
= BufferSize
;
531 CopyMem (ResultsData
, StrPtr
, BufferSize
);
533 FreePool (ConfigResp
);
536 // Prepare <ConfigResp>
538 TmpSize
= StrLen (ResultsData
);
539 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
540 ConfigResp
= AllocateZeroPool (BufferSize
);
541 ASSERT (ConfigResp
!= NULL
);
543 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
544 StrCat (ConfigResp
, L
"&");
545 StrCat (ConfigResp
, ResultsData
);
548 // Update Browser uncommited data
550 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
551 if (EFI_ERROR (Status
)) {
560 Initialize Setup Browser driver.
562 @param ImageHandle The image handle.
563 @param SystemTable The system table.
565 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
566 @return Other value if failed to initialize the Setup Browser module.
572 IN EFI_HANDLE ImageHandle
,
573 IN EFI_SYSTEM_TABLE
*SystemTable
577 EFI_INPUT_KEY DefaultHotKey
;
578 EFI_STRING HelpString
;
581 // Locate required Hii relative protocols
583 Status
= gBS
->LocateProtocol (
584 &gEfiHiiDatabaseProtocolGuid
,
586 (VOID
**) &mHiiDatabase
588 ASSERT_EFI_ERROR (Status
);
590 Status
= gBS
->LocateProtocol (
591 &gEfiHiiStringProtocolGuid
,
593 (VOID
**) &mHiiString
595 ASSERT_EFI_ERROR (Status
);
597 Status
= gBS
->LocateProtocol (
598 &gEfiHiiConfigRoutingProtocolGuid
,
600 (VOID
**) &mHiiConfigRouting
602 ASSERT_EFI_ERROR (Status
);
604 Status
= gBS
->LocateProtocol (
605 &gEfiDevicePathFromTextProtocolGuid
,
607 (VOID
**) &mPathFromText
611 // Publish our HII data
613 gHiiHandle
= HiiAddPackages (
619 ASSERT (gHiiHandle
!= NULL
);
622 // Initialize Driver private data
624 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
625 ASSERT (gBannerData
!= NULL
);
628 // Initialize generic help strings.
630 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
631 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
632 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
635 // Install FormBrowser2 protocol
637 mPrivateData
.Handle
= NULL
;
638 Status
= gBS
->InstallProtocolInterface (
639 &mPrivateData
.Handle
,
640 &gEfiFormBrowser2ProtocolGuid
,
641 EFI_NATIVE_INTERFACE
,
642 &mPrivateData
.FormBrowser2
644 ASSERT_EFI_ERROR (Status
);
647 // Install default HotKey F10 for Save
649 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
650 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
651 DefaultHotKey
.ScanCode
= SCAN_F10
;
652 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
653 FreePool (HelpString
);
655 // Install default HotKey F9 for Reset To Defaults
657 DefaultHotKey
.ScanCode
= SCAN_F9
;
658 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
659 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
660 FreePool (HelpString
);
663 // Install FormBrowserEx protocol
665 mPrivateData
.Handle
= NULL
;
666 Status
= gBS
->InstallProtocolInterface (
667 &mPrivateData
.Handle
,
668 &gEfiFormBrowserExProtocolGuid
,
669 EFI_NATIVE_INTERFACE
,
670 &mPrivateData
.FormBrowserEx
672 ASSERT_EFI_ERROR (Status
);
679 Create a new string in HII Package List.
681 @param String The String to be added
682 @param HiiHandle The package list in the HII database to insert the
685 @return The output string.
691 IN EFI_HII_HANDLE HiiHandle
694 EFI_STRING_ID StringId
;
696 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
697 ASSERT (StringId
!= 0);
704 Delete a string from HII Package List.
706 @param StringId Id of the string in HII database.
707 @param HiiHandle The HII package list handle.
709 @retval EFI_SUCCESS The string was deleted successfully.
714 IN EFI_STRING_ID StringId
,
715 IN EFI_HII_HANDLE HiiHandle
720 NullChar
= CHAR_NULL
;
721 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
727 Get the string based on the StringId and HII Package List Handle.
729 @param Token The String's ID.
730 @param HiiHandle The package list in the HII database to search for
731 the specified string.
733 @return The output string.
738 IN EFI_STRING_ID Token
,
739 IN EFI_HII_HANDLE HiiHandle
744 if (HiiHandle
== NULL
) {
748 String
= HiiGetString (HiiHandle
, Token
, NULL
);
749 if (String
== NULL
) {
750 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
751 ASSERT (String
!= NULL
);
753 return (CHAR16
*) String
;
758 Allocate new memory and then copy the Unicode string Source to Destination.
760 @param Dest Location to copy string
761 @param Src String to copy
766 IN OUT CHAR16
**Dest
,
773 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
774 ASSERT (*Dest
!= NULL
);
779 Allocate new memory and concatinate Source on the end of Destination.
781 @param Dest String to added to the end of.
782 @param Src String to concatinate.
787 IN OUT CHAR16
**Dest
,
795 NewStringCpy (Dest
, Src
);
799 TmpSize
= StrSize (*Dest
);
800 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
801 ASSERT (NewString
!= NULL
);
803 StrCpy (NewString
, *Dest
);
804 StrCat (NewString
, Src
);
812 Synchronize or restore Storage's Edit copy and Shadow copy.
814 @param Storage The Storage to be synchronized.
815 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
817 if TRUE, copy the editbuffer to the buffer.
818 if FALSE, copy the buffer to the editbuffer.
823 IN FORMSET_STORAGE
*Storage
,
824 IN BOOLEAN SyncOrRestore
828 NAME_VALUE_NODE
*Node
;
830 switch (Storage
->Type
) {
831 case EFI_HII_VARSTORE_BUFFER
:
832 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
834 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
836 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
840 case EFI_HII_VARSTORE_NAME_VALUE
:
841 Link
= GetFirstNode (&Storage
->NameValueListHead
);
842 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
843 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
846 NewStringCpy (&Node
->Value
, Node
->EditValue
);
848 NewStringCpy (&Node
->EditValue
, Node
->Value
);
851 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
855 case EFI_HII_VARSTORE_EFI_VARIABLE
:
863 Get Value for given Name from a NameValue Storage.
865 @param Storage The NameValue Storage.
866 @param Name The Name.
867 @param Value The retured Value.
868 @param GetValueFrom Where to get source value, from EditValue or Value.
870 @retval EFI_SUCCESS Value found for given Name.
871 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
876 IN FORMSET_STORAGE
*Storage
,
878 IN OUT CHAR16
**Value
,
879 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
883 NAME_VALUE_NODE
*Node
;
885 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
886 return EFI_INVALID_PARAMETER
;
891 Link
= GetFirstNode (&Storage
->NameValueListHead
);
892 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
893 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
895 if (StrCmp (Name
, Node
->Name
) == 0) {
896 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
897 NewStringCpy (Value
, Node
->EditValue
);
899 NewStringCpy (Value
, Node
->Value
);
904 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
907 return EFI_NOT_FOUND
;
912 Set Value of given Name in a NameValue Storage.
914 @param Storage The NameValue Storage.
915 @param Name The Name.
916 @param Value The Value to set.
917 @param SetValueTo Whether update editValue or Value.
919 @retval EFI_SUCCESS Value found for given Name.
920 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
925 IN FORMSET_STORAGE
*Storage
,
928 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
932 NAME_VALUE_NODE
*Node
;
935 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
936 return EFI_INVALID_PARAMETER
;
939 Link
= GetFirstNode (&Storage
->NameValueListHead
);
940 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
941 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
943 if (StrCmp (Name
, Node
->Name
) == 0) {
944 if (SetValueTo
== GetSetValueWithEditBuffer
) {
945 Buffer
= Node
->EditValue
;
947 Buffer
= Node
->Value
;
949 if (Buffer
!= NULL
) {
952 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
953 ASSERT (Buffer
!= NULL
);
954 if (SetValueTo
== GetSetValueWithEditBuffer
) {
955 Node
->EditValue
= Buffer
;
957 Node
->Value
= Buffer
;
962 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
965 return EFI_NOT_FOUND
;
970 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
972 @param Buffer The Storage to be conveted.
973 @param ConfigResp The returned <ConfigResp>.
974 @param SingleForm Whether update data for single form or formset level.
976 @retval EFI_SUCCESS Convert success.
977 @retval EFI_INVALID_PARAMETER Incorrect storage type.
981 StorageToConfigResp (
983 IN CHAR16
**ConfigResp
,
984 IN BOOLEAN SingleForm
990 NAME_VALUE_NODE
*Node
;
991 CHAR16
*ConfigRequest
;
992 FORMSET_STORAGE
*Storage
;
993 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
995 Status
= EFI_SUCCESS
;
997 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
998 Storage
= ConfigInfo
->Storage
;
999 ConfigRequest
= ConfigInfo
->ConfigRequest
;
1001 Storage
= (FORMSET_STORAGE
*) Buffer
;
1002 ConfigRequest
= Storage
->ConfigRequest
;
1005 switch (Storage
->Type
) {
1006 case EFI_HII_VARSTORE_BUFFER
:
1007 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1008 Status
= mHiiConfigRouting
->BlockToConfig (
1011 Storage
->EditBuffer
,
1018 case EFI_HII_VARSTORE_NAME_VALUE
:
1020 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1022 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1023 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1024 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1026 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1027 NewStringCat (ConfigResp
, L
"&");
1028 NewStringCat (ConfigResp
, Node
->Name
);
1029 NewStringCat (ConfigResp
, L
"=");
1030 NewStringCat (ConfigResp
, Node
->EditValue
);
1032 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1036 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1038 Status
= EFI_INVALID_PARAMETER
;
1047 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1049 @param Storage The Storage to receive the settings.
1050 @param ConfigResp The <ConfigResp> to be converted.
1052 @retval EFI_SUCCESS Convert success.
1053 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1057 ConfigRespToStorage (
1058 IN FORMSET_STORAGE
*Storage
,
1059 IN CHAR16
*ConfigResp
1063 EFI_STRING Progress
;
1069 Status
= EFI_SUCCESS
;
1071 switch (Storage
->Type
) {
1072 case EFI_HII_VARSTORE_BUFFER
:
1073 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1074 BufferSize
= Storage
->Size
;
1075 Status
= mHiiConfigRouting
->ConfigToBlock (
1078 Storage
->EditBuffer
,
1084 case EFI_HII_VARSTORE_NAME_VALUE
:
1085 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1086 if (StrPtr
== NULL
) {
1089 StrPtr
= StrStr (ConfigResp
, L
"&");
1090 while (StrPtr
!= NULL
) {
1094 StrPtr
= StrPtr
+ 1;
1096 StrPtr
= StrStr (StrPtr
, L
"=");
1097 if (StrPtr
== NULL
) {
1105 StrPtr
= StrPtr
+ 1;
1107 StrPtr
= StrStr (StrPtr
, L
"&");
1108 if (StrPtr
!= NULL
) {
1111 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
);
1115 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1117 Status
= EFI_INVALID_PARAMETER
;
1126 Get Question's current Value.
1128 @param FormSet FormSet data structure.
1129 @param Form Form data structure.
1130 @param Question Question to be initialized.
1131 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1133 @retval EFI_SUCCESS The function completed successfully.
1138 IN FORM_BROWSER_FORMSET
*FormSet
,
1139 IN FORM_BROWSER_FORM
*Form
,
1140 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1141 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1150 FORMSET_STORAGE
*Storage
;
1151 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1152 CHAR16
*ConfigRequest
;
1160 BOOLEAN IsBufferStorage
;
1166 Status
= EFI_SUCCESS
;
1170 if (GetValueFrom
>= GetSetValueWithMax
) {
1171 return EFI_INVALID_PARAMETER
;
1175 // Statement don't have storage, skip them
1177 if (Question
->QuestionId
== 0) {
1182 // Question value is provided by an Expression, evaluate it
1184 if (Question
->ValueExpression
!= NULL
) {
1185 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1186 if (!EFI_ERROR (Status
)) {
1187 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1188 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1189 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1190 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1191 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1193 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1194 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1196 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1198 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1199 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1205 // Get question value by read expression.
1207 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1208 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1209 if (!EFI_ERROR (Status
) &&
1210 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1212 // Only update question value to the valid result.
1214 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1215 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1216 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1217 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1218 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1220 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1221 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1223 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1225 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1226 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1232 // Question value is provided by RTC
1234 Storage
= Question
->Storage
;
1235 QuestionValue
= &Question
->HiiValue
.Value
;
1236 if (Storage
== NULL
) {
1238 // It's a Question without storage, or RTC date/time
1240 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1242 // Date and time define the same Flags bit
1244 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1245 case QF_DATE_STORAGE_TIME
:
1246 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1249 case QF_DATE_STORAGE_WAKEUP
:
1250 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1253 case QF_DATE_STORAGE_NORMAL
:
1256 // For date/time without storage
1261 if (EFI_ERROR (Status
)) {
1265 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1266 QuestionValue
->date
.Year
= EfiTime
.Year
;
1267 QuestionValue
->date
.Month
= EfiTime
.Month
;
1268 QuestionValue
->date
.Day
= EfiTime
.Day
;
1270 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1271 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1272 QuestionValue
->time
.Second
= EfiTime
.Second
;
1280 // Question value is provided by EFI variable
1282 StorageWidth
= Question
->StorageWidth
;
1283 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1284 if (Question
->BufferValue
!= NULL
) {
1285 Dst
= Question
->BufferValue
;
1287 Dst
= (UINT8
*) QuestionValue
;
1290 Status
= gRT
->GetVariable (
1291 Question
->VariableName
,
1298 // Always return success, even this EFI variable doesn't exist
1304 // Question Value is provided by Buffer Storage or NameValue Storage
1306 if (Question
->BufferValue
!= NULL
) {
1308 // This Question is password or orderedlist
1310 Dst
= Question
->BufferValue
;
1313 // Other type of Questions
1315 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1318 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1319 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1320 IsBufferStorage
= TRUE
;
1322 IsBufferStorage
= FALSE
;
1324 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1325 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1326 if (IsBufferStorage
) {
1327 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1329 // Copy from storage Edit buffer
1331 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1334 // Copy from storage Edit buffer
1336 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1340 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1341 if (EFI_ERROR (Status
)) {
1345 ASSERT (Value
!= NULL
);
1346 LengthStr
= StrLen (Value
);
1347 Status
= EFI_SUCCESS
;
1350 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1351 // Add string tail char L'\0' into Length
1353 Length
= StorageWidth
+ sizeof (CHAR16
);
1354 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1355 Status
= EFI_BUFFER_TOO_SMALL
;
1357 StringPtr
= (CHAR16
*) Dst
;
1358 ZeroMem (TemStr
, sizeof (TemStr
));
1359 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1360 StrnCpy (TemStr
, Value
+ Index
, 4);
1361 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1364 // Add tailing L'\0' character
1366 StringPtr
[Index
/4] = L
'\0';
1369 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1370 Status
= EFI_BUFFER_TOO_SMALL
;
1372 ZeroMem (TemStr
, sizeof (TemStr
));
1373 for (Index
= 0; Index
< LengthStr
; Index
++) {
1374 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1375 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1376 if ((Index
& 1) == 0) {
1377 Dst
[Index
/2] = DigitUint8
;
1379 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1388 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1390 // Request current settings from Configuration Driver
1392 if (FormSet
->ConfigAccess
== NULL
) {
1393 return EFI_NOT_FOUND
;
1397 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1398 // <ConfigHdr> + "&" + <VariableName>
1400 if (IsBufferStorage
) {
1401 Length
= StrLen (Storage
->ConfigHdr
);
1402 Length
+= StrLen (Question
->BlockName
);
1404 Length
= StrLen (Storage
->ConfigHdr
);
1405 Length
+= StrLen (Question
->VariableName
) + 1;
1407 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1408 ASSERT (ConfigRequest
!= NULL
);
1410 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1411 if (IsBufferStorage
) {
1412 StrCat (ConfigRequest
, Question
->BlockName
);
1414 StrCat (ConfigRequest
, L
"&");
1415 StrCat (ConfigRequest
, Question
->VariableName
);
1418 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1419 FormSet
->ConfigAccess
,
1424 FreePool (ConfigRequest
);
1425 if (EFI_ERROR (Status
)) {
1430 // Skip <ConfigRequest>
1432 if (IsBufferStorage
) {
1433 Value
= StrStr (Result
, L
"&VALUE");
1434 if (Value
== NULL
) {
1436 return EFI_NOT_FOUND
;
1443 Value
= Result
+ Length
;
1445 if (*Value
!= '=') {
1447 return EFI_NOT_FOUND
;
1450 // Skip '=', point to value
1455 // Suppress <AltResp> if any
1458 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1463 LengthStr
= StrLen (Value
);
1464 Status
= EFI_SUCCESS
;
1465 if (!IsBufferStorage
&& IsString
) {
1467 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1468 // Add string tail char L'\0' into Length
1470 Length
= StorageWidth
+ sizeof (CHAR16
);
1471 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1472 Status
= EFI_BUFFER_TOO_SMALL
;
1474 StringPtr
= (CHAR16
*) Dst
;
1475 ZeroMem (TemStr
, sizeof (TemStr
));
1476 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1477 StrnCpy (TemStr
, Value
+ Index
, 4);
1478 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1481 // Add tailing L'\0' character
1483 StringPtr
[Index
/4] = L
'\0';
1486 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1487 Status
= EFI_BUFFER_TOO_SMALL
;
1489 ZeroMem (TemStr
, sizeof (TemStr
));
1490 for (Index
= 0; Index
< LengthStr
; Index
++) {
1491 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1492 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1493 if ((Index
& 1) == 0) {
1494 Dst
[Index
/2] = DigitUint8
;
1496 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1502 if (EFI_ERROR (Status
)) {
1506 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1508 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1509 if (TemBuffer
== NULL
) {
1510 Status
= EFI_OUT_OF_RESOURCES
;
1513 Length
= Storage
->Size
;
1514 Status
= gRT
->GetVariable (
1521 if (EFI_ERROR (Status
)) {
1522 FreePool (TemBuffer
);
1526 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1528 FreePool (TemBuffer
);
1532 // Synchronize Edit Buffer
1534 if (IsBufferStorage
) {
1535 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1537 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
);
1540 if (Result
!= NULL
) {
1550 Save Question Value to edit copy(cached) or Storage(uncached).
1552 @param FormSet FormSet data structure.
1553 @param Form Form data structure.
1554 @param Question Pointer to the Question.
1555 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1557 @retval EFI_SUCCESS The function completed successfully.
1562 IN FORM_BROWSER_FORMSET
*FormSet
,
1563 IN FORM_BROWSER_FORM
*Form
,
1564 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1565 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1575 FORMSET_STORAGE
*Storage
;
1576 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1581 BOOLEAN IsBufferStorage
;
1588 Status
= EFI_SUCCESS
;
1590 if (SetValueTo
>= GetSetValueWithMax
) {
1591 return EFI_INVALID_PARAMETER
;
1595 // Statement don't have storage, skip them
1597 if (Question
->QuestionId
== 0) {
1602 // If Question value is provided by an Expression, then it is read only
1604 if (Question
->ValueExpression
!= NULL
) {
1609 // Before set question value, evaluate its write expression.
1611 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1612 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1613 if (EFI_ERROR (Status
)) {
1619 // Question value is provided by RTC
1621 Storage
= Question
->Storage
;
1622 QuestionValue
= &Question
->HiiValue
.Value
;
1623 if (Storage
== NULL
) {
1625 // It's a Question without storage, or RTC date/time
1627 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1629 // Date and time define the same Flags bit
1631 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1632 case QF_DATE_STORAGE_TIME
:
1633 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1636 case QF_DATE_STORAGE_WAKEUP
:
1637 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1640 case QF_DATE_STORAGE_NORMAL
:
1643 // For date/time without storage
1648 if (EFI_ERROR (Status
)) {
1652 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1653 EfiTime
.Year
= QuestionValue
->date
.Year
;
1654 EfiTime
.Month
= QuestionValue
->date
.Month
;
1655 EfiTime
.Day
= QuestionValue
->date
.Day
;
1657 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1658 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1659 EfiTime
.Second
= QuestionValue
->time
.Second
;
1662 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1663 Status
= gRT
->SetTime (&EfiTime
);
1665 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1673 // Question value is provided by EFI variable
1675 StorageWidth
= Question
->StorageWidth
;
1676 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1677 if (Question
->BufferValue
!= NULL
) {
1678 Src
= Question
->BufferValue
;
1680 Src
= (UINT8
*) QuestionValue
;
1683 Status
= gRT
->SetVariable (
1684 Question
->VariableName
,
1686 Storage
->Attributes
,
1694 // Question Value is provided by Buffer Storage or NameValue Storage
1696 if (Question
->BufferValue
!= NULL
) {
1697 Src
= Question
->BufferValue
;
1699 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1702 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1703 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1704 IsBufferStorage
= TRUE
;
1706 IsBufferStorage
= FALSE
;
1708 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1710 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1711 if (IsBufferStorage
) {
1712 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1714 // Copy to storage edit buffer
1716 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1717 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1719 // Copy to storage edit buffer
1721 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1726 // Allocate enough string buffer.
1729 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1730 Value
= AllocateZeroPool (BufferLen
);
1731 ASSERT (Value
!= NULL
);
1733 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1735 TemName
= (CHAR16
*) Src
;
1737 for (; *TemName
!= L
'\0'; TemName
++) {
1738 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1741 BufferLen
= StorageWidth
* 2 + 1;
1742 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1743 ASSERT (Value
!= NULL
);
1745 // Convert Buffer to Hex String
1747 TemBuffer
= Src
+ StorageWidth
- 1;
1749 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1750 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1754 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
);
1757 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1758 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1760 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1761 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1763 if (IsBufferStorage
) {
1764 Length
= StrLen (Question
->BlockName
) + 7;
1766 Length
= StrLen (Question
->VariableName
) + 2;
1768 if (!IsBufferStorage
&& IsString
) {
1769 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1771 Length
+= (StorageWidth
* 2);
1773 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1774 ASSERT (ConfigResp
!= NULL
);
1776 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1777 if (IsBufferStorage
) {
1778 StrCat (ConfigResp
, Question
->BlockName
);
1779 StrCat (ConfigResp
, L
"&VALUE=");
1781 StrCat (ConfigResp
, L
"&");
1782 StrCat (ConfigResp
, Question
->VariableName
);
1783 StrCat (ConfigResp
, L
"=");
1786 Value
= ConfigResp
+ StrLen (ConfigResp
);
1788 if (!IsBufferStorage
&& IsString
) {
1790 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1792 TemName
= (CHAR16
*) Src
;
1794 for (; *TemName
!= L
'\0'; TemName
++) {
1795 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1799 // Convert Buffer to Hex String
1801 TemBuffer
= Src
+ StorageWidth
- 1;
1803 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1804 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1809 // Convert to lower char.
1811 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1812 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1813 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1818 // Submit Question Value to Configuration Driver
1820 if (FormSet
->ConfigAccess
!= NULL
) {
1821 Status
= FormSet
->ConfigAccess
->RouteConfig (
1822 FormSet
->ConfigAccess
,
1826 if (EFI_ERROR (Status
)) {
1827 FreePool (ConfigResp
);
1831 FreePool (ConfigResp
);
1833 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1835 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1836 if (TemBuffer
== NULL
) {
1837 Status
= EFI_OUT_OF_RESOURCES
;
1840 Length
= Storage
->Size
;
1841 Status
= gRT
->GetVariable (
1849 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1851 Status
= gRT
->SetVariable (
1854 Storage
->Attributes
,
1858 FreePool (TemBuffer
);
1859 if (EFI_ERROR (Status
)){
1864 // Sync storage, from editbuffer to buffer.
1866 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1874 Perform inconsistent check for a Form.
1876 @param FormSet FormSet data structure.
1877 @param Form Form data structure.
1878 @param Question The Question to be validated.
1879 @param Type Validation type: InConsistent or NoSubmit
1881 @retval EFI_SUCCESS Form validation pass.
1882 @retval other Form validation failed.
1887 IN FORM_BROWSER_FORMSET
*FormSet
,
1888 IN FORM_BROWSER_FORM
*Form
,
1889 IN FORM_BROWSER_STATEMENT
*Question
,
1895 LIST_ENTRY
*ListHead
;
1898 FORM_EXPRESSION
*Expression
;
1900 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1901 ListHead
= &Question
->InconsistentListHead
;
1902 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1903 ListHead
= &Question
->NoSubmitListHead
;
1905 return EFI_UNSUPPORTED
;
1908 Link
= GetFirstNode (ListHead
);
1909 while (!IsNull (ListHead
, Link
)) {
1910 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1913 // Evaluate the expression
1915 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1916 if (EFI_ERROR (Status
)) {
1920 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1922 // Condition meet, show up error message
1924 if (Expression
->Error
!= 0) {
1925 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1927 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1928 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1932 return EFI_NOT_READY
;
1935 Link
= GetNextNode (ListHead
, Link
);
1943 Perform NoSubmit check for each Form in FormSet.
1945 @param FormSet FormSet data structure.
1946 @param CurrentForm Current input form data structure.
1948 @retval EFI_SUCCESS Form validation pass.
1949 @retval other Form validation failed.
1954 IN FORM_BROWSER_FORMSET
*FormSet
,
1955 IN FORM_BROWSER_FORM
*CurrentForm
1960 FORM_BROWSER_STATEMENT
*Question
;
1961 FORM_BROWSER_FORM
*Form
;
1962 LIST_ENTRY
*LinkForm
;
1964 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1965 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1966 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1967 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1969 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
1973 Link
= GetFirstNode (&Form
->StatementListHead
);
1974 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1975 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1977 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
1978 if (EFI_ERROR (Status
)) {
1982 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1990 Fill storage's edit copy with settings requested from Configuration Driver.
1992 @param FormSet FormSet data structure.
1993 @param ConfigInfo The config info related to this form.
1994 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
1995 editbuffer to buffer
1996 if TRUE, copy the editbuffer to the buffer.
1997 if FALSE, copy the buffer to the editbuffer.
1999 @retval EFI_SUCCESS The function completed successfully.
2003 SynchronizeStorageForForm (
2004 IN FORM_BROWSER_FORMSET
*FormSet
,
2005 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2006 IN BOOLEAN SyncOrRestore
2010 EFI_STRING Progress
;
2014 NAME_VALUE_NODE
*Node
;
2018 Status
= EFI_SUCCESS
;
2020 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2021 return EFI_NOT_FOUND
;
2024 if (ConfigInfo
->ElementCount
== 0) {
2026 // Skip if there is no RequestElement
2031 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2032 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2033 BufferSize
= ConfigInfo
->Storage
->Size
;
2035 if (SyncOrRestore
) {
2036 Src
= ConfigInfo
->Storage
->EditBuffer
;
2037 Dst
= ConfigInfo
->Storage
->Buffer
;
2039 Src
= ConfigInfo
->Storage
->Buffer
;
2040 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2043 Status
= mHiiConfigRouting
->BlockToConfig(
2045 ConfigInfo
->ConfigRequest
,
2051 if (EFI_ERROR (Status
)) {
2055 Status
= mHiiConfigRouting
->ConfigToBlock (
2062 if (Result
!= NULL
) {
2065 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2066 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2067 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2068 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2070 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2071 if (SyncOrRestore
) {
2072 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2074 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2078 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2086 When discard the question value, call the callback function with Changed type
2087 to inform the hii driver.
2089 @param FormSet FormSet data structure.
2090 @param Form Form data structure.
2094 SendDiscardInfoToDriver (
2095 IN FORM_BROWSER_FORMSET
*FormSet
,
2096 IN FORM_BROWSER_FORM
*Form
2100 FORM_BROWSER_STATEMENT
*Question
;
2102 EFI_HII_VALUE HiiValue
;
2104 BOOLEAN ValueChanged
;
2105 EFI_IFR_TYPE_VALUE
*TypeValue
;
2106 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2108 ValueChanged
= FALSE
;
2111 if(!Form
->NvUpdateRequired
) {
2115 Link
= GetFirstNode (&Form
->StatementListHead
);
2116 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2117 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2118 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2120 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2124 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2128 if (Question
->BufferValue
!= NULL
) {
2129 BufferValue
= AllocateZeroPool (Question
->StorageWidth
);
2130 ASSERT (BufferValue
!= NULL
);
2131 CopyMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
);
2133 HiiValue
.Type
= Question
->HiiValue
.Type
;
2134 CopyMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2137 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
2138 if (EFI_ERROR (Status
)) {
2139 if (BufferValue
!= NULL
) {
2140 FreePool (BufferValue
);
2146 if (Question
->BufferValue
!= NULL
) {
2147 if (CompareMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
)) {
2148 ValueChanged
= TRUE
;
2151 if (CompareMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
))) {
2152 ValueChanged
= TRUE
;
2156 if (BufferValue
!= NULL
) {
2157 FreePool (BufferValue
);
2161 if (!ValueChanged
) {
2165 ValueChanged
= FALSE
;
2167 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2168 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2170 TypeValue
= &Question
->HiiValue
.Value
;
2173 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2174 FormSet
->ConfigAccess
->Callback (
2175 FormSet
->ConfigAccess
,
2176 EFI_BROWSER_ACTION_CHANGED
,
2177 Question
->QuestionId
,
2178 Question
->HiiValue
.Type
,
2186 Validate the FormSet. If the formset is not validate, remove it from the list.
2188 @param FormSet The input FormSet which need to validate.
2190 @retval TRUE The handle is validate.
2191 @retval FALSE The handle is invalidate.
2196 FORM_BROWSER_FORMSET
*FormSet
2199 EFI_HII_HANDLE
*HiiHandles
;
2203 ASSERT (FormSet
!= NULL
);
2206 // Get all the Hii handles
2208 HiiHandles
= HiiGetHiiHandles (NULL
);
2209 ASSERT (HiiHandles
!= NULL
);
2212 // Search for formset of each class type
2214 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2215 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2222 RemoveEntryList (&FormSet
->Link
);
2223 DestroyFormSet (FormSet
);
2226 FreePool (HiiHandles
);
2232 Discard data based on the input setting scope (Form, FormSet or System).
2234 @param FormSet FormSet data structure.
2235 @param Form Form data structure.
2236 @param SettingScope Setting Scope for Discard action.
2238 @retval EFI_SUCCESS The function completed successfully.
2239 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2244 IN FORM_BROWSER_FORMSET
*FormSet
,
2245 IN FORM_BROWSER_FORM
*Form
,
2246 IN BROWSER_SETTING_SCOPE SettingScope
2250 FORMSET_STORAGE
*Storage
;
2251 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2252 FORM_BROWSER_FORMSET
*LocalFormSet
;
2255 // Check the supported setting level.
2257 if (SettingScope
>= MaxLevel
) {
2258 return EFI_UNSUPPORTED
;
2261 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2263 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2264 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2265 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2266 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2268 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2273 // Skip if there is no RequestElement
2275 if (ConfigInfo
->ElementCount
== 0) {
2280 // Prepare <ConfigResp>
2282 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2285 // Call callback with Changed type to inform the driver.
2287 SendDiscardInfoToDriver (FormSet
, Form
);
2290 Form
->NvUpdateRequired
= FALSE
;
2291 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2294 // Discard Buffer storage or Name/Value storage
2296 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2297 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2298 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2299 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2301 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2306 // Skip if there is no RequestElement
2308 if (Storage
->ElementCount
== 0) {
2312 SynchronizeStorage(Storage
, FALSE
);
2315 Link
= GetFirstNode (&FormSet
->FormListHead
);
2316 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2317 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2318 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2321 // Call callback with Changed type to inform the driver.
2323 SendDiscardInfoToDriver (FormSet
, Form
);
2326 UpdateNvInfoInForm (FormSet
, FALSE
);
2327 } else if (SettingScope
== SystemLevel
) {
2329 // System Level Discard.
2333 // Discard changed value for each FormSet in the maintain list.
2335 Link
= GetFirstNode (&gBrowserFormSetList
);
2336 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2337 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2338 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2339 if (!ValidateFormSet(LocalFormSet
)) {
2342 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2343 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2345 // Remove maintain backup list after discard except for the current using FormSet.
2347 RemoveEntryList (&LocalFormSet
->Link
);
2348 DestroyFormSet (LocalFormSet
);
2357 Submit data based on the input Setting level (Form, FormSet or System).
2359 @param FormSet FormSet data structure.
2360 @param Form Form data structure.
2361 @param SettingScope Setting Scope for Submit action.
2363 @retval EFI_SUCCESS The function completed successfully.
2364 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2369 IN FORM_BROWSER_FORMSET
*FormSet
,
2370 IN FORM_BROWSER_FORM
*Form
,
2371 IN BROWSER_SETTING_SCOPE SettingScope
2376 EFI_STRING ConfigResp
;
2377 EFI_STRING Progress
;
2378 FORMSET_STORAGE
*Storage
;
2381 FORM_BROWSER_FORMSET
*LocalFormSet
;
2382 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2385 // Check the supported setting level.
2387 if (SettingScope
>= MaxLevel
) {
2388 return EFI_UNSUPPORTED
;
2392 // Validate the Form by NoSubmit check
2394 Status
= EFI_SUCCESS
;
2395 if (SettingScope
== FormLevel
) {
2396 Status
= NoSubmitCheck (FormSet
, Form
);
2397 } else if (SettingScope
== FormSetLevel
) {
2398 Status
= NoSubmitCheck (FormSet
, NULL
);
2400 if (EFI_ERROR (Status
)) {
2404 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2406 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2407 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2408 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2409 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2411 Storage
= ConfigInfo
->Storage
;
2412 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2417 // Skip if there is no RequestElement
2419 if (ConfigInfo
->ElementCount
== 0) {
2424 // 1. Prepare <ConfigResp>
2426 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2427 if (EFI_ERROR (Status
)) {
2432 // 2. Set value to hii driver or efi variable.
2434 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2435 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2437 // Send <ConfigResp> to Configuration Driver
2439 if (FormSet
->ConfigAccess
!= NULL
) {
2440 Status
= FormSet
->ConfigAccess
->RouteConfig (
2441 FormSet
->ConfigAccess
,
2445 if (EFI_ERROR (Status
)) {
2446 FreePool (ConfigResp
);
2450 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2452 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2453 if (TmpBuf
== NULL
) {
2454 Status
= EFI_OUT_OF_RESOURCES
;
2458 BufferSize
= Storage
->Size
;
2459 Status
= gRT
->GetVariable (
2466 if (EFI_ERROR (Status
)) {
2468 FreePool (ConfigResp
);
2471 ASSERT (BufferSize
== Storage
->Size
);
2472 Status
= mHiiConfigRouting
->ConfigToBlock (
2479 if (EFI_ERROR (Status
)) {
2481 FreePool (ConfigResp
);
2485 Status
= gRT
->SetVariable (
2488 Storage
->Attributes
,
2493 if (EFI_ERROR (Status
)) {
2494 FreePool (ConfigResp
);
2498 FreePool (ConfigResp
);
2500 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2502 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2506 // 4. Update the NV flag.
2508 Form
->NvUpdateRequired
= FALSE
;
2509 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2511 // Submit Buffer storage or Name/Value storage
2513 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2514 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2515 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2516 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2518 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2523 // Skip if there is no RequestElement
2525 if (Storage
->ElementCount
== 0) {
2530 // 1. Prepare <ConfigResp>
2532 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2533 if (EFI_ERROR (Status
)) {
2537 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2538 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2541 // 2. Send <ConfigResp> to Configuration Driver
2543 if (FormSet
->ConfigAccess
!= NULL
) {
2544 Status
= FormSet
->ConfigAccess
->RouteConfig (
2545 FormSet
->ConfigAccess
,
2549 if (EFI_ERROR (Status
)) {
2550 FreePool (ConfigResp
);
2554 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2556 // 1&2. Set the edit data to the variable.
2559 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2560 if (TmpBuf
== NULL
) {
2561 Status
= EFI_OUT_OF_RESOURCES
;
2564 BufferSize
= Storage
->Size
;
2565 Status
= gRT
->GetVariable (
2572 ASSERT (BufferSize
== Storage
->Size
);
2573 Status
= mHiiConfigRouting
->ConfigToBlock (
2580 if (EFI_ERROR (Status
)) {
2582 FreePool (ConfigResp
);
2586 Status
= gRT
->SetVariable (
2589 Storage
->Attributes
,
2593 if (EFI_ERROR (Status
)) {
2595 FreePool (ConfigResp
);
2600 FreePool (ConfigResp
);
2602 // 3. Config success, update storage shadow Buffer
2604 SynchronizeStorage (Storage
, TRUE
);
2608 // 4. Update the NV flag.
2610 UpdateNvInfoInForm (FormSet
, FALSE
);
2611 } else if (SettingScope
== SystemLevel
) {
2613 // System Level Save.
2617 // Save changed value for each FormSet in the maintain list.
2619 Link
= GetFirstNode (&gBrowserFormSetList
);
2620 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2621 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2622 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2623 if (!ValidateFormSet(LocalFormSet
)) {
2626 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2627 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2629 // Remove maintain backup list after save except for the current using FormSet.
2631 RemoveEntryList (&LocalFormSet
->Link
);
2632 DestroyFormSet (LocalFormSet
);
2641 Get Question default value from AltCfg string.
2643 @param FormSet The form set.
2644 @param Question The question.
2645 @param DefaultId The default Id.
2647 @retval EFI_SUCCESS Question is reset to default value.
2651 GetDefaultValueFromAltCfg (
2652 IN FORM_BROWSER_FORMSET
*FormSet
,
2653 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2657 BOOLEAN IsBufferStorage
;
2660 FORMSET_STORAGE
*Storage
;
2661 CHAR16
*ConfigRequest
;
2674 Status
= EFI_NOT_FOUND
;
2677 ConfigRequest
= NULL
;
2681 Storage
= Question
->Storage
;
2683 if ((Storage
== NULL
) ||
2684 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2685 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2690 // Question Value is provided by Buffer Storage or NameValue Storage
2692 if (Question
->BufferValue
!= NULL
) {
2694 // This Question is password or orderedlist
2696 Dst
= Question
->BufferValue
;
2699 // Other type of Questions
2701 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2704 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2705 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2708 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2709 // <ConfigHdr> + "&" + <VariableName>
2711 if (IsBufferStorage
) {
2712 Length
= StrLen (Storage
->ConfigHdr
);
2713 Length
+= StrLen (Question
->BlockName
);
2715 Length
= StrLen (Storage
->ConfigHdr
);
2716 Length
+= StrLen (Question
->VariableName
) + 1;
2718 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2719 ASSERT (ConfigRequest
!= NULL
);
2721 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2722 if (IsBufferStorage
) {
2723 StrCat (ConfigRequest
, Question
->BlockName
);
2725 StrCat (ConfigRequest
, L
"&");
2726 StrCat (ConfigRequest
, Question
->VariableName
);
2729 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2730 FormSet
->ConfigAccess
,
2735 if (EFI_ERROR (Status
)) {
2740 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2741 // Get the default configuration string according to the default ID.
2743 Status
= mHiiConfigRouting
->GetAltConfig (
2749 &DefaultId
, // it can be NULL to get the current setting.
2754 // The required setting can't be found. So, it is not required to be validated and set.
2756 if (EFI_ERROR (Status
)) {
2761 // Skip <ConfigRequest>
2763 if (IsBufferStorage
) {
2764 Value
= StrStr (ConfigResp
, L
"&VALUE");
2765 ASSERT (Value
!= NULL
);
2771 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2772 ASSERT (Value
!= NULL
);
2774 Value
= Value
+ StrLen (Question
->VariableName
);
2776 if (*Value
!= '=') {
2777 Status
= EFI_NOT_FOUND
;
2781 // Skip '=', point to value
2786 // Suppress <AltResp> if any
2789 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2794 LengthStr
= StrLen (Value
);
2795 if (!IsBufferStorage
&& IsString
) {
2796 StringPtr
= (CHAR16
*) Dst
;
2797 ZeroMem (TemStr
, sizeof (TemStr
));
2798 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2799 StrnCpy (TemStr
, Value
+ Index
, 4);
2800 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2803 // Add tailing L'\0' character
2805 StringPtr
[Index
/4] = L
'\0';
2807 ZeroMem (TemStr
, sizeof (TemStr
));
2808 for (Index
= 0; Index
< LengthStr
; Index
++) {
2809 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2810 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2811 if ((Index
& 1) == 0) {
2812 Dst
[Index
/2] = DigitUint8
;
2814 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2820 if (ConfigRequest
!= NULL
){
2821 FreePool (ConfigRequest
);
2824 if (ConfigResp
!= NULL
) {
2825 FreePool (ConfigResp
);
2828 if (Result
!= NULL
) {
2836 Get default Id value used for browser.
2838 @param DefaultId The default id value used by hii.
2840 @retval Browser used default value.
2844 GetDefaultIdForCallBack (
2848 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2849 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2850 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2851 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2852 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2853 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2854 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2855 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2856 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2857 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2858 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2859 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2866 Reset Question to its default value.
2868 @param FormSet The form set.
2869 @param Form The form.
2870 @param Question The question.
2871 @param DefaultId The Class of the default.
2873 @retval EFI_SUCCESS Question is reset to default value.
2877 GetQuestionDefault (
2878 IN FORM_BROWSER_FORMSET
*FormSet
,
2879 IN FORM_BROWSER_FORM
*Form
,
2880 IN FORM_BROWSER_STATEMENT
*Question
,
2886 QUESTION_DEFAULT
*Default
;
2887 QUESTION_OPTION
*Option
;
2888 EFI_HII_VALUE
*HiiValue
;
2890 EFI_STRING StrValue
;
2891 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2892 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2895 Status
= EFI_NOT_FOUND
;
2899 // Statement don't have storage, skip them
2901 if (Question
->QuestionId
== 0) {
2906 // There are Five ways to specify default value for a Question:
2907 // 1, use call back function (highest priority)
2908 // 2, use ExtractConfig function
2909 // 3, use nested EFI_IFR_DEFAULT
2910 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2911 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2913 HiiValue
= &Question
->HiiValue
;
2916 // Get Question defaut value from call back function.
2918 ConfigAccess
= FormSet
->ConfigAccess
;
2919 Action
= GetDefaultIdForCallBack (DefaultId
);
2920 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2921 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2922 Status
= ConfigAccess
->Callback (
2925 Question
->QuestionId
,
2930 if (!EFI_ERROR (Status
)) {
2936 // Get default value from altcfg string.
2938 if (ConfigAccess
!= NULL
) {
2939 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2940 if (!EFI_ERROR (Status
)) {
2946 // EFI_IFR_DEFAULT has highest priority
2948 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2949 Link
= GetFirstNode (&Question
->DefaultListHead
);
2950 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2951 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2953 if (Default
->DefaultId
== DefaultId
) {
2954 if (Default
->ValueExpression
!= NULL
) {
2956 // Default is provided by an Expression, evaluate it
2958 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2959 if (EFI_ERROR (Status
)) {
2963 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
2964 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
2965 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
2966 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
2967 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
2969 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
2970 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
2972 FreePool (Default
->ValueExpression
->Result
.Buffer
);
2974 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
2975 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2978 // Default value is embedded in EFI_IFR_DEFAULT
2980 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2983 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2984 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
2985 if (StrValue
== NULL
) {
2986 return EFI_NOT_FOUND
;
2988 if (Question
->StorageWidth
> StrSize (StrValue
)) {
2989 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
2991 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
2998 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3003 // EFI_ONE_OF_OPTION
3005 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3006 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3008 // OneOfOption could only provide Standard and Manufacturing default
3010 Link
= GetFirstNode (&Question
->OptionListHead
);
3011 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3012 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3013 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3015 if ((Option
->SuppressExpression
!= NULL
) &&
3016 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3020 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3021 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3023 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3032 // EFI_IFR_CHECKBOX - lowest priority
3034 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3035 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3037 // Checkbox could only provide Standard and Manufacturing default
3039 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3040 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3042 HiiValue
->Value
.b
= TRUE
;
3044 HiiValue
->Value
.b
= FALSE
;
3052 // For Questions without default
3054 Status
= EFI_NOT_FOUND
;
3055 switch (Question
->Operand
) {
3056 case EFI_IFR_NUMERIC_OP
:
3058 // Take minimum value as numeric default value
3060 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3061 HiiValue
->Value
.u64
= Question
->Minimum
;
3062 Status
= EFI_SUCCESS
;
3066 case EFI_IFR_ONE_OF_OP
:
3068 // Take first oneof option as oneof's default value
3070 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3071 Link
= GetFirstNode (&Question
->OptionListHead
);
3072 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3073 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3074 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3076 if ((Option
->SuppressExpression
!= NULL
) &&
3077 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3081 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3082 Status
= EFI_SUCCESS
;
3088 case EFI_IFR_ORDERED_LIST_OP
:
3090 // Take option sequence in IFR as ordered list's default value
3093 Link
= GetFirstNode (&Question
->OptionListHead
);
3094 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3095 Status
= EFI_SUCCESS
;
3096 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3097 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3099 if ((Option
->SuppressExpression
!= NULL
) &&
3100 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3104 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3107 if (Index
>= Question
->MaxContainers
) {
3122 Reset Questions to their initial value or default value in a Form, Formset or System.
3124 GetDefaultValueScope parameter decides which questions will reset
3125 to its default value.
3127 @param FormSet FormSet data structure.
3128 @param Form Form data structure.
3129 @param DefaultId The Class of the default.
3130 @param SettingScope Setting Scope for Default action.
3131 @param GetDefaultValueScope Get default value scope.
3132 @param Storage Get default value only for this storage.
3133 @param RetrieveValueFirst Whether call the retrieve call back to
3134 get the initial value before get default
3137 @retval EFI_SUCCESS The function completed successfully.
3138 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3143 IN FORM_BROWSER_FORMSET
*FormSet
,
3144 IN FORM_BROWSER_FORM
*Form
,
3145 IN UINT16 DefaultId
,
3146 IN BROWSER_SETTING_SCOPE SettingScope
,
3147 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3148 IN FORMSET_STORAGE
*Storage OPTIONAL
,
3149 IN BOOLEAN RetrieveValueFirst
3153 LIST_ENTRY
*FormLink
;
3155 FORM_BROWSER_STATEMENT
*Question
;
3156 FORM_BROWSER_FORMSET
*BackUpFormSet
;
3157 FORM_BROWSER_FORMSET
*LocalFormSet
;
3158 EFI_HII_HANDLE
*HiiHandles
;
3162 Status
= EFI_SUCCESS
;
3165 // Check the supported setting level.
3167 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3168 return EFI_UNSUPPORTED
;
3171 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3172 return EFI_UNSUPPORTED
;
3175 if (SettingScope
== FormLevel
) {
3177 // Extract Form default
3179 Link
= GetFirstNode (&Form
->StatementListHead
);
3180 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3181 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3182 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3185 // If get default value only for this storage, check the storage first.
3187 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3192 // If get default value only for no storage question, just skip the question which has storage.
3194 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3199 // If Question is disabled, don't reset it to default
3201 if (Question
->Expression
!= NULL
) {
3202 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3207 if (RetrieveValueFirst
) {
3209 // Call the Retrieve call back to get the initial question value.
3211 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3215 // If not request to get the initial value or get initial value fail, then get default value.
3217 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3218 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3219 if (EFI_ERROR (Status
)) {
3225 // Synchronize Buffer storage's Edit buffer
3227 if ((Question
->Storage
!= NULL
) &&
3228 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3229 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3231 // Update Form NV flag.
3233 Form
->NvUpdateRequired
= TRUE
;
3236 } else if (SettingScope
== FormSetLevel
) {
3237 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3238 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3239 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3240 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3241 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3243 } else if (SettingScope
== SystemLevel
) {
3245 // Open all FormSet by locate HII packages.
3246 // Initiliaze the maintain FormSet to store default data as back up data.
3248 BackUpFormSet
= gOldFormSet
;
3252 // Get all the Hii handles
3254 HiiHandles
= HiiGetHiiHandles (NULL
);
3255 ASSERT (HiiHandles
!= NULL
);
3258 // Search for formset of each class type
3260 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3262 // Check HiiHandles[Index] does exist in global maintain list.
3264 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3269 // Initilize FormSet Setting
3271 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3272 ASSERT (LocalFormSet
!= NULL
);
3273 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3274 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
, FALSE
);
3275 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3276 DestroyFormSet (LocalFormSet
);
3279 Status
= InitializeCurrentSetting (LocalFormSet
);
3280 if (EFI_ERROR (Status
)) {
3281 DestroyFormSet (LocalFormSet
);
3285 // Initilize Questions' Value
3287 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
3288 if (EFI_ERROR (Status
)) {
3289 DestroyFormSet (LocalFormSet
);
3294 // Add FormSet into the maintain list.
3296 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3300 // Free resources, and restore gOldFormSet and gClassOfVfr
3302 FreePool (HiiHandles
);
3303 gOldFormSet
= BackUpFormSet
;
3306 // Set Default Value for each FormSet in the maintain list.
3308 Link
= GetFirstNode (&gBrowserFormSetList
);
3309 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3310 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3311 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3312 if (!ValidateFormSet(LocalFormSet
)) {
3315 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3323 Initialize Question's Edit copy from Storage.
3325 @param Selection Selection contains the information about
3326 the Selection, form and formset to be displayed.
3327 Selection action may be updated in retrieve callback.
3328 If Selection is NULL, only initialize Question value.
3329 @param FormSet FormSet data structure.
3330 @param Form Form data structure.
3332 @retval EFI_SUCCESS The function completed successfully.
3337 IN OUT UI_MENU_SELECTION
*Selection
,
3338 IN FORM_BROWSER_FORMSET
*FormSet
,
3339 IN FORM_BROWSER_FORM
*Form
3344 FORM_BROWSER_STATEMENT
*Question
;
3348 Link
= GetFirstNode (&Form
->StatementListHead
);
3349 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3350 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3353 // Initialize local copy of Value for each Question
3355 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3356 if (EFI_ERROR (Status
)) {
3360 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3361 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3365 // Call the Retrieve call back function for all questions.
3367 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3368 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3370 // Check QuestionValue does exist.
3372 StorageWidth
= Question
->StorageWidth
;
3373 if (Question
->BufferValue
!= NULL
) {
3374 BufferValue
= Question
->BufferValue
;
3376 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3380 // For efivarstore storage, initial question value first.
3382 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3383 Status
= gRT
->GetVariable (
3384 Question
->VariableName
,
3385 &Question
->Storage
->Guid
,
3392 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3395 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3402 Initialize Question's Edit copy from Storage for the whole Formset.
3404 @param Selection Selection contains the information about
3405 the Selection, form and formset to be displayed.
3406 Selection action may be updated in retrieve callback.
3407 If Selection is NULL, only initialize Question value.
3408 @param FormSet FormSet data structure.
3410 @retval EFI_SUCCESS The function completed successfully.
3415 IN OUT UI_MENU_SELECTION
*Selection
,
3416 IN FORM_BROWSER_FORMSET
*FormSet
3421 FORM_BROWSER_FORM
*Form
;
3423 Link
= GetFirstNode (&FormSet
->FormListHead
);
3424 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3425 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3428 // Initialize local copy of Value for each Form
3430 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3431 if (EFI_ERROR (Status
)) {
3435 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3442 Fill storage's edit copy with settings requested from Configuration Driver.
3444 @param FormSet FormSet data structure.
3445 @param Storage Buffer Storage.
3447 @retval EFI_SUCCESS The function completed successfully.
3452 IN FORM_BROWSER_FORMSET
*FormSet
,
3453 IN FORMSET_STORAGE
*Storage
3457 EFI_STRING Progress
;
3461 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3465 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3466 Status
= gRT
->GetVariable (
3470 (UINTN
*)&Storage
->Size
,
3476 if (FormSet
->ConfigAccess
== NULL
) {
3477 return EFI_NOT_FOUND
;
3480 if (Storage
->ElementCount
== 0) {
3482 // Skip if there is no RequestElement
3488 // Request current settings from Configuration Driver
3490 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3491 FormSet
->ConfigAccess
,
3492 Storage
->ConfigRequest
,
3496 if (EFI_ERROR (Status
)) {
3501 // Convert Result from <ConfigAltResp> to <ConfigResp>
3503 StrPtr
= StrStr (Result
, L
"&GUID=");
3504 if (StrPtr
!= NULL
) {
3508 Status
= ConfigRespToStorage (Storage
, Result
);
3515 Copy uncommitted data from source Storage to destination Storage.
3517 @param Dst Target Storage for uncommitted data.
3518 @param Src Source Storage for uncommitted data.
3520 @retval EFI_SUCCESS The function completed successfully.
3521 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
3526 IN OUT FORMSET_STORAGE
*Dst
,
3527 IN FORMSET_STORAGE
*Src
3531 NAME_VALUE_NODE
*Node
;
3533 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
3534 return EFI_INVALID_PARAMETER
;
3537 switch (Src
->Type
) {
3538 case EFI_HII_VARSTORE_BUFFER
:
3539 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3540 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
3541 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
3544 case EFI_HII_VARSTORE_NAME_VALUE
:
3545 Link
= GetFirstNode (&Src
->NameValueListHead
);
3546 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
3547 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3549 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, GetSetValueWithEditBuffer
);
3550 SetValueByName (Dst
, Node
->Name
, Node
->Value
, GetSetValueWithBuffer
);
3552 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
3556 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3565 Get old question value from the saved formset.
3567 @param Statement The question which need to get old question value.
3568 @param OldFormSet FormSet data structure saved in the list.
3572 GetOldQuestionValue (
3573 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
3574 IN FORM_BROWSER_FORMSET
*OldFormSet
3577 LIST_ENTRY
*FormLink
;
3579 FORM_BROWSER_STATEMENT
*Question
;
3580 FORM_BROWSER_FORM
*Form
;
3582 FormLink
= GetFirstNode (&OldFormSet
->FormListHead
);
3583 while (!IsNull (&OldFormSet
->FormListHead
, FormLink
)) {
3584 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3585 FormLink
= GetNextNode (&OldFormSet
->FormListHead
, FormLink
);
3587 Link
= GetFirstNode (&Form
->StatementListHead
);
3588 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3589 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3590 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3592 if (Question
->QuestionId
!= Statement
->QuestionId
) {
3596 CopyMem (&Statement
->HiiValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3603 Get old question value from the saved formset, all these questions not have
3606 @param FormSet FormSet data structure which is used now.
3607 @param OldFormSet FormSet data structure saved in the list.
3611 CopyOldValueForNoStorageQst (
3612 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
3613 IN FORM_BROWSER_FORMSET
*OldFormSet
3616 LIST_ENTRY
*FormLink
;
3618 FORM_BROWSER_STATEMENT
*Question
;
3619 FORM_BROWSER_FORM
*Form
;
3621 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3622 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3623 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3624 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3626 Link
= GetFirstNode (&Form
->StatementListHead
);
3627 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3628 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3629 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3631 if (Question
->Storage
== NULL
) {
3632 GetOldQuestionValue (Question
, OldFormSet
);
3639 Get current setting of Questions.
3641 @param FormSet FormSet data structure.
3643 @retval EFI_SUCCESS The function completed successfully.
3647 InitializeCurrentSetting (
3648 IN OUT FORM_BROWSER_FORMSET
*FormSet
3653 FORMSET_STORAGE
*Storage
;
3654 FORMSET_STORAGE
*StorageSrc
;
3655 FORMSET_STORAGE
*OldStorage
;
3656 FORM_BROWSER_FORM
*Form
;
3657 FORM_BROWSER_FORM
*Form2
;
3661 // Extract default from IFR binary for no storage questions.
3663 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
3666 // Request current settings from Configuration Driver
3668 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3669 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3670 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3673 if (gOldFormSet
!= NULL
) {
3675 // Try to find the Storage in backup formset gOldFormSet
3677 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3678 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3679 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3681 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3682 OldStorage
= StorageSrc
;
3686 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3690 if (OldStorage
== NULL
) {
3692 // Storage is not found in backup formset, request it from ConfigDriver
3694 Status
= LoadStorage (FormSet
, Storage
);
3696 if (EFI_ERROR (Status
)) {
3698 // If get last time changed value failed, extract default from IFR binary
3700 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3702 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3703 // in current situation.
3705 UpdateNvInfoInForm (FormSet
, FALSE
);
3709 // Now Edit Buffer is filled with default values(lower priority) or current
3710 // settings(higher priority), sychronize it to shadow Buffer
3712 SynchronizeStorage (Storage
, TRUE
);
3715 // Storage found in backup formset, use it
3717 Status
= CopyStorage (Storage
, OldStorage
);
3720 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3724 // If has old formset, get the old nv update status.
3726 if (gOldFormSet
!= NULL
) {
3727 Link
= GetFirstNode (&FormSet
->FormListHead
);
3728 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3729 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3731 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3732 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3733 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3735 if (Form
->FormId
== Form2
->FormId
) {
3736 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3740 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3742 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3751 Fetch the Ifr binary data of a FormSet.
3753 @param Handle PackageList Handle
3754 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3755 specified (NULL or zero GUID), take the first
3756 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3757 found in package list.
3758 On output, GUID of the formset found(if not NULL).
3759 @param BinaryLength The length of the FormSet IFR binary.
3760 @param BinaryData The buffer designed to receive the FormSet.
3762 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3763 BufferLength was updated.
3764 @retval EFI_INVALID_PARAMETER The handle is unknown.
3765 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3766 be found with the requested FormId.
3771 IN EFI_HII_HANDLE Handle
,
3772 IN OUT EFI_GUID
*FormSetGuid
,
3773 OUT UINTN
*BinaryLength
,
3774 OUT UINT8
**BinaryData
3778 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3784 UINT32 PackageListLength
;
3785 EFI_HII_PACKAGE_HEADER PackageHeader
;
3787 UINT8 NumberOfClassGuid
;
3788 BOOLEAN ClassGuidMatch
;
3789 EFI_GUID
*ClassGuid
;
3790 EFI_GUID
*ComparingGuid
;
3794 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3797 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3799 if (FormSetGuid
== NULL
) {
3800 ComparingGuid
= &gZeroGuid
;
3802 ComparingGuid
= FormSetGuid
;
3806 // Get HII PackageList
3809 HiiPackageList
= NULL
;
3810 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3811 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3812 HiiPackageList
= AllocatePool (BufferSize
);
3813 ASSERT (HiiPackageList
!= NULL
);
3815 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3817 if (EFI_ERROR (Status
)) {
3820 ASSERT (HiiPackageList
!= NULL
);
3823 // Get Form package from this HII package List
3825 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3827 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3829 ClassGuidMatch
= FALSE
;
3830 while (Offset
< PackageListLength
) {
3831 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3832 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3834 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3836 // Search FormSet in this Form Package
3838 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3839 while (Offset2
< PackageHeader
.Length
) {
3840 OpCodeData
= Package
+ Offset2
;
3842 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3844 // Try to compare against formset GUID
3846 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3847 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3851 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3853 // Try to compare against formset class GUID
3855 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3856 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3857 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3858 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3859 ClassGuidMatch
= TRUE
;
3863 if (ClassGuidMatch
) {
3866 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3867 ClassGuidMatch
= TRUE
;
3872 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3875 if (Offset2
< PackageHeader
.Length
) {
3877 // Target formset found
3883 Offset
+= PackageHeader
.Length
;
3886 if (Offset
>= PackageListLength
) {
3888 // Form package not found in this Package List
3890 FreePool (HiiPackageList
);
3891 return EFI_NOT_FOUND
;
3894 if (FormSetGuid
!= NULL
) {
3896 // Return the FormSet GUID
3898 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3902 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3903 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3904 // of the Form Package.
3906 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3907 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3909 FreePool (HiiPackageList
);
3911 if (*BinaryData
== NULL
) {
3912 return EFI_OUT_OF_RESOURCES
;
3920 Initialize the internal data structure of a FormSet.
3922 @param Handle PackageList Handle
3923 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3924 specified (NULL or zero GUID), take the first
3925 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3926 found in package list.
3927 On output, GUID of the formset found(if not NULL).
3928 @param FormSet FormSet data structure.
3929 @param UpdateGlobalVar Whether need to update the global variable.
3931 @retval EFI_SUCCESS The function completed successfully.
3932 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3937 IN EFI_HII_HANDLE Handle
,
3938 IN OUT EFI_GUID
*FormSetGuid
,
3939 OUT FORM_BROWSER_FORMSET
*FormSet
,
3940 IN BOOLEAN UpdateGlobalVar
3944 EFI_HANDLE DriverHandle
;
3947 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3948 if (EFI_ERROR (Status
)) {
3952 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3953 FormSet
->HiiHandle
= Handle
;
3954 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3957 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3959 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3960 if (EFI_ERROR (Status
)) {
3963 FormSet
->DriverHandle
= DriverHandle
;
3964 Status
= gBS
->HandleProtocol (
3966 &gEfiHiiConfigAccessProtocolGuid
,
3967 (VOID
**) &FormSet
->ConfigAccess
3969 if (EFI_ERROR (Status
)) {
3971 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3972 // list, then there will be no configuration action required
3974 FormSet
->ConfigAccess
= NULL
;
3978 // Parse the IFR binary OpCodes
3980 Status
= ParseOpCodes (FormSet
);
3981 if (EFI_ERROR (Status
)) {
3986 // If not need to update the global variable, just return.
3988 if (!UpdateGlobalVar
) {
3993 // Set VFR type by FormSet SubClass field
3995 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
3996 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
3997 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
4001 // Set VFR type by FormSet class guid
4003 for (Index
= 0; Index
< 3; Index
++) {
4004 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
4005 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
4010 gFunctionKeySetting
= ENABLE_FUNCTION_KEY_SETTING
;
4012 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
4013 gFrontPageHandle
= FormSet
->HiiHandle
;
4014 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
4018 // Match GUID to find out the function key setting. If match fail, use the default setting.
4020 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
4021 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
4023 // Update the function key setting.
4025 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
4034 Save globals used by previous call to SendForm(). SendForm() may be called from
4035 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4036 So, save globals of previous call to SendForm() and restore them upon exit.
4040 SaveBrowserContext (
4044 BROWSER_CONTEXT
*Context
;
4046 gBrowserContextCount
++;
4047 if (gBrowserContextCount
== 1) {
4049 // This is not reentry of SendForm(), no context to save
4054 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4055 ASSERT (Context
!= NULL
);
4057 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4060 // Save FormBrowser context
4062 Context
->BannerData
= gBannerData
;
4063 Context
->ClassOfVfr
= gClassOfVfr
;
4064 Context
->FunctionKeySetting
= gFunctionKeySetting
;
4065 Context
->ResetRequired
= gResetRequired
;
4066 Context
->Direction
= gDirection
;
4067 Context
->EnterString
= gEnterString
;
4068 Context
->EnterCommitString
= gEnterCommitString
;
4069 Context
->EnterEscapeString
= gEnterEscapeString
;
4070 Context
->EscapeString
= gEscapeString
;
4071 Context
->MoveHighlight
= gMoveHighlight
;
4072 Context
->MakeSelection
= gMakeSelection
;
4073 Context
->DecNumericInput
= gDecNumericInput
;
4074 Context
->HexNumericInput
= gHexNumericInput
;
4075 Context
->ToggleCheckBox
= gToggleCheckBox
;
4076 Context
->PromptForData
= gPromptForData
;
4077 Context
->PromptForPassword
= gPromptForPassword
;
4078 Context
->PromptForNewPassword
= gPromptForNewPassword
;
4079 Context
->ConfirmPassword
= gConfirmPassword
;
4080 Context
->ConfirmError
= gConfirmError
;
4081 Context
->PassowordInvalid
= gPassowordInvalid
;
4082 Context
->PressEnter
= gPressEnter
;
4083 Context
->EmptyString
= gEmptyString
;
4084 Context
->AreYouSure
= gAreYouSure
;
4085 Context
->YesResponse
= gYesResponse
;
4086 Context
->NoResponse
= gNoResponse
;
4087 Context
->MiniString
= gMiniString
;
4088 Context
->PlusString
= gPlusString
;
4089 Context
->MinusString
= gMinusString
;
4090 Context
->AdjustNumber
= gAdjustNumber
;
4091 Context
->SaveChanges
= gSaveChanges
;
4092 Context
->OptionMismatch
= gOptionMismatch
;
4093 Context
->FormSuppress
= gFormSuppress
;
4094 Context
->PromptBlockWidth
= gPromptBlockWidth
;
4095 Context
->OptionBlockWidth
= gOptionBlockWidth
;
4096 Context
->HelpBlockWidth
= gHelpBlockWidth
;
4097 Context
->OldFormSet
= gOldFormSet
;
4098 Context
->MenuRefreshHead
= gMenuRefreshHead
;
4099 Context
->ProtocolNotFound
= gProtocolNotFound
;
4101 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
4102 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
4105 // Insert to FormBrowser context list
4107 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4112 Restore globals used by previous call to SendForm().
4116 RestoreBrowserContext (
4121 BROWSER_CONTEXT
*Context
;
4123 ASSERT (gBrowserContextCount
!= 0);
4124 gBrowserContextCount
--;
4125 if (gBrowserContextCount
== 0) {
4127 // This is not reentry of SendForm(), no context to restore
4132 ASSERT (!IsListEmpty (&gBrowserContextList
));
4134 Link
= GetFirstNode (&gBrowserContextList
);
4135 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4138 // Restore FormBrowser context
4140 gBannerData
= Context
->BannerData
;
4141 gClassOfVfr
= Context
->ClassOfVfr
;
4142 gFunctionKeySetting
= Context
->FunctionKeySetting
;
4143 gResetRequired
= Context
->ResetRequired
;
4144 gDirection
= Context
->Direction
;
4145 gEnterString
= Context
->EnterString
;
4146 gEnterCommitString
= Context
->EnterCommitString
;
4147 gEnterEscapeString
= Context
->EnterEscapeString
;
4148 gEscapeString
= Context
->EscapeString
;
4149 gMoveHighlight
= Context
->MoveHighlight
;
4150 gMakeSelection
= Context
->MakeSelection
;
4151 gDecNumericInput
= Context
->DecNumericInput
;
4152 gHexNumericInput
= Context
->HexNumericInput
;
4153 gToggleCheckBox
= Context
->ToggleCheckBox
;
4154 gPromptForData
= Context
->PromptForData
;
4155 gPromptForPassword
= Context
->PromptForPassword
;
4156 gPromptForNewPassword
= Context
->PromptForNewPassword
;
4157 gConfirmPassword
= Context
->ConfirmPassword
;
4158 gConfirmError
= Context
->ConfirmError
;
4159 gPassowordInvalid
= Context
->PassowordInvalid
;
4160 gPressEnter
= Context
->PressEnter
;
4161 gEmptyString
= Context
->EmptyString
;
4162 gAreYouSure
= Context
->AreYouSure
;
4163 gYesResponse
= Context
->YesResponse
;
4164 gNoResponse
= Context
->NoResponse
;
4165 gMiniString
= Context
->MiniString
;
4166 gPlusString
= Context
->PlusString
;
4167 gMinusString
= Context
->MinusString
;
4168 gAdjustNumber
= Context
->AdjustNumber
;
4169 gSaveChanges
= Context
->SaveChanges
;
4170 gOptionMismatch
= Context
->OptionMismatch
;
4171 gFormSuppress
= Context
->FormSuppress
;
4172 gPromptBlockWidth
= Context
->PromptBlockWidth
;
4173 gOptionBlockWidth
= Context
->OptionBlockWidth
;
4174 gHelpBlockWidth
= Context
->HelpBlockWidth
;
4175 gOldFormSet
= Context
->OldFormSet
;
4176 gMenuRefreshHead
= Context
->MenuRefreshHead
;
4177 gProtocolNotFound
= Context
->ProtocolNotFound
;
4179 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
4180 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
4183 // Remove from FormBrowser context list
4185 RemoveEntryList (&Context
->Link
);
4186 gBS
->FreePool (Context
);
4190 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4192 @param Handle The Hii Handle.
4194 @return the found FormSet context. If no found, NULL will return.
4197 FORM_BROWSER_FORMSET
*
4198 GetFormSetFromHiiHandle (
4199 EFI_HII_HANDLE Handle
4203 FORM_BROWSER_FORMSET
*FormSet
;
4205 Link
= GetFirstNode (&gBrowserFormSetList
);
4206 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4207 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4208 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4209 if (!ValidateFormSet(FormSet
)) {
4212 if (FormSet
->HiiHandle
== Handle
) {
4221 Check whether the input HII handle is the FormSet that is being used.
4223 @param Handle The Hii Handle.
4225 @retval TRUE HII handle is being used.
4226 @retval FALSE HII handle is not being used.
4230 IsHiiHandleInBrowserContext (
4231 EFI_HII_HANDLE Handle
4235 BROWSER_CONTEXT
*Context
;
4238 // HiiHandle is Current FormSet.
4240 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
4245 // Check whether HiiHandle is in BrowserContext.
4247 Link
= GetFirstNode (&gBrowserContextList
);
4248 while (!IsNull (&gBrowserContextList
, Link
)) {
4249 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4250 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
4252 // HiiHandle is in BrowserContext
4256 Link
= GetNextNode (&gBrowserContextList
, Link
);
4263 Find the registered HotKey based on KeyData.
4265 @param[in] KeyData A pointer to a buffer that describes the keystroke
4266 information for the hot key.
4268 @return The registered HotKey context. If no found, NULL will return.
4271 GetHotKeyFromRegisterList (
4272 IN EFI_INPUT_KEY
*KeyData
4276 BROWSER_HOT_KEY
*HotKey
;
4278 Link
= GetFirstNode (&gBrowserHotKeyList
);
4279 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4280 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4281 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4284 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4291 Configure what scope the hot key will impact.
4292 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4293 If no scope is set, the default scope will be FormSet level.
4294 After all registered hot keys are removed, previous Scope can reset to another level.
4296 @param[in] Scope Scope level to be set.
4298 @retval EFI_SUCCESS Scope is set correctly.
4299 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4300 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4306 IN BROWSER_SETTING_SCOPE Scope
4309 if (Scope
>= MaxLevel
) {
4310 return EFI_INVALID_PARAMETER
;
4314 // When no hot key registered in system or on the first setting,
4315 // Scope can be set.
4317 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4318 gBrowserSettingScope
= Scope
;
4319 mBrowserScopeFirstSet
= FALSE
;
4320 } else if (Scope
!= gBrowserSettingScope
) {
4321 return EFI_UNSUPPORTED
;
4328 Register the hot key with its browser action, or unregistered the hot key.
4329 Only support hot key that is not printable character (control key, function key, etc.).
4330 If the action value is zero, the hot key will be unregistered if it has been registered.
4331 If the same hot key has been registered, the new action and help string will override the previous ones.
4333 @param[in] KeyData A pointer to a buffer that describes the keystroke
4334 information for the hot key. Its type is EFI_INPUT_KEY to
4335 be supported by all ConsoleIn devices.
4336 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4337 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4338 @param[in] HelpString Help string that describes the hot key information.
4339 Its value may be NULL for the unregistered hot key.
4341 @retval EFI_SUCCESS Hot key is registered or unregistered.
4342 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4343 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4344 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4349 IN EFI_INPUT_KEY
*KeyData
,
4351 IN UINT16 DefaultId
,
4352 IN EFI_STRING HelpString OPTIONAL
4355 BROWSER_HOT_KEY
*HotKey
;
4358 // Check input parameters.
4360 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4361 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4362 return EFI_INVALID_PARAMETER
;
4366 // Check whether the input KeyData is in BrowserHotKeyList.
4368 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4371 // Unregister HotKey
4373 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4374 if (HotKey
!= NULL
) {
4376 // The registered HotKey is found.
4377 // Remove it from List, and free its resource.
4379 RemoveEntryList (&HotKey
->Link
);
4380 FreePool (HotKey
->KeyData
);
4381 FreePool (HotKey
->HelpString
);
4385 // The registered HotKey is not found.
4387 return EFI_NOT_FOUND
;
4392 // Register HotKey into List.
4394 if (HotKey
== NULL
) {
4396 // Create new Key, and add it into List.
4398 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4399 ASSERT (HotKey
!= NULL
);
4400 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4401 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4402 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4406 // Fill HotKey information.
4408 HotKey
->Action
= Action
;
4409 HotKey
->DefaultId
= DefaultId
;
4410 if (HotKey
->HelpString
!= NULL
) {
4411 FreePool (HotKey
->HelpString
);
4413 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4419 Register Exit handler function.
4420 When more than one handler function is registered, the latter one will override the previous one.
4421 When NULL handler is specified, the previous Exit handler will be unregistered.
4423 @param[in] Handler Pointer to handler function.
4428 RegiserExitHandler (
4429 IN EXIT_HANDLER Handler
4432 ExitHandlerFunction
= Handler
;
4437 Create reminder to let user to choose save or discard the changed browser data.
4438 Caller can use it to actively check the changed browser data.
4440 @retval BROWSER_NO_CHANGES No browser data is changed.
4441 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4442 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4452 FORM_BROWSER_FORMSET
*FormSet
;
4453 BOOLEAN IsDataChanged
;
4454 UINT32 DataSavedAction
;
4455 CHAR16
*YesResponse
;
4457 CHAR16
*EmptyString
;
4458 CHAR16
*ChangeReminderString
;
4459 CHAR16
*SaveConfirmString
;
4462 DataSavedAction
= BROWSER_NO_CHANGES
;
4463 IsDataChanged
= FALSE
;
4464 Link
= GetFirstNode (&gBrowserFormSetList
);
4465 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4466 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4467 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4468 if (!ValidateFormSet(FormSet
)) {
4471 if (IsNvUpdateRequired (FormSet
)) {
4472 IsDataChanged
= TRUE
;
4478 // No data is changed. No save is required.
4480 if (!IsDataChanged
) {
4481 return DataSavedAction
;
4485 // If data is changed, prompt user
4487 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4489 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4490 ASSERT (YesResponse
!= NULL
);
4491 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4492 ASSERT (NoResponse
!= NULL
);
4493 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4494 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4495 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4498 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4500 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4501 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4505 // If the user hits the YesResponse key
4507 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4508 SubmitForm (NULL
, NULL
, SystemLevel
);
4509 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4511 DiscardForm (NULL
, NULL
, SystemLevel
);
4512 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4513 gResetRequired
= FALSE
;
4516 FreePool (YesResponse
);
4517 FreePool (NoResponse
);
4518 FreePool (EmptyString
);
4519 FreePool (SaveConfirmString
);
4520 FreePool (ChangeReminderString
);
4522 return DataSavedAction
;