2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
32 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
33 EFI_HII_STRING_PROTOCOL
*mHiiString
;
34 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
35 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
37 UINTN gBrowserContextCount
= 0;
38 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
39 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
40 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
42 BANNER_DATA
*gBannerData
;
43 EFI_HII_HANDLE gFrontPageHandle
;
45 UINTN gFunctionKeySetting
;
46 BOOLEAN gResetRequired
;
47 EFI_HII_HANDLE gHiiHandle
;
49 EFI_SCREEN_DESCRIPTOR gScreenDimensions
;
50 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
51 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
52 EXIT_HANDLER ExitHandlerFunction
= NULL
;
56 // Browser Global Strings
59 CHAR16
*gDiscardFailed
;
60 CHAR16
*gDefaultFailed
;
62 CHAR16
*gEnterCommitString
;
63 CHAR16
*gEnterEscapeString
;
64 CHAR16
*gEscapeString
;
65 CHAR16
*gMoveHighlight
;
66 CHAR16
*gMakeSelection
;
67 CHAR16
*gDecNumericInput
;
68 CHAR16
*gHexNumericInput
;
69 CHAR16
*gToggleCheckBox
;
70 CHAR16
*gPromptForData
;
71 CHAR16
*gPromptForPassword
;
72 CHAR16
*gPromptForNewPassword
;
73 CHAR16
*gConfirmPassword
;
74 CHAR16
*gConfirmError
;
75 CHAR16
*gPassowordInvalid
;
84 CHAR16
*gAdjustNumber
;
86 CHAR16
*gOptionMismatch
;
87 CHAR16
*gFormSuppress
;
88 CHAR16
*gProtocolNotFound
;
90 CHAR16
*mUnknownString
= L
"!";
92 CHAR16 gPromptBlockWidth
;
93 CHAR16 gOptionBlockWidth
;
94 CHAR16 gHelpBlockWidth
;
96 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
97 EFI_GUID gSetupBrowserGuid
= {
98 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
101 FORM_BROWSER_FORMSET
*gOldFormSet
= NULL
;
103 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
123 NONE_FUNCTION_KEY_SETTING
144 NONE_FUNCTION_KEY_SETTING
165 NONE_FUNCTION_KEY_SETTING
168 // BMM File Explorer FormSet.
186 NONE_FUNCTION_KEY_SETTING
191 This is the routine which an external caller uses to direct the browser
192 where to obtain it's information.
195 @param This The Form Browser protocol instanse.
196 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
197 display a list of the formsets for the handles specified.
198 @param HandleCount The number of Handles specified in Handle.
199 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
200 field in the EFI_IFR_FORM_SET op-code for the specified
201 forms-based package. If FormSetGuid is NULL, then this
202 function will display the first found forms package.
203 @param FormId This field specifies which EFI_IFR_FORM to render as the first
204 displayable page. If this field has a value of 0x0000, then
205 the forms browser will render the specified forms in their encoded order.
206 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
208 @param ActionRequest Points to the action recommended by the form.
210 @retval EFI_SUCCESS The function completed successfully.
211 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
212 @retval EFI_NOT_FOUND No valid forms could be found to display.
218 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
219 IN EFI_HII_HANDLE
*Handles
,
220 IN UINTN HandleCount
,
221 IN EFI_GUID
*FormSetGuid
, OPTIONAL
222 IN UINT16 FormId
, OPTIONAL
223 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
224 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
228 UI_MENU_SELECTION
*Selection
;
230 FORM_BROWSER_FORMSET
*FormSet
;
234 // Calculate total number of Register HotKeys.
237 Link
= GetFirstNode (&gBrowserHotKeyList
);
238 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
239 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
243 // Show three HotKeys help information on one ROW.
245 gFooterHeight
= FOOTER_HEIGHT
+ (Index
/ 3);
248 // Save globals used by SendForm()
250 SaveBrowserContext ();
252 gResetRequired
= FALSE
;
253 Status
= EFI_SUCCESS
;
254 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
257 // Seed the dimensions in the global
259 gST
->ConOut
->QueryMode (
261 gST
->ConOut
->Mode
->Mode
,
262 &gScreenDimensions
.RightColumn
,
263 &gScreenDimensions
.BottomRow
266 if (ScreenDimensions
!= NULL
) {
268 // Check local dimension vs. global dimension.
270 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
271 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
273 Status
= EFI_INVALID_PARAMETER
;
277 // Local dimension validation.
279 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
280 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
281 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
283 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
284 SCROLL_ARROW_HEIGHT
*
286 FRONT_PAGE_HEADER_HEIGHT
+
291 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
293 Status
= EFI_INVALID_PARAMETER
;
299 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
300 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
301 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
304 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
306 InitializeBrowserStrings ();
308 gFunctionKeySetting
= ENABLE_FUNCTION_KEY_SETTING
;
311 // Ensure we are in Text mode
313 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
315 for (Index
= 0; Index
< HandleCount
; Index
++) {
316 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
317 ASSERT (Selection
!= NULL
);
319 Selection
->Handle
= Handles
[Index
];
320 if (FormSetGuid
!= NULL
) {
321 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
322 Selection
->FormId
= FormId
;
324 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
328 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
329 ASSERT (FormSet
!= NULL
);
332 // Initialize internal data structures of FormSet
334 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
, TRUE
);
335 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
336 DestroyFormSet (FormSet
);
339 Selection
->FormSet
= FormSet
;
342 // Try to find pre FormSet in the maintain backup list.
344 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
347 // Display this formset
349 gCurrentSelection
= Selection
;
351 Status
= SetupBrowser (Selection
);
353 gCurrentSelection
= NULL
;
355 if (EFI_ERROR (Status
)) {
359 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
361 if (gOldFormSet
!= NULL
) {
363 // If no data is changed, don't need to save current FormSet into the maintain list.
365 if (!IsNvUpdateRequired (gOldFormSet
)) {
366 RemoveEntryList (&gOldFormSet
->Link
);
367 DestroyFormSet (gOldFormSet
);
372 FreePool (Selection
);
375 if (ActionRequest
!= NULL
) {
376 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
377 if (gResetRequired
) {
378 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
382 FreeBrowserStrings ();
384 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
385 gST
->ConOut
->ClearScreen (gST
->ConOut
);
389 // Restore globals used by SendForm()
391 RestoreBrowserContext ();
398 This function is called by a callback handler to retrieve uncommitted state
399 data from the browser.
401 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
403 @param ResultsDataSize A pointer to the size of the buffer associated
405 @param ResultsData A string returned from an IFR browser or
406 equivalent. The results string will have no
407 routing information in them.
408 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
409 (if RetrieveData = TRUE) data from the uncommitted
410 browser state information or set (if RetrieveData
411 = FALSE) data in the uncommitted browser state
413 @param VariableGuid An optional field to indicate the target variable
415 @param VariableName An optional field to indicate the target
416 human-readable variable name.
418 @retval EFI_SUCCESS The results have been distributed or are awaiting
420 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
421 contain the results data.
427 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
428 IN OUT UINTN
*ResultsDataSize
,
429 IN OUT EFI_STRING ResultsData
,
430 IN BOOLEAN RetrieveData
,
431 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
432 IN CONST CHAR16
*VariableName OPTIONAL
437 FORMSET_STORAGE
*Storage
;
438 FORM_BROWSER_FORMSET
*FormSet
;
445 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
446 return EFI_INVALID_PARAMETER
;
449 if (gCurrentSelection
== NULL
) {
450 return EFI_NOT_READY
;
455 FormSet
= gCurrentSelection
->FormSet
;
458 // Find target storage
460 Link
= GetFirstNode (&FormSet
->StorageListHead
);
461 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
462 return EFI_UNSUPPORTED
;
465 if (VariableGuid
!= NULL
) {
467 // Try to find target storage
470 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
471 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
472 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
474 if (CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
475 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
476 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
478 // Buffer storage require both GUID and Name
480 if (VariableName
== NULL
) {
481 return EFI_NOT_FOUND
;
484 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
494 return EFI_NOT_FOUND
;
498 // GUID/Name is not specified, take the first storage in FormSet
500 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
505 // Skip if there is no RequestElement
507 if (Storage
->ElementCount
== 0) {
512 // Generate <ConfigResp>
514 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
515 if (EFI_ERROR (Status
)) {
520 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
522 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
524 BufferSize
= StrSize (StrPtr
);
525 if (*ResultsDataSize
< BufferSize
) {
526 *ResultsDataSize
= BufferSize
;
528 FreePool (ConfigResp
);
529 return EFI_BUFFER_TOO_SMALL
;
532 *ResultsDataSize
= BufferSize
;
533 CopyMem (ResultsData
, StrPtr
, BufferSize
);
535 FreePool (ConfigResp
);
538 // Prepare <ConfigResp>
540 TmpSize
= StrLen (ResultsData
);
541 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
542 ConfigResp
= AllocateZeroPool (BufferSize
);
543 ASSERT (ConfigResp
!= NULL
);
545 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
546 StrCat (ConfigResp
, L
"&");
547 StrCat (ConfigResp
, ResultsData
);
550 // Update Browser uncommited data
552 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
553 if (EFI_ERROR (Status
)) {
562 Initialize Setup Browser driver.
564 @param ImageHandle The image handle.
565 @param SystemTable The system table.
567 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
568 @return Other value if failed to initialize the Setup Browser module.
574 IN EFI_HANDLE ImageHandle
,
575 IN EFI_SYSTEM_TABLE
*SystemTable
579 EFI_INPUT_KEY DefaultHotKey
;
580 EFI_STRING HelpString
;
583 // Locate required Hii relative protocols
585 Status
= gBS
->LocateProtocol (
586 &gEfiHiiDatabaseProtocolGuid
,
588 (VOID
**) &mHiiDatabase
590 ASSERT_EFI_ERROR (Status
);
592 Status
= gBS
->LocateProtocol (
593 &gEfiHiiStringProtocolGuid
,
595 (VOID
**) &mHiiString
597 ASSERT_EFI_ERROR (Status
);
599 Status
= gBS
->LocateProtocol (
600 &gEfiHiiConfigRoutingProtocolGuid
,
602 (VOID
**) &mHiiConfigRouting
604 ASSERT_EFI_ERROR (Status
);
606 Status
= gBS
->LocateProtocol (
607 &gEfiDevicePathFromTextProtocolGuid
,
609 (VOID
**) &mPathFromText
613 // Publish our HII data
615 gHiiHandle
= HiiAddPackages (
621 ASSERT (gHiiHandle
!= NULL
);
624 // Initialize Driver private data
626 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
627 ASSERT (gBannerData
!= NULL
);
630 // Initialize generic help strings.
632 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
633 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
634 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
637 // Install FormBrowser2 protocol
639 mPrivateData
.Handle
= NULL
;
640 Status
= gBS
->InstallProtocolInterface (
641 &mPrivateData
.Handle
,
642 &gEfiFormBrowser2ProtocolGuid
,
643 EFI_NATIVE_INTERFACE
,
644 &mPrivateData
.FormBrowser2
646 ASSERT_EFI_ERROR (Status
);
649 // Install default HotKey F10 for Save
651 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
652 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
653 DefaultHotKey
.ScanCode
= SCAN_F10
;
654 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
655 FreePool (HelpString
);
657 // Install default HotKey F9 for Reset To Defaults
659 DefaultHotKey
.ScanCode
= SCAN_F9
;
660 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
661 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
662 FreePool (HelpString
);
665 // Install FormBrowserEx protocol
667 mPrivateData
.Handle
= NULL
;
668 Status
= gBS
->InstallProtocolInterface (
669 &mPrivateData
.Handle
,
670 &gEfiFormBrowserExProtocolGuid
,
671 EFI_NATIVE_INTERFACE
,
672 &mPrivateData
.FormBrowserEx
674 ASSERT_EFI_ERROR (Status
);
681 Create a new string in HII Package List.
683 @param String The String to be added
684 @param HiiHandle The package list in the HII database to insert the
687 @return The output string.
693 IN EFI_HII_HANDLE HiiHandle
696 EFI_STRING_ID StringId
;
698 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
699 ASSERT (StringId
!= 0);
706 Delete a string from HII Package List.
708 @param StringId Id of the string in HII database.
709 @param HiiHandle The HII package list handle.
711 @retval EFI_SUCCESS The string was deleted successfully.
716 IN EFI_STRING_ID StringId
,
717 IN EFI_HII_HANDLE HiiHandle
722 NullChar
= CHAR_NULL
;
723 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
729 Get the string based on the StringId and HII Package List Handle.
731 @param Token The String's ID.
732 @param HiiHandle The package list in the HII database to search for
733 the specified string.
735 @return The output string.
740 IN EFI_STRING_ID Token
,
741 IN EFI_HII_HANDLE HiiHandle
746 if (HiiHandle
== NULL
) {
750 String
= HiiGetString (HiiHandle
, Token
, NULL
);
751 if (String
== NULL
) {
752 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
753 ASSERT (String
!= NULL
);
755 return (CHAR16
*) String
;
760 Allocate new memory and then copy the Unicode string Source to Destination.
762 @param Dest Location to copy string
763 @param Src String to copy
768 IN OUT CHAR16
**Dest
,
775 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
776 ASSERT (*Dest
!= NULL
);
781 Allocate new memory and concatinate Source on the end of Destination.
783 @param Dest String to added to the end of.
784 @param Src String to concatinate.
789 IN OUT CHAR16
**Dest
,
797 NewStringCpy (Dest
, Src
);
801 TmpSize
= StrSize (*Dest
);
802 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
803 ASSERT (NewString
!= NULL
);
805 StrCpy (NewString
, *Dest
);
806 StrCat (NewString
, Src
);
814 Synchronize or restore Storage's Edit copy and Shadow copy.
816 @param Storage The Storage to be synchronized.
817 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
819 if TRUE, copy the editbuffer to the buffer.
820 if FALSE, copy the buffer to the editbuffer.
825 IN FORMSET_STORAGE
*Storage
,
826 IN BOOLEAN SyncOrRestore
830 NAME_VALUE_NODE
*Node
;
832 switch (Storage
->Type
) {
833 case EFI_HII_VARSTORE_BUFFER
:
834 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
836 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
838 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
842 case EFI_HII_VARSTORE_NAME_VALUE
:
843 Link
= GetFirstNode (&Storage
->NameValueListHead
);
844 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
845 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
848 NewStringCpy (&Node
->Value
, Node
->EditValue
);
850 NewStringCpy (&Node
->EditValue
, Node
->Value
);
853 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
857 case EFI_HII_VARSTORE_EFI_VARIABLE
:
865 Get Value for given Name from a NameValue Storage.
867 @param Storage The NameValue Storage.
868 @param Name The Name.
869 @param Value The retured Value.
870 @param GetValueFrom Where to get source value, from EditValue or Value.
872 @retval EFI_SUCCESS Value found for given Name.
873 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
878 IN FORMSET_STORAGE
*Storage
,
880 IN OUT CHAR16
**Value
,
881 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
885 NAME_VALUE_NODE
*Node
;
887 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
888 return EFI_INVALID_PARAMETER
;
893 Link
= GetFirstNode (&Storage
->NameValueListHead
);
894 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
895 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
897 if (StrCmp (Name
, Node
->Name
) == 0) {
898 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
899 NewStringCpy (Value
, Node
->EditValue
);
901 NewStringCpy (Value
, Node
->Value
);
906 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
909 return EFI_NOT_FOUND
;
914 Set Value of given Name in a NameValue Storage.
916 @param Storage The NameValue Storage.
917 @param Name The Name.
918 @param Value The Value to set.
919 @param SetValueTo Whether update editValue or Value.
921 @retval EFI_SUCCESS Value found for given Name.
922 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
927 IN FORMSET_STORAGE
*Storage
,
930 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
934 NAME_VALUE_NODE
*Node
;
937 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
938 return EFI_INVALID_PARAMETER
;
941 Link
= GetFirstNode (&Storage
->NameValueListHead
);
942 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
943 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
945 if (StrCmp (Name
, Node
->Name
) == 0) {
946 if (SetValueTo
== GetSetValueWithEditBuffer
) {
947 Buffer
= Node
->EditValue
;
949 Buffer
= Node
->Value
;
951 if (Buffer
!= NULL
) {
954 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
955 ASSERT (Buffer
!= NULL
);
956 if (SetValueTo
== GetSetValueWithEditBuffer
) {
957 Node
->EditValue
= Buffer
;
959 Node
->Value
= Buffer
;
964 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
967 return EFI_NOT_FOUND
;
972 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
974 @param Buffer The Storage to be conveted.
975 @param ConfigResp The returned <ConfigResp>.
976 @param SingleForm Whether update data for single form or formset level.
978 @retval EFI_SUCCESS Convert success.
979 @retval EFI_INVALID_PARAMETER Incorrect storage type.
983 StorageToConfigResp (
985 IN CHAR16
**ConfigResp
,
986 IN BOOLEAN SingleForm
992 NAME_VALUE_NODE
*Node
;
993 CHAR16
*ConfigRequest
;
994 FORMSET_STORAGE
*Storage
;
995 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
997 Status
= EFI_SUCCESS
;
999 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
1000 Storage
= ConfigInfo
->Storage
;
1001 ConfigRequest
= ConfigInfo
->ConfigRequest
;
1003 Storage
= (FORMSET_STORAGE
*) Buffer
;
1004 ConfigRequest
= Storage
->ConfigRequest
;
1007 switch (Storage
->Type
) {
1008 case EFI_HII_VARSTORE_BUFFER
:
1009 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1010 Status
= mHiiConfigRouting
->BlockToConfig (
1013 Storage
->EditBuffer
,
1020 case EFI_HII_VARSTORE_NAME_VALUE
:
1022 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1024 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1025 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1026 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1028 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1029 NewStringCat (ConfigResp
, L
"&");
1030 NewStringCat (ConfigResp
, Node
->Name
);
1031 NewStringCat (ConfigResp
, L
"=");
1032 NewStringCat (ConfigResp
, Node
->EditValue
);
1034 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1038 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1040 Status
= EFI_INVALID_PARAMETER
;
1049 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1051 @param Storage The Storage to receive the settings.
1052 @param ConfigResp The <ConfigResp> to be converted.
1054 @retval EFI_SUCCESS Convert success.
1055 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1059 ConfigRespToStorage (
1060 IN FORMSET_STORAGE
*Storage
,
1061 IN CHAR16
*ConfigResp
1065 EFI_STRING Progress
;
1071 Status
= EFI_SUCCESS
;
1073 switch (Storage
->Type
) {
1074 case EFI_HII_VARSTORE_BUFFER
:
1075 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1076 BufferSize
= Storage
->Size
;
1077 Status
= mHiiConfigRouting
->ConfigToBlock (
1080 Storage
->EditBuffer
,
1086 case EFI_HII_VARSTORE_NAME_VALUE
:
1087 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1088 if (StrPtr
== NULL
) {
1091 StrPtr
= StrStr (ConfigResp
, L
"&");
1092 while (StrPtr
!= NULL
) {
1096 StrPtr
= StrPtr
+ 1;
1098 StrPtr
= StrStr (StrPtr
, L
"=");
1099 if (StrPtr
== NULL
) {
1107 StrPtr
= StrPtr
+ 1;
1109 StrPtr
= StrStr (StrPtr
, L
"&");
1110 if (StrPtr
!= NULL
) {
1113 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
);
1117 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1119 Status
= EFI_INVALID_PARAMETER
;
1128 Get Question's current Value.
1130 @param FormSet FormSet data structure.
1131 @param Form Form data structure.
1132 @param Question Question to be initialized.
1133 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1135 @retval EFI_SUCCESS The function completed successfully.
1140 IN FORM_BROWSER_FORMSET
*FormSet
,
1141 IN FORM_BROWSER_FORM
*Form
,
1142 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1143 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1152 FORMSET_STORAGE
*Storage
;
1153 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1154 CHAR16
*ConfigRequest
;
1162 BOOLEAN IsBufferStorage
;
1168 Status
= EFI_SUCCESS
;
1172 if (GetValueFrom
>= GetSetValueWithMax
) {
1173 return EFI_INVALID_PARAMETER
;
1177 // Statement don't have storage, skip them
1179 if (Question
->QuestionId
== 0) {
1184 // Question value is provided by an Expression, evaluate it
1186 if (Question
->ValueExpression
!= NULL
) {
1187 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1188 if (!EFI_ERROR (Status
)) {
1189 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1190 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1191 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1192 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1193 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1195 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1196 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1198 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1200 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1201 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1207 // Get question value by read expression.
1209 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1210 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1211 if (!EFI_ERROR (Status
) &&
1212 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1214 // Only update question value to the valid result.
1216 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1217 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1218 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1219 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1220 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1222 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1223 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1225 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1227 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1228 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1234 // Question value is provided by RTC
1236 Storage
= Question
->Storage
;
1237 QuestionValue
= &Question
->HiiValue
.Value
;
1238 if (Storage
== NULL
) {
1240 // It's a Question without storage, or RTC date/time
1242 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1244 // Date and time define the same Flags bit
1246 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1247 case QF_DATE_STORAGE_TIME
:
1248 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1251 case QF_DATE_STORAGE_WAKEUP
:
1252 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1255 case QF_DATE_STORAGE_NORMAL
:
1258 // For date/time without storage
1263 if (EFI_ERROR (Status
)) {
1267 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1268 QuestionValue
->date
.Year
= EfiTime
.Year
;
1269 QuestionValue
->date
.Month
= EfiTime
.Month
;
1270 QuestionValue
->date
.Day
= EfiTime
.Day
;
1272 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1273 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1274 QuestionValue
->time
.Second
= EfiTime
.Second
;
1282 // Question value is provided by EFI variable
1284 StorageWidth
= Question
->StorageWidth
;
1285 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1286 if (Question
->BufferValue
!= NULL
) {
1287 Dst
= Question
->BufferValue
;
1289 Dst
= (UINT8
*) QuestionValue
;
1292 Status
= gRT
->GetVariable (
1293 Question
->VariableName
,
1300 // Always return success, even this EFI variable doesn't exist
1306 // Question Value is provided by Buffer Storage or NameValue Storage
1308 if (Question
->BufferValue
!= NULL
) {
1310 // This Question is password or orderedlist
1312 Dst
= Question
->BufferValue
;
1315 // Other type of Questions
1317 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1320 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1321 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1322 IsBufferStorage
= TRUE
;
1324 IsBufferStorage
= FALSE
;
1326 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1327 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1328 if (IsBufferStorage
) {
1329 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1331 // Copy from storage Edit buffer
1333 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1336 // Copy from storage Edit buffer
1338 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1342 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1343 if (EFI_ERROR (Status
)) {
1347 ASSERT (Value
!= NULL
);
1348 LengthStr
= StrLen (Value
);
1349 Status
= EFI_SUCCESS
;
1352 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1353 // Add string tail char L'\0' into Length
1355 Length
= StorageWidth
+ sizeof (CHAR16
);
1356 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1357 Status
= EFI_BUFFER_TOO_SMALL
;
1359 StringPtr
= (CHAR16
*) Dst
;
1360 ZeroMem (TemStr
, sizeof (TemStr
));
1361 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1362 StrnCpy (TemStr
, Value
+ Index
, 4);
1363 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1366 // Add tailing L'\0' character
1368 StringPtr
[Index
/4] = L
'\0';
1371 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1372 Status
= EFI_BUFFER_TOO_SMALL
;
1374 ZeroMem (TemStr
, sizeof (TemStr
));
1375 for (Index
= 0; Index
< LengthStr
; Index
++) {
1376 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1377 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1378 if ((Index
& 1) == 0) {
1379 Dst
[Index
/2] = DigitUint8
;
1381 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1390 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1392 // Request current settings from Configuration Driver
1394 if (FormSet
->ConfigAccess
== NULL
) {
1395 return EFI_NOT_FOUND
;
1399 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1400 // <ConfigHdr> + "&" + <VariableName>
1402 if (IsBufferStorage
) {
1403 Length
= StrLen (Storage
->ConfigHdr
);
1404 Length
+= StrLen (Question
->BlockName
);
1406 Length
= StrLen (Storage
->ConfigHdr
);
1407 Length
+= StrLen (Question
->VariableName
) + 1;
1409 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1410 ASSERT (ConfigRequest
!= NULL
);
1412 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1413 if (IsBufferStorage
) {
1414 StrCat (ConfigRequest
, Question
->BlockName
);
1416 StrCat (ConfigRequest
, L
"&");
1417 StrCat (ConfigRequest
, Question
->VariableName
);
1420 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1421 FormSet
->ConfigAccess
,
1426 FreePool (ConfigRequest
);
1427 if (EFI_ERROR (Status
)) {
1432 // Skip <ConfigRequest>
1434 if (IsBufferStorage
) {
1435 Value
= StrStr (Result
, L
"&VALUE");
1436 if (Value
== NULL
) {
1438 return EFI_NOT_FOUND
;
1445 Value
= Result
+ Length
;
1447 if (*Value
!= '=') {
1449 return EFI_NOT_FOUND
;
1452 // Skip '=', point to value
1457 // Suppress <AltResp> if any
1460 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1465 LengthStr
= StrLen (Value
);
1466 Status
= EFI_SUCCESS
;
1467 if (!IsBufferStorage
&& IsString
) {
1469 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1470 // Add string tail char L'\0' into Length
1472 Length
= StorageWidth
+ sizeof (CHAR16
);
1473 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1474 Status
= EFI_BUFFER_TOO_SMALL
;
1476 StringPtr
= (CHAR16
*) Dst
;
1477 ZeroMem (TemStr
, sizeof (TemStr
));
1478 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1479 StrnCpy (TemStr
, Value
+ Index
, 4);
1480 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1483 // Add tailing L'\0' character
1485 StringPtr
[Index
/4] = L
'\0';
1488 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1489 Status
= EFI_BUFFER_TOO_SMALL
;
1491 ZeroMem (TemStr
, sizeof (TemStr
));
1492 for (Index
= 0; Index
< LengthStr
; Index
++) {
1493 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1494 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1495 if ((Index
& 1) == 0) {
1496 Dst
[Index
/2] = DigitUint8
;
1498 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1504 if (EFI_ERROR (Status
)) {
1508 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1510 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1511 if (TemBuffer
== NULL
) {
1512 Status
= EFI_OUT_OF_RESOURCES
;
1515 Length
= Storage
->Size
;
1516 Status
= gRT
->GetVariable (
1523 if (EFI_ERROR (Status
)) {
1524 FreePool (TemBuffer
);
1528 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1530 FreePool (TemBuffer
);
1534 // Synchronize Edit Buffer
1536 if (IsBufferStorage
) {
1537 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1539 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
);
1542 if (Result
!= NULL
) {
1552 Save Question Value to edit copy(cached) or Storage(uncached).
1554 @param FormSet FormSet data structure.
1555 @param Form Form data structure.
1556 @param Question Pointer to the Question.
1557 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1559 @retval EFI_SUCCESS The function completed successfully.
1564 IN FORM_BROWSER_FORMSET
*FormSet
,
1565 IN FORM_BROWSER_FORM
*Form
,
1566 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1567 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1577 FORMSET_STORAGE
*Storage
;
1578 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1583 BOOLEAN IsBufferStorage
;
1590 Status
= EFI_SUCCESS
;
1592 if (SetValueTo
>= GetSetValueWithMax
) {
1593 return EFI_INVALID_PARAMETER
;
1597 // Statement don't have storage, skip them
1599 if (Question
->QuestionId
== 0) {
1604 // If Question value is provided by an Expression, then it is read only
1606 if (Question
->ValueExpression
!= NULL
) {
1611 // Before set question value, evaluate its write expression.
1613 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1614 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1615 if (EFI_ERROR (Status
)) {
1621 // Question value is provided by RTC
1623 Storage
= Question
->Storage
;
1624 QuestionValue
= &Question
->HiiValue
.Value
;
1625 if (Storage
== NULL
) {
1627 // It's a Question without storage, or RTC date/time
1629 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1631 // Date and time define the same Flags bit
1633 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1634 case QF_DATE_STORAGE_TIME
:
1635 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1638 case QF_DATE_STORAGE_WAKEUP
:
1639 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1642 case QF_DATE_STORAGE_NORMAL
:
1645 // For date/time without storage
1650 if (EFI_ERROR (Status
)) {
1654 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1655 EfiTime
.Year
= QuestionValue
->date
.Year
;
1656 EfiTime
.Month
= QuestionValue
->date
.Month
;
1657 EfiTime
.Day
= QuestionValue
->date
.Day
;
1659 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1660 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1661 EfiTime
.Second
= QuestionValue
->time
.Second
;
1664 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1665 Status
= gRT
->SetTime (&EfiTime
);
1667 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1675 // Question value is provided by EFI variable
1677 StorageWidth
= Question
->StorageWidth
;
1678 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1679 if (Question
->BufferValue
!= NULL
) {
1680 Src
= Question
->BufferValue
;
1682 Src
= (UINT8
*) QuestionValue
;
1685 Status
= gRT
->SetVariable (
1686 Question
->VariableName
,
1688 Storage
->Attributes
,
1696 // Question Value is provided by Buffer Storage or NameValue Storage
1698 if (Question
->BufferValue
!= NULL
) {
1699 Src
= Question
->BufferValue
;
1701 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1704 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1705 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1706 IsBufferStorage
= TRUE
;
1708 IsBufferStorage
= FALSE
;
1710 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1712 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1713 if (IsBufferStorage
) {
1714 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1716 // Copy to storage edit buffer
1718 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1719 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1721 // Copy to storage edit buffer
1723 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1728 // Allocate enough string buffer.
1731 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1732 Value
= AllocateZeroPool (BufferLen
);
1733 ASSERT (Value
!= NULL
);
1735 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1737 TemName
= (CHAR16
*) Src
;
1739 for (; *TemName
!= L
'\0'; TemName
++) {
1740 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1743 BufferLen
= StorageWidth
* 2 + 1;
1744 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1745 ASSERT (Value
!= NULL
);
1747 // Convert Buffer to Hex String
1749 TemBuffer
= Src
+ StorageWidth
- 1;
1751 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1752 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1756 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
);
1759 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1760 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1762 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1763 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1765 if (IsBufferStorage
) {
1766 Length
= StrLen (Question
->BlockName
) + 7;
1768 Length
= StrLen (Question
->VariableName
) + 2;
1770 if (!IsBufferStorage
&& IsString
) {
1771 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1773 Length
+= (StorageWidth
* 2);
1775 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1776 ASSERT (ConfigResp
!= NULL
);
1778 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1779 if (IsBufferStorage
) {
1780 StrCat (ConfigResp
, Question
->BlockName
);
1781 StrCat (ConfigResp
, L
"&VALUE=");
1783 StrCat (ConfigResp
, L
"&");
1784 StrCat (ConfigResp
, Question
->VariableName
);
1785 StrCat (ConfigResp
, L
"=");
1788 Value
= ConfigResp
+ StrLen (ConfigResp
);
1790 if (!IsBufferStorage
&& IsString
) {
1792 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1794 TemName
= (CHAR16
*) Src
;
1796 for (; *TemName
!= L
'\0'; TemName
++) {
1797 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1801 // Convert Buffer to Hex String
1803 TemBuffer
= Src
+ StorageWidth
- 1;
1805 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1806 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1811 // Convert to lower char.
1813 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1814 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1815 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1820 // Submit Question Value to Configuration Driver
1822 if (FormSet
->ConfigAccess
!= NULL
) {
1823 Status
= FormSet
->ConfigAccess
->RouteConfig (
1824 FormSet
->ConfigAccess
,
1828 if (EFI_ERROR (Status
)) {
1829 FreePool (ConfigResp
);
1833 FreePool (ConfigResp
);
1835 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1837 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1838 if (TemBuffer
== NULL
) {
1839 Status
= EFI_OUT_OF_RESOURCES
;
1842 Length
= Storage
->Size
;
1843 Status
= gRT
->GetVariable (
1851 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1853 Status
= gRT
->SetVariable (
1856 Storage
->Attributes
,
1860 FreePool (TemBuffer
);
1861 if (EFI_ERROR (Status
)){
1866 // Sync storage, from editbuffer to buffer.
1868 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1876 Perform inconsistent check for a Form.
1878 @param FormSet FormSet data structure.
1879 @param Form Form data structure.
1880 @param Question The Question to be validated.
1881 @param Type Validation type: InConsistent or NoSubmit
1883 @retval EFI_SUCCESS Form validation pass.
1884 @retval other Form validation failed.
1889 IN FORM_BROWSER_FORMSET
*FormSet
,
1890 IN FORM_BROWSER_FORM
*Form
,
1891 IN FORM_BROWSER_STATEMENT
*Question
,
1897 LIST_ENTRY
*ListHead
;
1900 FORM_EXPRESSION
*Expression
;
1902 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1903 ListHead
= &Question
->InconsistentListHead
;
1904 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1905 ListHead
= &Question
->NoSubmitListHead
;
1907 return EFI_UNSUPPORTED
;
1910 Link
= GetFirstNode (ListHead
);
1911 while (!IsNull (ListHead
, Link
)) {
1912 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1915 // Evaluate the expression
1917 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1918 if (EFI_ERROR (Status
)) {
1922 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1924 // Condition meet, show up error message
1926 if (Expression
->Error
!= 0) {
1927 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1929 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1930 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1934 return EFI_NOT_READY
;
1937 Link
= GetNextNode (ListHead
, Link
);
1945 Perform NoSubmit check for each Form in FormSet.
1947 @param FormSet FormSet data structure.
1948 @param CurrentForm Current input form data structure.
1950 @retval EFI_SUCCESS Form validation pass.
1951 @retval other Form validation failed.
1956 IN FORM_BROWSER_FORMSET
*FormSet
,
1957 IN FORM_BROWSER_FORM
*CurrentForm
1962 FORM_BROWSER_STATEMENT
*Question
;
1963 FORM_BROWSER_FORM
*Form
;
1964 LIST_ENTRY
*LinkForm
;
1966 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1967 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1968 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1969 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1971 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
1975 Link
= GetFirstNode (&Form
->StatementListHead
);
1976 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1977 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1979 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
1980 if (EFI_ERROR (Status
)) {
1984 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1992 Fill storage's edit copy with settings requested from Configuration Driver.
1994 @param FormSet FormSet data structure.
1995 @param ConfigInfo The config info related to this form.
1996 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
1997 editbuffer to buffer
1998 if TRUE, copy the editbuffer to the buffer.
1999 if FALSE, copy the buffer to the editbuffer.
2001 @retval EFI_SUCCESS The function completed successfully.
2005 SynchronizeStorageForForm (
2006 IN FORM_BROWSER_FORMSET
*FormSet
,
2007 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2008 IN BOOLEAN SyncOrRestore
2012 EFI_STRING Progress
;
2016 NAME_VALUE_NODE
*Node
;
2020 Status
= EFI_SUCCESS
;
2022 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2023 return EFI_NOT_FOUND
;
2026 if (ConfigInfo
->ElementCount
== 0) {
2028 // Skip if there is no RequestElement
2033 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2034 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2035 BufferSize
= ConfigInfo
->Storage
->Size
;
2037 if (SyncOrRestore
) {
2038 Src
= ConfigInfo
->Storage
->EditBuffer
;
2039 Dst
= ConfigInfo
->Storage
->Buffer
;
2041 Src
= ConfigInfo
->Storage
->Buffer
;
2042 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2045 Status
= mHiiConfigRouting
->BlockToConfig(
2047 ConfigInfo
->ConfigRequest
,
2053 if (EFI_ERROR (Status
)) {
2057 Status
= mHiiConfigRouting
->ConfigToBlock (
2064 if (Result
!= NULL
) {
2067 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2068 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2069 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2070 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2072 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2073 if (SyncOrRestore
) {
2074 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2076 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2080 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2088 When discard the question value, call the callback function with Changed type
2089 to inform the hii driver.
2091 @param FormSet FormSet data structure.
2092 @param Form Form data structure.
2096 SendDiscardInfoToDriver (
2097 IN FORM_BROWSER_FORMSET
*FormSet
,
2098 IN FORM_BROWSER_FORM
*Form
2102 FORM_BROWSER_STATEMENT
*Question
;
2104 EFI_HII_VALUE HiiValue
;
2106 BOOLEAN ValueChanged
;
2107 EFI_IFR_TYPE_VALUE
*TypeValue
;
2108 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2110 ValueChanged
= FALSE
;
2113 if(!Form
->NvUpdateRequired
) {
2117 Link
= GetFirstNode (&Form
->StatementListHead
);
2118 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2119 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2120 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2122 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2126 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2130 if (Question
->BufferValue
!= NULL
) {
2131 BufferValue
= AllocateZeroPool (Question
->StorageWidth
);
2132 ASSERT (BufferValue
!= NULL
);
2133 CopyMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
);
2135 HiiValue
.Type
= Question
->HiiValue
.Type
;
2136 CopyMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2139 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
2140 if (EFI_ERROR (Status
)) {
2141 if (BufferValue
!= NULL
) {
2142 FreePool (BufferValue
);
2148 if (Question
->BufferValue
!= NULL
) {
2149 if (CompareMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
)) {
2150 ValueChanged
= TRUE
;
2153 if (CompareMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
))) {
2154 ValueChanged
= TRUE
;
2158 if (BufferValue
!= NULL
) {
2159 FreePool (BufferValue
);
2163 if (!ValueChanged
) {
2167 ValueChanged
= FALSE
;
2169 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2170 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2172 TypeValue
= &Question
->HiiValue
.Value
;
2175 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2176 FormSet
->ConfigAccess
->Callback (
2177 FormSet
->ConfigAccess
,
2178 EFI_BROWSER_ACTION_CHANGED
,
2179 Question
->QuestionId
,
2180 Question
->HiiValue
.Type
,
2188 Validate the FormSet. If the formset is not validate, remove it from the list.
2190 @param FormSet The input FormSet which need to validate.
2192 @retval TRUE The handle is validate.
2193 @retval FALSE The handle is invalidate.
2198 FORM_BROWSER_FORMSET
*FormSet
2201 EFI_HII_HANDLE
*HiiHandles
;
2205 ASSERT (FormSet
!= NULL
);
2208 // Get all the Hii handles
2210 HiiHandles
= HiiGetHiiHandles (NULL
);
2211 ASSERT (HiiHandles
!= NULL
);
2214 // Search for formset of each class type
2216 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2217 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2224 RemoveEntryList (&FormSet
->Link
);
2225 DestroyFormSet (FormSet
);
2228 FreePool (HiiHandles
);
2234 Discard data based on the input setting scope (Form, FormSet or System).
2236 @param FormSet FormSet data structure.
2237 @param Form Form data structure.
2238 @param SettingScope Setting Scope for Discard action.
2240 @retval EFI_SUCCESS The function completed successfully.
2241 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2246 IN FORM_BROWSER_FORMSET
*FormSet
,
2247 IN FORM_BROWSER_FORM
*Form
,
2248 IN BROWSER_SETTING_SCOPE SettingScope
2252 FORMSET_STORAGE
*Storage
;
2253 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2254 FORM_BROWSER_FORMSET
*LocalFormSet
;
2257 // Check the supported setting level.
2259 if (SettingScope
>= MaxLevel
) {
2260 return EFI_UNSUPPORTED
;
2263 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2265 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2266 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2267 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2268 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2270 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2275 // Skip if there is no RequestElement
2277 if (ConfigInfo
->ElementCount
== 0) {
2282 // Prepare <ConfigResp>
2284 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2287 // Call callback with Changed type to inform the driver.
2289 SendDiscardInfoToDriver (FormSet
, Form
);
2292 Form
->NvUpdateRequired
= FALSE
;
2293 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2296 // Discard Buffer storage or Name/Value storage
2298 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2299 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2300 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2301 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2303 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2308 // Skip if there is no RequestElement
2310 if (Storage
->ElementCount
== 0) {
2314 SynchronizeStorage(Storage
, FALSE
);
2317 Link
= GetFirstNode (&FormSet
->FormListHead
);
2318 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2319 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2320 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2323 // Call callback with Changed type to inform the driver.
2325 SendDiscardInfoToDriver (FormSet
, Form
);
2328 UpdateNvInfoInForm (FormSet
, FALSE
);
2329 } else if (SettingScope
== SystemLevel
) {
2331 // System Level Discard.
2335 // Discard changed value for each FormSet in the maintain list.
2337 Link
= GetFirstNode (&gBrowserFormSetList
);
2338 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2339 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2340 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2341 if (!ValidateFormSet(LocalFormSet
)) {
2344 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2345 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2347 // Remove maintain backup list after discard except for the current using FormSet.
2349 RemoveEntryList (&LocalFormSet
->Link
);
2350 DestroyFormSet (LocalFormSet
);
2359 Submit data based on the input Setting level (Form, FormSet or System).
2361 @param FormSet FormSet data structure.
2362 @param Form Form data structure.
2363 @param SettingScope Setting Scope for Submit action.
2365 @retval EFI_SUCCESS The function completed successfully.
2366 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2371 IN FORM_BROWSER_FORMSET
*FormSet
,
2372 IN FORM_BROWSER_FORM
*Form
,
2373 IN BROWSER_SETTING_SCOPE SettingScope
2378 EFI_STRING ConfigResp
;
2379 EFI_STRING Progress
;
2380 FORMSET_STORAGE
*Storage
;
2383 FORM_BROWSER_FORMSET
*LocalFormSet
;
2384 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2387 // Check the supported setting level.
2389 if (SettingScope
>= MaxLevel
) {
2390 return EFI_UNSUPPORTED
;
2394 // Validate the Form by NoSubmit check
2396 Status
= EFI_SUCCESS
;
2397 if (SettingScope
== FormLevel
) {
2398 Status
= NoSubmitCheck (FormSet
, Form
);
2399 } else if (SettingScope
== FormSetLevel
) {
2400 Status
= NoSubmitCheck (FormSet
, NULL
);
2402 if (EFI_ERROR (Status
)) {
2406 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2408 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2409 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2410 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2411 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2413 Storage
= ConfigInfo
->Storage
;
2414 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2419 // Skip if there is no RequestElement
2421 if (ConfigInfo
->ElementCount
== 0) {
2426 // 1. Prepare <ConfigResp>
2428 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2429 if (EFI_ERROR (Status
)) {
2434 // 2. Set value to hii driver or efi variable.
2436 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2437 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2439 // Send <ConfigResp> to Configuration Driver
2441 if (FormSet
->ConfigAccess
!= NULL
) {
2442 Status
= FormSet
->ConfigAccess
->RouteConfig (
2443 FormSet
->ConfigAccess
,
2447 if (EFI_ERROR (Status
)) {
2448 FreePool (ConfigResp
);
2452 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2454 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2455 if (TmpBuf
== NULL
) {
2456 Status
= EFI_OUT_OF_RESOURCES
;
2460 BufferSize
= Storage
->Size
;
2461 Status
= gRT
->GetVariable (
2468 if (EFI_ERROR (Status
)) {
2470 FreePool (ConfigResp
);
2473 ASSERT (BufferSize
== Storage
->Size
);
2474 Status
= mHiiConfigRouting
->ConfigToBlock (
2481 if (EFI_ERROR (Status
)) {
2483 FreePool (ConfigResp
);
2487 Status
= gRT
->SetVariable (
2490 Storage
->Attributes
,
2495 if (EFI_ERROR (Status
)) {
2496 FreePool (ConfigResp
);
2500 FreePool (ConfigResp
);
2502 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2504 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2508 // 4. Update the NV flag.
2510 Form
->NvUpdateRequired
= FALSE
;
2511 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2513 // Submit Buffer storage or Name/Value storage
2515 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2516 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2517 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2518 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2520 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2525 // Skip if there is no RequestElement
2527 if (Storage
->ElementCount
== 0) {
2532 // 1. Prepare <ConfigResp>
2534 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2535 if (EFI_ERROR (Status
)) {
2539 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2540 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2543 // 2. Send <ConfigResp> to Configuration Driver
2545 if (FormSet
->ConfigAccess
!= NULL
) {
2546 Status
= FormSet
->ConfigAccess
->RouteConfig (
2547 FormSet
->ConfigAccess
,
2551 if (EFI_ERROR (Status
)) {
2552 FreePool (ConfigResp
);
2556 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2558 // 1&2. Set the edit data to the variable.
2561 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2562 if (TmpBuf
== NULL
) {
2563 Status
= EFI_OUT_OF_RESOURCES
;
2566 BufferSize
= Storage
->Size
;
2567 Status
= gRT
->GetVariable (
2574 ASSERT (BufferSize
== Storage
->Size
);
2575 Status
= mHiiConfigRouting
->ConfigToBlock (
2582 if (EFI_ERROR (Status
)) {
2584 FreePool (ConfigResp
);
2588 Status
= gRT
->SetVariable (
2591 Storage
->Attributes
,
2595 if (EFI_ERROR (Status
)) {
2597 FreePool (ConfigResp
);
2602 FreePool (ConfigResp
);
2604 // 3. Config success, update storage shadow Buffer
2606 SynchronizeStorage (Storage
, TRUE
);
2610 // 4. Update the NV flag.
2612 UpdateNvInfoInForm (FormSet
, FALSE
);
2613 } else if (SettingScope
== SystemLevel
) {
2615 // System Level Save.
2619 // Save changed value for each FormSet in the maintain list.
2621 Link
= GetFirstNode (&gBrowserFormSetList
);
2622 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2623 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2624 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2625 if (!ValidateFormSet(LocalFormSet
)) {
2628 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2629 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2631 // Remove maintain backup list after save except for the current using FormSet.
2633 RemoveEntryList (&LocalFormSet
->Link
);
2634 DestroyFormSet (LocalFormSet
);
2643 Get Question default value from AltCfg string.
2645 @param FormSet The form set.
2646 @param Question The question.
2647 @param DefaultId The default Id.
2649 @retval EFI_SUCCESS Question is reset to default value.
2653 GetDefaultValueFromAltCfg (
2654 IN FORM_BROWSER_FORMSET
*FormSet
,
2655 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2659 BOOLEAN IsBufferStorage
;
2662 FORMSET_STORAGE
*Storage
;
2663 CHAR16
*ConfigRequest
;
2676 Status
= EFI_NOT_FOUND
;
2679 ConfigRequest
= NULL
;
2683 Storage
= Question
->Storage
;
2685 if ((Storage
== NULL
) ||
2686 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2687 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2692 // Question Value is provided by Buffer Storage or NameValue Storage
2694 if (Question
->BufferValue
!= NULL
) {
2696 // This Question is password or orderedlist
2698 Dst
= Question
->BufferValue
;
2701 // Other type of Questions
2703 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2706 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2707 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2710 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2711 // <ConfigHdr> + "&" + <VariableName>
2713 if (IsBufferStorage
) {
2714 Length
= StrLen (Storage
->ConfigHdr
);
2715 Length
+= StrLen (Question
->BlockName
);
2717 Length
= StrLen (Storage
->ConfigHdr
);
2718 Length
+= StrLen (Question
->VariableName
) + 1;
2720 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2721 ASSERT (ConfigRequest
!= NULL
);
2723 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2724 if (IsBufferStorage
) {
2725 StrCat (ConfigRequest
, Question
->BlockName
);
2727 StrCat (ConfigRequest
, L
"&");
2728 StrCat (ConfigRequest
, Question
->VariableName
);
2731 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2732 FormSet
->ConfigAccess
,
2737 if (EFI_ERROR (Status
)) {
2742 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2743 // Get the default configuration string according to the default ID.
2745 Status
= mHiiConfigRouting
->GetAltConfig (
2751 &DefaultId
, // it can be NULL to get the current setting.
2756 // The required setting can't be found. So, it is not required to be validated and set.
2758 if (EFI_ERROR (Status
)) {
2763 // Skip <ConfigRequest>
2765 if (IsBufferStorage
) {
2766 Value
= StrStr (ConfigResp
, L
"&VALUE");
2767 ASSERT (Value
!= NULL
);
2773 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2774 ASSERT (Value
!= NULL
);
2776 Value
= Value
+ StrLen (Question
->VariableName
);
2778 if (*Value
!= '=') {
2779 Status
= EFI_NOT_FOUND
;
2783 // Skip '=', point to value
2788 // Suppress <AltResp> if any
2791 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2796 LengthStr
= StrLen (Value
);
2797 if (!IsBufferStorage
&& IsString
) {
2798 StringPtr
= (CHAR16
*) Dst
;
2799 ZeroMem (TemStr
, sizeof (TemStr
));
2800 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2801 StrnCpy (TemStr
, Value
+ Index
, 4);
2802 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2805 // Add tailing L'\0' character
2807 StringPtr
[Index
/4] = L
'\0';
2809 ZeroMem (TemStr
, sizeof (TemStr
));
2810 for (Index
= 0; Index
< LengthStr
; Index
++) {
2811 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2812 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2813 if ((Index
& 1) == 0) {
2814 Dst
[Index
/2] = DigitUint8
;
2816 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2822 if (ConfigRequest
!= NULL
){
2823 FreePool (ConfigRequest
);
2826 if (ConfigResp
!= NULL
) {
2827 FreePool (ConfigResp
);
2830 if (Result
!= NULL
) {
2838 Get default Id value used for browser.
2840 @param DefaultId The default id value used by hii.
2842 @retval Browser used default value.
2846 GetDefaultIdForCallBack (
2850 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2851 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2852 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2853 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2854 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2855 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2856 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2857 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2858 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2859 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2860 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2861 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2868 Reset Question to its default value.
2870 @param FormSet The form set.
2871 @param Form The form.
2872 @param Question The question.
2873 @param DefaultId The Class of the default.
2875 @retval EFI_SUCCESS Question is reset to default value.
2879 GetQuestionDefault (
2880 IN FORM_BROWSER_FORMSET
*FormSet
,
2881 IN FORM_BROWSER_FORM
*Form
,
2882 IN FORM_BROWSER_STATEMENT
*Question
,
2888 QUESTION_DEFAULT
*Default
;
2889 QUESTION_OPTION
*Option
;
2890 EFI_HII_VALUE
*HiiValue
;
2892 EFI_STRING StrValue
;
2893 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2894 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2897 Status
= EFI_NOT_FOUND
;
2901 // Statement don't have storage, skip them
2903 if (Question
->QuestionId
== 0) {
2908 // There are Five ways to specify default value for a Question:
2909 // 1, use call back function (highest priority)
2910 // 2, use ExtractConfig function
2911 // 3, use nested EFI_IFR_DEFAULT
2912 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2913 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2915 HiiValue
= &Question
->HiiValue
;
2918 // Get Question defaut value from call back function.
2920 ConfigAccess
= FormSet
->ConfigAccess
;
2921 Action
= GetDefaultIdForCallBack (DefaultId
);
2922 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2923 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2924 Status
= ConfigAccess
->Callback (
2927 Question
->QuestionId
,
2932 if (!EFI_ERROR (Status
)) {
2938 // Get default value from altcfg string.
2940 if (ConfigAccess
!= NULL
) {
2941 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2942 if (!EFI_ERROR (Status
)) {
2948 // EFI_IFR_DEFAULT has highest priority
2950 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2951 Link
= GetFirstNode (&Question
->DefaultListHead
);
2952 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2953 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2955 if (Default
->DefaultId
== DefaultId
) {
2956 if (Default
->ValueExpression
!= NULL
) {
2958 // Default is provided by an Expression, evaluate it
2960 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2961 if (EFI_ERROR (Status
)) {
2965 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
2966 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
2967 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
2968 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
2969 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
2971 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
2972 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
2974 FreePool (Default
->ValueExpression
->Result
.Buffer
);
2976 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
2977 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2980 // Default value is embedded in EFI_IFR_DEFAULT
2982 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2985 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2986 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
2987 if (StrValue
== NULL
) {
2988 return EFI_NOT_FOUND
;
2990 if (Question
->StorageWidth
> StrSize (StrValue
)) {
2991 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
2993 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3000 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3005 // EFI_ONE_OF_OPTION
3007 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3008 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3010 // OneOfOption could only provide Standard and Manufacturing default
3012 Link
= GetFirstNode (&Question
->OptionListHead
);
3013 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3014 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3015 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3017 if ((Option
->SuppressExpression
!= NULL
) &&
3018 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3022 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3023 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3025 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3034 // EFI_IFR_CHECKBOX - lowest priority
3036 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3037 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3039 // Checkbox could only provide Standard and Manufacturing default
3041 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3042 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3044 HiiValue
->Value
.b
= TRUE
;
3046 HiiValue
->Value
.b
= FALSE
;
3054 // For Questions without default
3056 Status
= EFI_NOT_FOUND
;
3057 switch (Question
->Operand
) {
3058 case EFI_IFR_NUMERIC_OP
:
3060 // Take minimum value as numeric default value
3062 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3063 HiiValue
->Value
.u64
= Question
->Minimum
;
3064 Status
= EFI_SUCCESS
;
3068 case EFI_IFR_ONE_OF_OP
:
3070 // Take first oneof option as oneof's default value
3072 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3073 Link
= GetFirstNode (&Question
->OptionListHead
);
3074 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3075 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3076 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3078 if ((Option
->SuppressExpression
!= NULL
) &&
3079 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3083 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3084 Status
= EFI_SUCCESS
;
3090 case EFI_IFR_ORDERED_LIST_OP
:
3092 // Take option sequence in IFR as ordered list's default value
3095 Link
= GetFirstNode (&Question
->OptionListHead
);
3096 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3097 Status
= EFI_SUCCESS
;
3098 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3099 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3101 if ((Option
->SuppressExpression
!= NULL
) &&
3102 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3106 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3109 if (Index
>= Question
->MaxContainers
) {
3124 Reset Questions to their initial value or default value in a Form, Formset or System.
3126 GetDefaultValueScope parameter decides which questions will reset
3127 to its default value.
3129 @param FormSet FormSet data structure.
3130 @param Form Form data structure.
3131 @param DefaultId The Class of the default.
3132 @param SettingScope Setting Scope for Default action.
3133 @param GetDefaultValueScope Get default value scope.
3134 @param Storage Get default value only for this storage.
3135 @param RetrieveValueFirst Whether call the retrieve call back to
3136 get the initial value before get default
3139 @retval EFI_SUCCESS The function completed successfully.
3140 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3145 IN FORM_BROWSER_FORMSET
*FormSet
,
3146 IN FORM_BROWSER_FORM
*Form
,
3147 IN UINT16 DefaultId
,
3148 IN BROWSER_SETTING_SCOPE SettingScope
,
3149 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3150 IN FORMSET_STORAGE
*Storage OPTIONAL
,
3151 IN BOOLEAN RetrieveValueFirst
3155 LIST_ENTRY
*FormLink
;
3157 FORM_BROWSER_STATEMENT
*Question
;
3158 FORM_BROWSER_FORMSET
*BackUpFormSet
;
3159 FORM_BROWSER_FORMSET
*LocalFormSet
;
3160 EFI_HII_HANDLE
*HiiHandles
;
3164 Status
= EFI_SUCCESS
;
3167 // Check the supported setting level.
3169 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3170 return EFI_UNSUPPORTED
;
3173 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3174 return EFI_UNSUPPORTED
;
3177 if (SettingScope
== FormLevel
) {
3179 // Extract Form default
3181 Link
= GetFirstNode (&Form
->StatementListHead
);
3182 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3183 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3184 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3187 // If get default value only for this storage, check the storage first.
3189 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3194 // If get default value only for no storage question, just skip the question which has storage.
3196 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3201 // If Question is disabled, don't reset it to default
3203 if (Question
->Expression
!= NULL
) {
3204 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3209 if (RetrieveValueFirst
) {
3211 // Call the Retrieve call back to get the initial question value.
3213 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3217 // If not request to get the initial value or get initial value fail, then get default value.
3219 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3220 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3221 if (EFI_ERROR (Status
)) {
3227 // Synchronize Buffer storage's Edit buffer
3229 if ((Question
->Storage
!= NULL
) &&
3230 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3231 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3233 // Update Form NV flag.
3235 Form
->NvUpdateRequired
= TRUE
;
3238 } else if (SettingScope
== FormSetLevel
) {
3239 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3240 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3241 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3242 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3243 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3245 } else if (SettingScope
== SystemLevel
) {
3247 // Open all FormSet by locate HII packages.
3248 // Initiliaze the maintain FormSet to store default data as back up data.
3250 BackUpFormSet
= gOldFormSet
;
3254 // Get all the Hii handles
3256 HiiHandles
= HiiGetHiiHandles (NULL
);
3257 ASSERT (HiiHandles
!= NULL
);
3260 // Search for formset of each class type
3262 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3264 // Check HiiHandles[Index] does exist in global maintain list.
3266 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3271 // Initilize FormSet Setting
3273 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3274 ASSERT (LocalFormSet
!= NULL
);
3275 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3276 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
, FALSE
);
3277 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3278 DestroyFormSet (LocalFormSet
);
3281 Status
= InitializeCurrentSetting (LocalFormSet
);
3282 if (EFI_ERROR (Status
)) {
3283 DestroyFormSet (LocalFormSet
);
3287 // Initilize Questions' Value
3289 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
3290 if (EFI_ERROR (Status
)) {
3291 DestroyFormSet (LocalFormSet
);
3296 // Add FormSet into the maintain list.
3298 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3302 // Free resources, and restore gOldFormSet and gClassOfVfr
3304 FreePool (HiiHandles
);
3305 gOldFormSet
= BackUpFormSet
;
3308 // Set Default Value for each FormSet in the maintain list.
3310 Link
= GetFirstNode (&gBrowserFormSetList
);
3311 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3312 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3313 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3314 if (!ValidateFormSet(LocalFormSet
)) {
3317 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3325 Initialize Question's Edit copy from Storage.
3327 @param Selection Selection contains the information about
3328 the Selection, form and formset to be displayed.
3329 Selection action may be updated in retrieve callback.
3330 If Selection is NULL, only initialize Question value.
3331 @param FormSet FormSet data structure.
3332 @param Form Form data structure.
3334 @retval EFI_SUCCESS The function completed successfully.
3339 IN OUT UI_MENU_SELECTION
*Selection
,
3340 IN FORM_BROWSER_FORMSET
*FormSet
,
3341 IN FORM_BROWSER_FORM
*Form
3346 FORM_BROWSER_STATEMENT
*Question
;
3350 Link
= GetFirstNode (&Form
->StatementListHead
);
3351 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3352 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3355 // Initialize local copy of Value for each Question
3357 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3358 if (EFI_ERROR (Status
)) {
3362 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3363 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3367 // Call the Retrieve call back function for all questions.
3369 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3370 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3372 // Check QuestionValue does exist.
3374 StorageWidth
= Question
->StorageWidth
;
3375 if (Question
->BufferValue
!= NULL
) {
3376 BufferValue
= Question
->BufferValue
;
3378 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3382 // For efivarstore storage, initial question value first.
3384 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3385 Status
= gRT
->GetVariable (
3386 Question
->VariableName
,
3387 &Question
->Storage
->Guid
,
3394 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3397 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3404 Initialize Question's Edit copy from Storage for the whole Formset.
3406 @param Selection Selection contains the information about
3407 the Selection, form and formset to be displayed.
3408 Selection action may be updated in retrieve callback.
3409 If Selection is NULL, only initialize Question value.
3410 @param FormSet FormSet data structure.
3412 @retval EFI_SUCCESS The function completed successfully.
3417 IN OUT UI_MENU_SELECTION
*Selection
,
3418 IN FORM_BROWSER_FORMSET
*FormSet
3423 FORM_BROWSER_FORM
*Form
;
3425 Link
= GetFirstNode (&FormSet
->FormListHead
);
3426 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3427 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3430 // Initialize local copy of Value for each Form
3432 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3433 if (EFI_ERROR (Status
)) {
3437 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3444 Fill storage's edit copy with settings requested from Configuration Driver.
3446 @param FormSet FormSet data structure.
3447 @param Storage Buffer Storage.
3449 @retval EFI_SUCCESS The function completed successfully.
3454 IN FORM_BROWSER_FORMSET
*FormSet
,
3455 IN FORMSET_STORAGE
*Storage
3459 EFI_STRING Progress
;
3463 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3467 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3468 Status
= gRT
->GetVariable (
3472 (UINTN
*)&Storage
->Size
,
3478 if (FormSet
->ConfigAccess
== NULL
) {
3479 return EFI_NOT_FOUND
;
3482 if (Storage
->ElementCount
== 0) {
3484 // Skip if there is no RequestElement
3490 // Request current settings from Configuration Driver
3492 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3493 FormSet
->ConfigAccess
,
3494 Storage
->ConfigRequest
,
3498 if (EFI_ERROR (Status
)) {
3503 // Convert Result from <ConfigAltResp> to <ConfigResp>
3505 StrPtr
= StrStr (Result
, L
"&GUID=");
3506 if (StrPtr
!= NULL
) {
3510 Status
= ConfigRespToStorage (Storage
, Result
);
3517 Copy uncommitted data from source Storage to destination Storage.
3519 @param Dst Target Storage for uncommitted data.
3520 @param Src Source Storage for uncommitted data.
3522 @retval EFI_SUCCESS The function completed successfully.
3523 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
3528 IN OUT FORMSET_STORAGE
*Dst
,
3529 IN FORMSET_STORAGE
*Src
3533 NAME_VALUE_NODE
*Node
;
3535 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
3536 return EFI_INVALID_PARAMETER
;
3539 switch (Src
->Type
) {
3540 case EFI_HII_VARSTORE_BUFFER
:
3541 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3542 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
3543 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
3546 case EFI_HII_VARSTORE_NAME_VALUE
:
3547 Link
= GetFirstNode (&Src
->NameValueListHead
);
3548 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
3549 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3551 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, GetSetValueWithEditBuffer
);
3552 SetValueByName (Dst
, Node
->Name
, Node
->Value
, GetSetValueWithBuffer
);
3554 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
3558 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3567 Get old question value from the saved formset.
3569 @param Statement The question which need to get old question value.
3570 @param OldFormSet FormSet data structure saved in the list.
3574 GetOldQuestionValue (
3575 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
3576 IN FORM_BROWSER_FORMSET
*OldFormSet
3579 LIST_ENTRY
*FormLink
;
3581 FORM_BROWSER_STATEMENT
*Question
;
3582 FORM_BROWSER_FORM
*Form
;
3584 FormLink
= GetFirstNode (&OldFormSet
->FormListHead
);
3585 while (!IsNull (&OldFormSet
->FormListHead
, FormLink
)) {
3586 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3587 FormLink
= GetNextNode (&OldFormSet
->FormListHead
, FormLink
);
3589 Link
= GetFirstNode (&Form
->StatementListHead
);
3590 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3591 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3592 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3594 if (Question
->QuestionId
!= Statement
->QuestionId
) {
3598 CopyMem (&Statement
->HiiValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3605 Get old question value from the saved formset, all these questions not have
3608 @param FormSet FormSet data structure which is used now.
3609 @param OldFormSet FormSet data structure saved in the list.
3613 CopyOldValueForNoStorageQst (
3614 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
3615 IN FORM_BROWSER_FORMSET
*OldFormSet
3618 LIST_ENTRY
*FormLink
;
3620 FORM_BROWSER_STATEMENT
*Question
;
3621 FORM_BROWSER_FORM
*Form
;
3623 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3624 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3625 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3626 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3628 Link
= GetFirstNode (&Form
->StatementListHead
);
3629 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3630 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3631 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3633 if (Question
->Storage
== NULL
) {
3634 GetOldQuestionValue (Question
, OldFormSet
);
3641 Get current setting of Questions.
3643 @param FormSet FormSet data structure.
3645 @retval EFI_SUCCESS The function completed successfully.
3649 InitializeCurrentSetting (
3650 IN OUT FORM_BROWSER_FORMSET
*FormSet
3655 FORMSET_STORAGE
*Storage
;
3656 FORMSET_STORAGE
*StorageSrc
;
3657 FORMSET_STORAGE
*OldStorage
;
3658 FORM_BROWSER_FORM
*Form
;
3659 FORM_BROWSER_FORM
*Form2
;
3663 // Extract default from IFR binary for no storage questions.
3665 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
3668 // Request current settings from Configuration Driver
3670 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3671 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3672 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3675 if (gOldFormSet
!= NULL
) {
3677 // Try to find the Storage in backup formset gOldFormSet
3679 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3680 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3681 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3683 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3684 OldStorage
= StorageSrc
;
3688 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3692 if (OldStorage
== NULL
) {
3694 // Storage is not found in backup formset, request it from ConfigDriver
3696 Status
= LoadStorage (FormSet
, Storage
);
3698 if (EFI_ERROR (Status
)) {
3700 // If get last time changed value failed, extract default from IFR binary
3702 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3704 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3705 // in current situation.
3707 UpdateNvInfoInForm (FormSet
, FALSE
);
3711 // Now Edit Buffer is filled with default values(lower priority) or current
3712 // settings(higher priority), sychronize it to shadow Buffer
3714 SynchronizeStorage (Storage
, TRUE
);
3717 // Storage found in backup formset, use it
3719 Status
= CopyStorage (Storage
, OldStorage
);
3722 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3726 // If has old formset, get the old nv update status.
3728 if (gOldFormSet
!= NULL
) {
3729 Link
= GetFirstNode (&FormSet
->FormListHead
);
3730 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3731 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3733 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3734 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3735 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3737 if (Form
->FormId
== Form2
->FormId
) {
3738 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3742 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3744 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3753 Fetch the Ifr binary data of a FormSet.
3755 @param Handle PackageList Handle
3756 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3757 specified (NULL or zero GUID), take the first
3758 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3759 found in package list.
3760 On output, GUID of the formset found(if not NULL).
3761 @param BinaryLength The length of the FormSet IFR binary.
3762 @param BinaryData The buffer designed to receive the FormSet.
3764 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3765 BufferLength was updated.
3766 @retval EFI_INVALID_PARAMETER The handle is unknown.
3767 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3768 be found with the requested FormId.
3773 IN EFI_HII_HANDLE Handle
,
3774 IN OUT EFI_GUID
*FormSetGuid
,
3775 OUT UINTN
*BinaryLength
,
3776 OUT UINT8
**BinaryData
3780 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3786 UINT32 PackageListLength
;
3787 EFI_HII_PACKAGE_HEADER PackageHeader
;
3789 UINT8 NumberOfClassGuid
;
3790 BOOLEAN ClassGuidMatch
;
3791 EFI_GUID
*ClassGuid
;
3792 EFI_GUID
*ComparingGuid
;
3796 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3799 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3801 if (FormSetGuid
== NULL
) {
3802 ComparingGuid
= &gZeroGuid
;
3804 ComparingGuid
= FormSetGuid
;
3808 // Get HII PackageList
3811 HiiPackageList
= NULL
;
3812 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3813 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3814 HiiPackageList
= AllocatePool (BufferSize
);
3815 ASSERT (HiiPackageList
!= NULL
);
3817 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3819 if (EFI_ERROR (Status
)) {
3822 ASSERT (HiiPackageList
!= NULL
);
3825 // Get Form package from this HII package List
3827 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3829 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3831 ClassGuidMatch
= FALSE
;
3832 while (Offset
< PackageListLength
) {
3833 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3834 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3836 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3838 // Search FormSet in this Form Package
3840 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3841 while (Offset2
< PackageHeader
.Length
) {
3842 OpCodeData
= Package
+ Offset2
;
3844 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3846 // Try to compare against formset GUID
3848 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3849 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3853 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3855 // Try to compare against formset class GUID
3857 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3858 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3859 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3860 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3861 ClassGuidMatch
= TRUE
;
3865 if (ClassGuidMatch
) {
3868 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3869 ClassGuidMatch
= TRUE
;
3874 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3877 if (Offset2
< PackageHeader
.Length
) {
3879 // Target formset found
3885 Offset
+= PackageHeader
.Length
;
3888 if (Offset
>= PackageListLength
) {
3890 // Form package not found in this Package List
3892 FreePool (HiiPackageList
);
3893 return EFI_NOT_FOUND
;
3896 if (FormSetGuid
!= NULL
) {
3898 // Return the FormSet GUID
3900 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3904 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3905 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3906 // of the Form Package.
3908 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3909 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3911 FreePool (HiiPackageList
);
3913 if (*BinaryData
== NULL
) {
3914 return EFI_OUT_OF_RESOURCES
;
3922 Initialize the internal data structure of a FormSet.
3924 @param Handle PackageList Handle
3925 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3926 specified (NULL or zero GUID), take the first
3927 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3928 found in package list.
3929 On output, GUID of the formset found(if not NULL).
3930 @param FormSet FormSet data structure.
3931 @param UpdateGlobalVar Whether need to update the global variable.
3933 @retval EFI_SUCCESS The function completed successfully.
3934 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3939 IN EFI_HII_HANDLE Handle
,
3940 IN OUT EFI_GUID
*FormSetGuid
,
3941 OUT FORM_BROWSER_FORMSET
*FormSet
,
3942 IN BOOLEAN UpdateGlobalVar
3946 EFI_HANDLE DriverHandle
;
3949 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3950 if (EFI_ERROR (Status
)) {
3954 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3955 FormSet
->HiiHandle
= Handle
;
3956 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3959 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3961 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3962 if (EFI_ERROR (Status
)) {
3965 FormSet
->DriverHandle
= DriverHandle
;
3966 Status
= gBS
->HandleProtocol (
3968 &gEfiHiiConfigAccessProtocolGuid
,
3969 (VOID
**) &FormSet
->ConfigAccess
3971 if (EFI_ERROR (Status
)) {
3973 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3974 // list, then there will be no configuration action required
3976 FormSet
->ConfigAccess
= NULL
;
3980 // Parse the IFR binary OpCodes
3982 Status
= ParseOpCodes (FormSet
);
3983 if (EFI_ERROR (Status
)) {
3988 // If not need to update the global variable, just return.
3990 if (!UpdateGlobalVar
) {
3995 // Set VFR type by FormSet SubClass field
3997 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
3998 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
3999 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
4003 // Set VFR type by FormSet class guid
4005 for (Index
= 0; Index
< 3; Index
++) {
4006 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
4007 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
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
;