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
);
41 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
43 BANNER_DATA
*gBannerData
;
44 EFI_HII_HANDLE gFrontPageHandle
;
46 UINTN gFunctionKeySetting
;
47 BOOLEAN gResetRequired
;
48 EFI_HII_HANDLE gHiiHandle
;
50 EFI_SCREEN_DESCRIPTOR gScreenDimensions
;
51 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
52 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
53 EXIT_HANDLER ExitHandlerFunction
= NULL
;
57 // Browser Global Strings
60 CHAR16
*gDiscardFailed
;
61 CHAR16
*gDefaultFailed
;
63 CHAR16
*gEnterCommitString
;
64 CHAR16
*gEnterEscapeString
;
65 CHAR16
*gEscapeString
;
66 CHAR16
*gMoveHighlight
;
67 CHAR16
*gMakeSelection
;
68 CHAR16
*gDecNumericInput
;
69 CHAR16
*gHexNumericInput
;
70 CHAR16
*gToggleCheckBox
;
71 CHAR16
*gPromptForData
;
72 CHAR16
*gPromptForPassword
;
73 CHAR16
*gPromptForNewPassword
;
74 CHAR16
*gConfirmPassword
;
75 CHAR16
*gConfirmError
;
76 CHAR16
*gPassowordInvalid
;
85 CHAR16
*gAdjustNumber
;
87 CHAR16
*gOptionMismatch
;
88 CHAR16
*gFormSuppress
;
89 CHAR16
*gProtocolNotFound
;
91 CHAR16
*mUnknownString
= L
"!";
93 CHAR16 gPromptBlockWidth
;
94 CHAR16 gOptionBlockWidth
;
95 CHAR16 gHelpBlockWidth
;
97 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
98 EFI_GUID gSetupBrowserGuid
= {
99 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
102 FORM_BROWSER_FORMSET
*gOldFormSet
= NULL
;
104 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
124 NONE_FUNCTION_KEY_SETTING
145 NONE_FUNCTION_KEY_SETTING
166 NONE_FUNCTION_KEY_SETTING
169 // BMM File Explorer FormSet.
187 NONE_FUNCTION_KEY_SETTING
192 This is the routine which an external caller uses to direct the browser
193 where to obtain it's information.
196 @param This The Form Browser protocol instanse.
197 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
198 display a list of the formsets for the handles specified.
199 @param HandleCount The number of Handles specified in Handle.
200 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
201 field in the EFI_IFR_FORM_SET op-code for the specified
202 forms-based package. If FormSetGuid is NULL, then this
203 function will display the first found forms package.
204 @param FormId This field specifies which EFI_IFR_FORM to render as the first
205 displayable page. If this field has a value of 0x0000, then
206 the forms browser will render the specified forms in their encoded order.
207 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
209 @param ActionRequest Points to the action recommended by the form.
211 @retval EFI_SUCCESS The function completed successfully.
212 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
213 @retval EFI_NOT_FOUND No valid forms could be found to display.
219 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
220 IN EFI_HII_HANDLE
*Handles
,
221 IN UINTN HandleCount
,
222 IN EFI_GUID
*FormSetGuid
, OPTIONAL
223 IN UINT16 FormId
, OPTIONAL
224 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
225 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
229 UI_MENU_SELECTION
*Selection
;
231 FORM_BROWSER_FORMSET
*FormSet
;
235 // Calculate total number of Register HotKeys.
238 Link
= GetFirstNode (&gBrowserHotKeyList
);
239 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
240 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
244 // Show three HotKeys help information on one ROW.
246 gFooterHeight
= FOOTER_HEIGHT
+ (Index
/ 3);
249 // Clean the history menu list.
251 InitializeListHead (&gMenuList
);
254 // Save globals used by SendForm()
256 SaveBrowserContext ();
258 gResetRequired
= FALSE
;
259 Status
= EFI_SUCCESS
;
260 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
263 // Seed the dimensions in the global
265 gST
->ConOut
->QueryMode (
267 gST
->ConOut
->Mode
->Mode
,
268 &gScreenDimensions
.RightColumn
,
269 &gScreenDimensions
.BottomRow
272 if (ScreenDimensions
!= NULL
) {
274 // Check local dimension vs. global dimension.
276 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
277 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
279 Status
= EFI_INVALID_PARAMETER
;
283 // Local dimension validation.
285 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
286 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
287 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
289 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
290 SCROLL_ARROW_HEIGHT
*
292 FRONT_PAGE_HEADER_HEIGHT
+
297 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
299 Status
= EFI_INVALID_PARAMETER
;
305 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
306 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
307 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
310 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
312 InitializeBrowserStrings ();
315 // Ensure we are in Text mode
317 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
319 for (Index
= 0; Index
< HandleCount
; Index
++) {
320 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
321 ASSERT (Selection
!= NULL
);
323 Selection
->Handle
= Handles
[Index
];
324 if (FormSetGuid
!= NULL
) {
325 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
326 Selection
->FormId
= FormId
;
328 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
332 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
333 ASSERT (FormSet
!= NULL
);
336 // Initialize internal data structures of FormSet
338 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
, TRUE
);
339 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
340 DestroyFormSet (FormSet
);
343 Selection
->FormSet
= FormSet
;
346 // Try to find pre FormSet in the maintain backup list.
348 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
351 // Display this formset
353 gCurrentSelection
= Selection
;
355 Status
= SetupBrowser (Selection
);
357 gCurrentSelection
= NULL
;
359 if (EFI_ERROR (Status
)) {
363 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
365 if (gOldFormSet
!= NULL
) {
367 // If no data is changed, don't need to save current FormSet into the maintain list.
369 if (!IsNvUpdateRequired (gOldFormSet
)) {
370 CleanBrowserStorage(gOldFormSet
);
371 RemoveEntryList (&gOldFormSet
->Link
);
372 DestroyFormSet (gOldFormSet
);
377 FreePool (Selection
);
380 if (ActionRequest
!= NULL
) {
381 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
382 if (gResetRequired
) {
383 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
387 FreeBrowserStrings ();
388 UiFreeMenuList(&gMenuList
);
390 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
391 gST
->ConOut
->ClearScreen (gST
->ConOut
);
395 // Restore globals used by SendForm()
397 RestoreBrowserContext ();
404 This function is called by a callback handler to retrieve uncommitted state
405 data from the browser.
407 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
409 @param ResultsDataSize A pointer to the size of the buffer associated
411 @param ResultsData A string returned from an IFR browser or
412 equivalent. The results string will have no
413 routing information in them.
414 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
415 (if RetrieveData = TRUE) data from the uncommitted
416 browser state information or set (if RetrieveData
417 = FALSE) data in the uncommitted browser state
419 @param VariableGuid An optional field to indicate the target variable
421 @param VariableName An optional field to indicate the target
422 human-readable variable name.
424 @retval EFI_SUCCESS The results have been distributed or are awaiting
426 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
427 contain the results data.
433 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
434 IN OUT UINTN
*ResultsDataSize
,
435 IN OUT EFI_STRING ResultsData
,
436 IN BOOLEAN RetrieveData
,
437 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
438 IN CONST CHAR16
*VariableName OPTIONAL
443 FORMSET_STORAGE
*Storage
;
444 FORM_BROWSER_FORMSET
*FormSet
;
451 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
452 return EFI_INVALID_PARAMETER
;
455 if (gCurrentSelection
== NULL
) {
456 return EFI_NOT_READY
;
461 FormSet
= gCurrentSelection
->FormSet
;
464 // Find target storage
466 Link
= GetFirstNode (&FormSet
->StorageListHead
);
467 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
468 return EFI_UNSUPPORTED
;
471 if (VariableGuid
!= NULL
) {
473 // Try to find target storage
476 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
477 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
478 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
480 if (CompareGuid (&Storage
->BrowserStorage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
481 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
482 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
484 // Buffer storage require both GUID and Name
486 if (VariableName
== NULL
) {
487 return EFI_NOT_FOUND
;
490 if (StrCmp (Storage
->BrowserStorage
->Name
, (CHAR16
*) VariableName
) != 0) {
500 return EFI_NOT_FOUND
;
504 // GUID/Name is not specified, take the first storage in FormSet
506 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
511 // Skip if there is no RequestElement
513 if (Storage
->ElementCount
== 0) {
518 // Generate <ConfigResp>
520 Status
= StorageToConfigResp (Storage
->BrowserStorage
, &ConfigResp
, Storage
->ConfigRequest
);
521 if (EFI_ERROR (Status
)) {
526 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
528 StrPtr
= ConfigResp
+ StrLen (Storage
->BrowserStorage
->ConfigHdr
) + 1;
530 BufferSize
= StrSize (StrPtr
);
531 if (*ResultsDataSize
< BufferSize
) {
532 *ResultsDataSize
= BufferSize
;
534 FreePool (ConfigResp
);
535 return EFI_BUFFER_TOO_SMALL
;
538 *ResultsDataSize
= BufferSize
;
539 CopyMem (ResultsData
, StrPtr
, BufferSize
);
541 FreePool (ConfigResp
);
544 // Prepare <ConfigResp>
546 TmpSize
= StrLen (ResultsData
);
547 BufferSize
= (TmpSize
+ StrLen (Storage
->BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
548 ConfigResp
= AllocateZeroPool (BufferSize
);
549 ASSERT (ConfigResp
!= NULL
);
551 StrCpy (ConfigResp
, Storage
->BrowserStorage
->ConfigHdr
);
552 StrCat (ConfigResp
, L
"&");
553 StrCat (ConfigResp
, ResultsData
);
556 // Update Browser uncommited data
558 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, ConfigResp
);
559 if (EFI_ERROR (Status
)) {
568 Initialize Setup Browser driver.
570 @param ImageHandle The image handle.
571 @param SystemTable The system table.
573 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
574 @return Other value if failed to initialize the Setup Browser module.
580 IN EFI_HANDLE ImageHandle
,
581 IN EFI_SYSTEM_TABLE
*SystemTable
585 EFI_INPUT_KEY DefaultHotKey
;
586 EFI_STRING HelpString
;
589 // Locate required Hii relative protocols
591 Status
= gBS
->LocateProtocol (
592 &gEfiHiiDatabaseProtocolGuid
,
594 (VOID
**) &mHiiDatabase
596 ASSERT_EFI_ERROR (Status
);
598 Status
= gBS
->LocateProtocol (
599 &gEfiHiiStringProtocolGuid
,
601 (VOID
**) &mHiiString
603 ASSERT_EFI_ERROR (Status
);
605 Status
= gBS
->LocateProtocol (
606 &gEfiHiiConfigRoutingProtocolGuid
,
608 (VOID
**) &mHiiConfigRouting
610 ASSERT_EFI_ERROR (Status
);
612 Status
= gBS
->LocateProtocol (
613 &gEfiDevicePathFromTextProtocolGuid
,
615 (VOID
**) &mPathFromText
619 // Publish our HII data
621 gHiiHandle
= HiiAddPackages (
627 ASSERT (gHiiHandle
!= NULL
);
630 // Initialize Driver private data
632 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
633 ASSERT (gBannerData
!= NULL
);
636 // Initialize generic help strings.
638 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
639 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
640 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
643 // Install FormBrowser2 protocol
645 mPrivateData
.Handle
= NULL
;
646 Status
= gBS
->InstallProtocolInterface (
647 &mPrivateData
.Handle
,
648 &gEfiFormBrowser2ProtocolGuid
,
649 EFI_NATIVE_INTERFACE
,
650 &mPrivateData
.FormBrowser2
652 ASSERT_EFI_ERROR (Status
);
655 // Install default HotKey F10 for Save
657 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
658 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
659 DefaultHotKey
.ScanCode
= SCAN_F10
;
660 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
661 FreePool (HelpString
);
663 // Install default HotKey F9 for Reset To Defaults
665 DefaultHotKey
.ScanCode
= SCAN_F9
;
666 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
667 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
668 FreePool (HelpString
);
671 // Install FormBrowserEx protocol
673 mPrivateData
.Handle
= NULL
;
674 Status
= gBS
->InstallProtocolInterface (
675 &mPrivateData
.Handle
,
676 &gEfiFormBrowserExProtocolGuid
,
677 EFI_NATIVE_INTERFACE
,
678 &mPrivateData
.FormBrowserEx
680 ASSERT_EFI_ERROR (Status
);
687 Create a new string in HII Package List.
689 @param String The String to be added
690 @param HiiHandle The package list in the HII database to insert the
693 @return The output string.
699 IN EFI_HII_HANDLE HiiHandle
702 EFI_STRING_ID StringId
;
704 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
705 ASSERT (StringId
!= 0);
712 Delete a string from HII Package List.
714 @param StringId Id of the string in HII database.
715 @param HiiHandle The HII package list handle.
717 @retval EFI_SUCCESS The string was deleted successfully.
722 IN EFI_STRING_ID StringId
,
723 IN EFI_HII_HANDLE HiiHandle
728 NullChar
= CHAR_NULL
;
729 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
735 Get the string based on the StringId and HII Package List Handle.
737 @param Token The String's ID.
738 @param HiiHandle The package list in the HII database to search for
739 the specified string.
741 @return The output string.
746 IN EFI_STRING_ID Token
,
747 IN EFI_HII_HANDLE HiiHandle
752 if (HiiHandle
== NULL
) {
756 String
= HiiGetString (HiiHandle
, Token
, NULL
);
757 if (String
== NULL
) {
758 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
759 ASSERT (String
!= NULL
);
761 return (CHAR16
*) String
;
766 Allocate new memory and then copy the Unicode string Source to Destination.
768 @param Dest Location to copy string
769 @param Src String to copy
774 IN OUT CHAR16
**Dest
,
781 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
782 ASSERT (*Dest
!= NULL
);
787 Allocate new memory and concatinate Source on the end of Destination.
789 @param Dest String to added to the end of.
790 @param Src String to concatinate.
795 IN OUT CHAR16
**Dest
,
803 NewStringCpy (Dest
, Src
);
807 TmpSize
= StrSize (*Dest
);
808 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
809 ASSERT (NewString
!= NULL
);
811 StrCpy (NewString
, *Dest
);
812 StrCat (NewString
, Src
);
820 Synchronize or restore Storage's Edit copy and Shadow copy.
822 @param Storage The Storage to be synchronized.
823 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
825 if TRUE, copy the editbuffer to the buffer.
826 if FALSE, copy the buffer to the editbuffer.
831 IN BROWSER_STORAGE
*Storage
,
832 IN BOOLEAN SyncOrRestore
836 NAME_VALUE_NODE
*Node
;
838 switch (Storage
->Type
) {
839 case EFI_HII_VARSTORE_BUFFER
:
840 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
842 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
844 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
848 case EFI_HII_VARSTORE_NAME_VALUE
:
849 Link
= GetFirstNode (&Storage
->NameValueListHead
);
850 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
851 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
854 NewStringCpy (&Node
->Value
, Node
->EditValue
);
856 NewStringCpy (&Node
->EditValue
, Node
->Value
);
859 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
863 case EFI_HII_VARSTORE_EFI_VARIABLE
:
871 Get Value for given Name from a NameValue Storage.
873 @param Storage The NameValue Storage.
874 @param Name The Name.
875 @param Value The retured Value.
876 @param GetValueFrom Where to get source value, from EditValue or Value.
878 @retval EFI_SUCCESS Value found for given Name.
879 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
884 IN BROWSER_STORAGE
*Storage
,
886 IN OUT CHAR16
**Value
,
887 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
891 NAME_VALUE_NODE
*Node
;
893 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
894 return EFI_INVALID_PARAMETER
;
899 Link
= GetFirstNode (&Storage
->NameValueListHead
);
900 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
901 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
903 if (StrCmp (Name
, Node
->Name
) == 0) {
904 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
905 NewStringCpy (Value
, Node
->EditValue
);
907 NewStringCpy (Value
, Node
->Value
);
912 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
915 return EFI_NOT_FOUND
;
920 Set Value of given Name in a NameValue Storage.
922 @param Storage The NameValue Storage.
923 @param Name The Name.
924 @param Value The Value to set.
925 @param SetValueTo Whether update editValue or Value.
927 @retval EFI_SUCCESS Value found for given Name.
928 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
933 IN BROWSER_STORAGE
*Storage
,
936 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
940 NAME_VALUE_NODE
*Node
;
943 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
944 return EFI_INVALID_PARAMETER
;
947 Link
= GetFirstNode (&Storage
->NameValueListHead
);
948 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
949 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
951 if (StrCmp (Name
, Node
->Name
) == 0) {
952 if (SetValueTo
== GetSetValueWithEditBuffer
) {
953 Buffer
= Node
->EditValue
;
955 Buffer
= Node
->Value
;
957 if (Buffer
!= NULL
) {
960 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
961 ASSERT (Buffer
!= NULL
);
962 if (SetValueTo
== GetSetValueWithEditBuffer
) {
963 Node
->EditValue
= Buffer
;
965 Node
->Value
= Buffer
;
970 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
973 return EFI_NOT_FOUND
;
978 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
980 @param Storage The Storage to be conveted.
981 @param ConfigResp The returned <ConfigResp>.
982 @param ConfigRequest The ConfigRequest string.
984 @retval EFI_SUCCESS Convert success.
985 @retval EFI_INVALID_PARAMETER Incorrect storage type.
989 StorageToConfigResp (
990 IN BROWSER_STORAGE
*Storage
,
991 IN CHAR16
**ConfigResp
,
992 IN CHAR16
*ConfigRequest
998 NAME_VALUE_NODE
*Node
;
1000 Status
= EFI_SUCCESS
;
1002 switch (Storage
->Type
) {
1003 case EFI_HII_VARSTORE_BUFFER
:
1004 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1005 Status
= mHiiConfigRouting
->BlockToConfig (
1008 Storage
->EditBuffer
,
1015 case EFI_HII_VARSTORE_NAME_VALUE
:
1017 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1019 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1020 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1021 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1023 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1024 NewStringCat (ConfigResp
, L
"&");
1025 NewStringCat (ConfigResp
, Node
->Name
);
1026 NewStringCat (ConfigResp
, L
"=");
1027 NewStringCat (ConfigResp
, Node
->EditValue
);
1029 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1033 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1035 Status
= EFI_INVALID_PARAMETER
;
1044 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1046 @param Storage The Storage to receive the settings.
1047 @param ConfigResp The <ConfigResp> to be converted.
1049 @retval EFI_SUCCESS Convert success.
1050 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1054 ConfigRespToStorage (
1055 IN BROWSER_STORAGE
*Storage
,
1056 IN CHAR16
*ConfigResp
1060 EFI_STRING Progress
;
1066 Status
= EFI_SUCCESS
;
1068 switch (Storage
->Type
) {
1069 case EFI_HII_VARSTORE_BUFFER
:
1070 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1071 BufferSize
= Storage
->Size
;
1072 Status
= mHiiConfigRouting
->ConfigToBlock (
1075 Storage
->EditBuffer
,
1081 case EFI_HII_VARSTORE_NAME_VALUE
:
1082 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1083 if (StrPtr
== NULL
) {
1086 StrPtr
= StrStr (ConfigResp
, L
"&");
1087 while (StrPtr
!= NULL
) {
1091 StrPtr
= StrPtr
+ 1;
1093 StrPtr
= StrStr (StrPtr
, L
"=");
1094 if (StrPtr
== NULL
) {
1102 StrPtr
= StrPtr
+ 1;
1104 StrPtr
= StrStr (StrPtr
, L
"&");
1105 if (StrPtr
!= NULL
) {
1108 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
);
1112 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1114 Status
= EFI_INVALID_PARAMETER
;
1123 Get Question's current Value.
1125 @param FormSet FormSet data structure.
1126 @param Form Form data structure.
1127 @param Question Question to be initialized.
1128 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1130 @retval EFI_SUCCESS The function completed successfully.
1135 IN FORM_BROWSER_FORMSET
*FormSet
,
1136 IN FORM_BROWSER_FORM
*Form
,
1137 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1138 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1147 BROWSER_STORAGE
*Storage
;
1148 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1149 CHAR16
*ConfigRequest
;
1157 BOOLEAN IsBufferStorage
;
1163 Status
= EFI_SUCCESS
;
1167 if (GetValueFrom
>= GetSetValueWithMax
) {
1168 return EFI_INVALID_PARAMETER
;
1172 // Statement don't have storage, skip them
1174 if (Question
->QuestionId
== 0) {
1179 // Question value is provided by an Expression, evaluate it
1181 if (Question
->ValueExpression
!= NULL
) {
1182 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1183 if (!EFI_ERROR (Status
)) {
1184 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1185 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1186 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1187 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1188 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1190 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1191 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1193 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1195 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1196 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1202 // Get question value by read expression.
1204 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1205 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1206 if (!EFI_ERROR (Status
) &&
1207 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1209 // Only update question value to the valid result.
1211 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1212 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1213 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1214 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1215 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1217 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1218 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1220 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1222 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1223 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1229 // Question value is provided by RTC
1231 Storage
= Question
->Storage
;
1232 QuestionValue
= &Question
->HiiValue
.Value
;
1233 if (Storage
== NULL
) {
1235 // It's a Question without storage, or RTC date/time
1237 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1239 // Date and time define the same Flags bit
1241 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1242 case QF_DATE_STORAGE_TIME
:
1243 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1246 case QF_DATE_STORAGE_WAKEUP
:
1247 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1250 case QF_DATE_STORAGE_NORMAL
:
1253 // For date/time without storage
1258 if (EFI_ERROR (Status
)) {
1262 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1263 QuestionValue
->date
.Year
= EfiTime
.Year
;
1264 QuestionValue
->date
.Month
= EfiTime
.Month
;
1265 QuestionValue
->date
.Day
= EfiTime
.Day
;
1267 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1268 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1269 QuestionValue
->time
.Second
= EfiTime
.Second
;
1277 // Question value is provided by EFI variable
1279 StorageWidth
= Question
->StorageWidth
;
1280 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1281 if (Question
->BufferValue
!= NULL
) {
1282 Dst
= Question
->BufferValue
;
1284 Dst
= (UINT8
*) QuestionValue
;
1287 Status
= gRT
->GetVariable (
1288 Question
->VariableName
,
1295 // Always return success, even this EFI variable doesn't exist
1301 // Question Value is provided by Buffer Storage or NameValue Storage
1303 if (Question
->BufferValue
!= NULL
) {
1305 // This Question is password or orderedlist
1307 Dst
= Question
->BufferValue
;
1310 // Other type of Questions
1312 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1315 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1316 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1317 IsBufferStorage
= TRUE
;
1319 IsBufferStorage
= FALSE
;
1321 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1322 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1323 if (IsBufferStorage
) {
1324 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1326 // Copy from storage Edit buffer
1328 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1331 // Copy from storage Edit buffer
1333 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1337 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1338 if (EFI_ERROR (Status
)) {
1342 ASSERT (Value
!= NULL
);
1343 LengthStr
= StrLen (Value
);
1344 Status
= EFI_SUCCESS
;
1347 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1348 // Add string tail char L'\0' into Length
1350 Length
= StorageWidth
+ sizeof (CHAR16
);
1351 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1352 Status
= EFI_BUFFER_TOO_SMALL
;
1354 StringPtr
= (CHAR16
*) Dst
;
1355 ZeroMem (TemStr
, sizeof (TemStr
));
1356 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1357 StrnCpy (TemStr
, Value
+ Index
, 4);
1358 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1361 // Add tailing L'\0' character
1363 StringPtr
[Index
/4] = L
'\0';
1366 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1367 Status
= EFI_BUFFER_TOO_SMALL
;
1369 ZeroMem (TemStr
, sizeof (TemStr
));
1370 for (Index
= 0; Index
< LengthStr
; Index
++) {
1371 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1372 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1373 if ((Index
& 1) == 0) {
1374 Dst
[Index
/2] = DigitUint8
;
1376 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1385 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1387 // Request current settings from Configuration Driver
1389 if (FormSet
->ConfigAccess
== NULL
) {
1390 return EFI_NOT_FOUND
;
1394 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1395 // <ConfigHdr> + "&" + <VariableName>
1397 if (IsBufferStorage
) {
1398 Length
= StrLen (Storage
->ConfigHdr
);
1399 Length
+= StrLen (Question
->BlockName
);
1401 Length
= StrLen (Storage
->ConfigHdr
);
1402 Length
+= StrLen (Question
->VariableName
) + 1;
1404 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1405 ASSERT (ConfigRequest
!= NULL
);
1407 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1408 if (IsBufferStorage
) {
1409 StrCat (ConfigRequest
, Question
->BlockName
);
1411 StrCat (ConfigRequest
, L
"&");
1412 StrCat (ConfigRequest
, Question
->VariableName
);
1415 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1416 FormSet
->ConfigAccess
,
1421 FreePool (ConfigRequest
);
1422 if (EFI_ERROR (Status
)) {
1427 // Skip <ConfigRequest>
1429 if (IsBufferStorage
) {
1430 Value
= StrStr (Result
, L
"&VALUE");
1431 if (Value
== NULL
) {
1433 return EFI_NOT_FOUND
;
1440 Value
= Result
+ Length
;
1442 if (*Value
!= '=') {
1444 return EFI_NOT_FOUND
;
1447 // Skip '=', point to value
1452 // Suppress <AltResp> if any
1455 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1460 LengthStr
= StrLen (Value
);
1461 Status
= EFI_SUCCESS
;
1462 if (!IsBufferStorage
&& IsString
) {
1464 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1465 // Add string tail char L'\0' into Length
1467 Length
= StorageWidth
+ sizeof (CHAR16
);
1468 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1469 Status
= EFI_BUFFER_TOO_SMALL
;
1471 StringPtr
= (CHAR16
*) Dst
;
1472 ZeroMem (TemStr
, sizeof (TemStr
));
1473 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1474 StrnCpy (TemStr
, Value
+ Index
, 4);
1475 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1478 // Add tailing L'\0' character
1480 StringPtr
[Index
/4] = L
'\0';
1483 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1484 Status
= EFI_BUFFER_TOO_SMALL
;
1486 ZeroMem (TemStr
, sizeof (TemStr
));
1487 for (Index
= 0; Index
< LengthStr
; Index
++) {
1488 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1489 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1490 if ((Index
& 1) == 0) {
1491 Dst
[Index
/2] = DigitUint8
;
1493 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1499 if (EFI_ERROR (Status
)) {
1503 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1505 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1506 if (TemBuffer
== NULL
) {
1507 Status
= EFI_OUT_OF_RESOURCES
;
1510 Length
= Storage
->Size
;
1511 Status
= gRT
->GetVariable (
1518 if (EFI_ERROR (Status
)) {
1519 FreePool (TemBuffer
);
1523 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1525 FreePool (TemBuffer
);
1529 // Synchronize Edit Buffer
1531 if (IsBufferStorage
) {
1532 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1534 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
);
1537 if (Result
!= NULL
) {
1547 Save Question Value to edit copy(cached) or Storage(uncached).
1549 @param FormSet FormSet data structure.
1550 @param Form Form data structure.
1551 @param Question Pointer to the Question.
1552 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1554 @retval EFI_SUCCESS The function completed successfully.
1559 IN FORM_BROWSER_FORMSET
*FormSet
,
1560 IN FORM_BROWSER_FORM
*Form
,
1561 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1562 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1572 BROWSER_STORAGE
*Storage
;
1573 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1578 BOOLEAN IsBufferStorage
;
1585 Status
= EFI_SUCCESS
;
1587 if (SetValueTo
>= GetSetValueWithMax
) {
1588 return EFI_INVALID_PARAMETER
;
1592 // Statement don't have storage, skip them
1594 if (Question
->QuestionId
== 0) {
1599 // If Question value is provided by an Expression, then it is read only
1601 if (Question
->ValueExpression
!= NULL
) {
1606 // Before set question value, evaluate its write expression.
1608 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1609 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1610 if (EFI_ERROR (Status
)) {
1616 // Question value is provided by RTC
1618 Storage
= Question
->Storage
;
1619 QuestionValue
= &Question
->HiiValue
.Value
;
1620 if (Storage
== NULL
) {
1622 // It's a Question without storage, or RTC date/time
1624 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1626 // Date and time define the same Flags bit
1628 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1629 case QF_DATE_STORAGE_TIME
:
1630 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1633 case QF_DATE_STORAGE_WAKEUP
:
1634 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1637 case QF_DATE_STORAGE_NORMAL
:
1640 // For date/time without storage
1645 if (EFI_ERROR (Status
)) {
1649 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1650 EfiTime
.Year
= QuestionValue
->date
.Year
;
1651 EfiTime
.Month
= QuestionValue
->date
.Month
;
1652 EfiTime
.Day
= QuestionValue
->date
.Day
;
1654 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1655 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1656 EfiTime
.Second
= QuestionValue
->time
.Second
;
1659 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1660 Status
= gRT
->SetTime (&EfiTime
);
1662 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1670 // Question value is provided by EFI variable
1672 StorageWidth
= Question
->StorageWidth
;
1673 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1674 if (Question
->BufferValue
!= NULL
) {
1675 Src
= Question
->BufferValue
;
1677 Src
= (UINT8
*) QuestionValue
;
1680 Status
= gRT
->SetVariable (
1681 Question
->VariableName
,
1683 Storage
->Attributes
,
1691 // Question Value is provided by Buffer Storage or NameValue Storage
1693 if (Question
->BufferValue
!= NULL
) {
1694 Src
= Question
->BufferValue
;
1696 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1699 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1700 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1701 IsBufferStorage
= TRUE
;
1703 IsBufferStorage
= FALSE
;
1705 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1707 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1708 if (IsBufferStorage
) {
1709 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1711 // Copy to storage edit buffer
1713 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1714 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1716 // Copy to storage edit buffer
1718 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1723 // Allocate enough string buffer.
1726 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1727 Value
= AllocateZeroPool (BufferLen
);
1728 ASSERT (Value
!= NULL
);
1730 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1732 TemName
= (CHAR16
*) Src
;
1734 for (; *TemName
!= L
'\0'; TemName
++) {
1735 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1738 BufferLen
= StorageWidth
* 2 + 1;
1739 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1740 ASSERT (Value
!= NULL
);
1742 // Convert Buffer to Hex String
1744 TemBuffer
= Src
+ StorageWidth
- 1;
1746 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1747 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1751 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
);
1754 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1755 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1757 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1758 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1760 if (IsBufferStorage
) {
1761 Length
= StrLen (Question
->BlockName
) + 7;
1763 Length
= StrLen (Question
->VariableName
) + 2;
1765 if (!IsBufferStorage
&& IsString
) {
1766 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1768 Length
+= (StorageWidth
* 2);
1770 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1771 ASSERT (ConfigResp
!= NULL
);
1773 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1774 if (IsBufferStorage
) {
1775 StrCat (ConfigResp
, Question
->BlockName
);
1776 StrCat (ConfigResp
, L
"&VALUE=");
1778 StrCat (ConfigResp
, L
"&");
1779 StrCat (ConfigResp
, Question
->VariableName
);
1780 StrCat (ConfigResp
, L
"=");
1783 Value
= ConfigResp
+ StrLen (ConfigResp
);
1785 if (!IsBufferStorage
&& IsString
) {
1787 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1789 TemName
= (CHAR16
*) Src
;
1791 for (; *TemName
!= L
'\0'; TemName
++) {
1792 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1796 // Convert Buffer to Hex String
1798 TemBuffer
= Src
+ StorageWidth
- 1;
1800 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1801 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1806 // Convert to lower char.
1808 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1809 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1810 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1815 // Submit Question Value to Configuration Driver
1817 if (FormSet
->ConfigAccess
!= NULL
) {
1818 Status
= FormSet
->ConfigAccess
->RouteConfig (
1819 FormSet
->ConfigAccess
,
1823 if (EFI_ERROR (Status
)) {
1824 FreePool (ConfigResp
);
1828 FreePool (ConfigResp
);
1830 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1832 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1833 if (TemBuffer
== NULL
) {
1834 Status
= EFI_OUT_OF_RESOURCES
;
1837 Length
= Storage
->Size
;
1838 Status
= gRT
->GetVariable (
1846 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1848 Status
= gRT
->SetVariable (
1851 Storage
->Attributes
,
1855 FreePool (TemBuffer
);
1856 if (EFI_ERROR (Status
)){
1861 // Sync storage, from editbuffer to buffer.
1863 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1871 Perform inconsistent check for a Form.
1873 @param FormSet FormSet data structure.
1874 @param Form Form data structure.
1875 @param Question The Question to be validated.
1876 @param Type Validation type: InConsistent or NoSubmit
1878 @retval EFI_SUCCESS Form validation pass.
1879 @retval other Form validation failed.
1884 IN FORM_BROWSER_FORMSET
*FormSet
,
1885 IN FORM_BROWSER_FORM
*Form
,
1886 IN FORM_BROWSER_STATEMENT
*Question
,
1892 LIST_ENTRY
*ListHead
;
1895 FORM_EXPRESSION
*Expression
;
1897 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1898 ListHead
= &Question
->InconsistentListHead
;
1899 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1900 ListHead
= &Question
->NoSubmitListHead
;
1902 return EFI_UNSUPPORTED
;
1905 Link
= GetFirstNode (ListHead
);
1906 while (!IsNull (ListHead
, Link
)) {
1907 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1910 // Evaluate the expression
1912 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1913 if (EFI_ERROR (Status
)) {
1917 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1919 // Condition meet, show up error message
1921 if (Expression
->Error
!= 0) {
1922 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1924 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1925 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1929 return EFI_NOT_READY
;
1932 Link
= GetNextNode (ListHead
, Link
);
1940 Perform NoSubmit check for each Form in FormSet.
1942 @param FormSet FormSet data structure.
1943 @param CurrentForm Current input form data structure.
1945 @retval EFI_SUCCESS Form validation pass.
1946 @retval other Form validation failed.
1951 IN FORM_BROWSER_FORMSET
*FormSet
,
1952 IN FORM_BROWSER_FORM
*CurrentForm
1957 FORM_BROWSER_STATEMENT
*Question
;
1958 FORM_BROWSER_FORM
*Form
;
1959 LIST_ENTRY
*LinkForm
;
1961 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1962 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1963 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1964 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1966 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
1970 Link
= GetFirstNode (&Form
->StatementListHead
);
1971 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1972 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1974 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
1975 if (EFI_ERROR (Status
)) {
1979 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1987 Fill storage's edit copy with settings requested from Configuration Driver.
1989 @param FormSet FormSet data structure.
1990 @param ConfigInfo The config info related to this form.
1991 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
1992 editbuffer to buffer
1993 if TRUE, copy the editbuffer to the buffer.
1994 if FALSE, copy the buffer to the editbuffer.
1996 @retval EFI_SUCCESS The function completed successfully.
2000 SynchronizeStorageForForm (
2001 IN FORM_BROWSER_FORMSET
*FormSet
,
2002 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2003 IN BOOLEAN SyncOrRestore
2007 EFI_STRING Progress
;
2011 NAME_VALUE_NODE
*Node
;
2015 Status
= EFI_SUCCESS
;
2017 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2018 return EFI_NOT_FOUND
;
2021 if (ConfigInfo
->ElementCount
== 0) {
2023 // Skip if there is no RequestElement
2028 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2029 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2030 BufferSize
= ConfigInfo
->Storage
->Size
;
2032 if (SyncOrRestore
) {
2033 Src
= ConfigInfo
->Storage
->EditBuffer
;
2034 Dst
= ConfigInfo
->Storage
->Buffer
;
2036 Src
= ConfigInfo
->Storage
->Buffer
;
2037 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2040 Status
= mHiiConfigRouting
->BlockToConfig(
2042 ConfigInfo
->ConfigRequest
,
2048 if (EFI_ERROR (Status
)) {
2052 Status
= mHiiConfigRouting
->ConfigToBlock (
2059 if (Result
!= NULL
) {
2062 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2063 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2064 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2065 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2067 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2068 if (SyncOrRestore
) {
2069 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2071 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2075 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2083 When discard the question value, call the callback function with Changed type
2084 to inform the hii driver.
2086 @param FormSet FormSet data structure.
2087 @param Form Form data structure.
2091 SendDiscardInfoToDriver (
2092 IN FORM_BROWSER_FORMSET
*FormSet
,
2093 IN FORM_BROWSER_FORM
*Form
2097 FORM_BROWSER_STATEMENT
*Question
;
2099 EFI_HII_VALUE HiiValue
;
2101 BOOLEAN ValueChanged
;
2102 EFI_IFR_TYPE_VALUE
*TypeValue
;
2103 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2105 ValueChanged
= FALSE
;
2108 if(!Form
->NvUpdateRequired
) {
2112 Link
= GetFirstNode (&Form
->StatementListHead
);
2113 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2114 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2115 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2117 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2121 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2125 if (Question
->BufferValue
!= NULL
) {
2126 BufferValue
= AllocateZeroPool (Question
->StorageWidth
);
2127 ASSERT (BufferValue
!= NULL
);
2128 CopyMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
);
2130 HiiValue
.Type
= Question
->HiiValue
.Type
;
2131 CopyMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2134 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
2135 if (EFI_ERROR (Status
)) {
2136 if (BufferValue
!= NULL
) {
2137 FreePool (BufferValue
);
2143 if (Question
->BufferValue
!= NULL
) {
2144 if (CompareMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
)) {
2145 ValueChanged
= TRUE
;
2148 if (CompareMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
))) {
2149 ValueChanged
= TRUE
;
2153 if (BufferValue
!= NULL
) {
2154 FreePool (BufferValue
);
2158 if (!ValueChanged
) {
2162 ValueChanged
= FALSE
;
2164 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2165 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2167 TypeValue
= &Question
->HiiValue
.Value
;
2170 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2171 FormSet
->ConfigAccess
->Callback (
2172 FormSet
->ConfigAccess
,
2173 EFI_BROWSER_ACTION_CHANGED
,
2174 Question
->QuestionId
,
2175 Question
->HiiValue
.Type
,
2183 Validate the FormSet. If the formset is not validate, remove it from the list.
2185 @param FormSet The input FormSet which need to validate.
2187 @retval TRUE The handle is validate.
2188 @retval FALSE The handle is invalidate.
2193 FORM_BROWSER_FORMSET
*FormSet
2196 EFI_HII_HANDLE
*HiiHandles
;
2200 ASSERT (FormSet
!= NULL
);
2203 // Get all the Hii handles
2205 HiiHandles
= HiiGetHiiHandles (NULL
);
2206 ASSERT (HiiHandles
!= NULL
);
2209 // Search for formset of each class type
2211 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2212 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2219 CleanBrowserStorage(FormSet
);
2220 RemoveEntryList (&FormSet
->Link
);
2221 DestroyFormSet (FormSet
);
2224 FreePool (HiiHandles
);
2230 Discard data based on the input setting scope (Form, FormSet or System).
2232 @param FormSet FormSet data structure.
2233 @param Form Form data structure.
2234 @param SettingScope Setting Scope for Discard action.
2236 @retval EFI_SUCCESS The function completed successfully.
2237 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2242 IN FORM_BROWSER_FORMSET
*FormSet
,
2243 IN FORM_BROWSER_FORM
*Form
,
2244 IN BROWSER_SETTING_SCOPE SettingScope
2248 FORMSET_STORAGE
*Storage
;
2249 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2250 FORM_BROWSER_FORMSET
*LocalFormSet
;
2253 // Check the supported setting level.
2255 if (SettingScope
>= MaxLevel
) {
2256 return EFI_UNSUPPORTED
;
2259 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2261 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2262 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2263 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2264 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2266 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2271 // Skip if there is no RequestElement
2273 if (ConfigInfo
->ElementCount
== 0) {
2278 // Prepare <ConfigResp>
2280 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2283 // Call callback with Changed type to inform the driver.
2285 SendDiscardInfoToDriver (FormSet
, Form
);
2288 Form
->NvUpdateRequired
= FALSE
;
2289 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2292 // Discard Buffer storage or Name/Value storage
2294 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2295 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2296 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2297 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2299 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2304 // Skip if there is no RequestElement
2306 if (Storage
->ElementCount
== 0) {
2310 SynchronizeStorage(Storage
->BrowserStorage
, FALSE
);
2313 Link
= GetFirstNode (&FormSet
->FormListHead
);
2314 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2315 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2316 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2319 // Call callback with Changed type to inform the driver.
2321 SendDiscardInfoToDriver (FormSet
, Form
);
2324 UpdateNvInfoInForm (FormSet
, FALSE
);
2325 } else if (SettingScope
== SystemLevel
) {
2327 // System Level Discard.
2331 // Discard changed value for each FormSet in the maintain list.
2333 Link
= GetFirstNode (&gBrowserFormSetList
);
2334 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2335 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2336 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2337 if (!ValidateFormSet(LocalFormSet
)) {
2340 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2341 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2343 // Remove maintain backup list after discard except for the current using FormSet.
2345 CleanBrowserStorage(LocalFormSet
);
2346 RemoveEntryList (&LocalFormSet
->Link
);
2347 DestroyFormSet (LocalFormSet
);
2356 Submit data based on the input Setting level (Form, FormSet or System).
2358 @param FormSet FormSet data structure.
2359 @param Form Form data structure.
2360 @param SettingScope Setting Scope for Submit action.
2362 @retval EFI_SUCCESS The function completed successfully.
2363 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2368 IN FORM_BROWSER_FORMSET
*FormSet
,
2369 IN FORM_BROWSER_FORM
*Form
,
2370 IN BROWSER_SETTING_SCOPE SettingScope
2375 EFI_STRING ConfigResp
;
2376 EFI_STRING Progress
;
2377 BROWSER_STORAGE
*Storage
;
2378 FORMSET_STORAGE
*FormSetStorage
;
2381 FORM_BROWSER_FORMSET
*LocalFormSet
;
2382 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2385 // Check the supported setting level.
2387 if (SettingScope
>= MaxLevel
) {
2388 return EFI_UNSUPPORTED
;
2392 // Validate the Form by NoSubmit check
2394 Status
= EFI_SUCCESS
;
2395 if (SettingScope
== FormLevel
) {
2396 Status
= NoSubmitCheck (FormSet
, Form
);
2397 } else if (SettingScope
== FormSetLevel
) {
2398 Status
= NoSubmitCheck (FormSet
, NULL
);
2400 if (EFI_ERROR (Status
)) {
2404 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2406 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2407 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2408 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2409 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2411 Storage
= ConfigInfo
->Storage
;
2412 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2417 // Skip if there is no RequestElement
2419 if (ConfigInfo
->ElementCount
== 0) {
2424 // 1. Prepare <ConfigResp>
2426 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
);
2427 if (EFI_ERROR (Status
)) {
2432 // 2. Set value to hii driver or efi variable.
2434 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2435 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2437 // Send <ConfigResp> to Configuration Driver
2439 if (FormSet
->ConfigAccess
!= NULL
) {
2440 Status
= FormSet
->ConfigAccess
->RouteConfig (
2441 FormSet
->ConfigAccess
,
2445 if (EFI_ERROR (Status
)) {
2446 FreePool (ConfigResp
);
2450 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2452 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2453 if (TmpBuf
== NULL
) {
2454 Status
= EFI_OUT_OF_RESOURCES
;
2458 BufferSize
= Storage
->Size
;
2459 Status
= gRT
->GetVariable (
2466 if (EFI_ERROR (Status
)) {
2468 FreePool (ConfigResp
);
2471 ASSERT (BufferSize
== Storage
->Size
);
2472 Status
= mHiiConfigRouting
->ConfigToBlock (
2479 if (EFI_ERROR (Status
)) {
2481 FreePool (ConfigResp
);
2485 Status
= gRT
->SetVariable (
2488 Storage
->Attributes
,
2493 if (EFI_ERROR (Status
)) {
2494 FreePool (ConfigResp
);
2498 FreePool (ConfigResp
);
2500 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2502 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2506 // 4. Update the NV flag.
2508 Form
->NvUpdateRequired
= FALSE
;
2509 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2511 // Submit Buffer storage or Name/Value storage
2513 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2514 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2515 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2516 Storage
= FormSetStorage
->BrowserStorage
;
2517 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2519 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2524 // Skip if there is no RequestElement
2526 if (FormSetStorage
->ElementCount
== 0) {
2531 // 1. Prepare <ConfigResp>
2533 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
);
2534 if (EFI_ERROR (Status
)) {
2538 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2539 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2542 // 2. Send <ConfigResp> to Configuration Driver
2544 if (FormSet
->ConfigAccess
!= NULL
) {
2545 Status
= FormSet
->ConfigAccess
->RouteConfig (
2546 FormSet
->ConfigAccess
,
2550 if (EFI_ERROR (Status
)) {
2551 FreePool (ConfigResp
);
2555 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2557 // 1&2. Set the edit data to the variable.
2560 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2561 if (TmpBuf
== NULL
) {
2562 Status
= EFI_OUT_OF_RESOURCES
;
2565 BufferSize
= Storage
->Size
;
2566 Status
= gRT
->GetVariable (
2573 ASSERT (BufferSize
== Storage
->Size
);
2574 Status
= mHiiConfigRouting
->ConfigToBlock (
2581 if (EFI_ERROR (Status
)) {
2583 FreePool (ConfigResp
);
2587 Status
= gRT
->SetVariable (
2590 Storage
->Attributes
,
2594 if (EFI_ERROR (Status
)) {
2596 FreePool (ConfigResp
);
2601 FreePool (ConfigResp
);
2603 // 3. Config success, update storage shadow Buffer
2605 SynchronizeStorage (Storage
, TRUE
);
2609 // 4. Update the NV flag.
2611 UpdateNvInfoInForm (FormSet
, FALSE
);
2612 } else if (SettingScope
== SystemLevel
) {
2614 // System Level Save.
2618 // Save changed value for each FormSet in the maintain list.
2620 Link
= GetFirstNode (&gBrowserFormSetList
);
2621 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2622 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2623 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2624 if (!ValidateFormSet(LocalFormSet
)) {
2627 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2628 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2630 // Remove maintain backup list after save except for the current using FormSet.
2632 CleanBrowserStorage(LocalFormSet
);
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 BROWSER_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 BROWSER_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 Remove the Request element from the Config Request.
3446 @param Storage Pointer to the browser storage.
3447 @param RequestElement The pointer to the Request element.
3452 IN OUT BROWSER_STORAGE
*Storage
,
3453 IN CHAR16
*RequestElement
3459 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3461 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3463 if (NewStr
== NULL
) {
3468 // Remove this element from this ConfigRequest.
3471 NewStr
+= StrLen (RequestElement
);
3472 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3474 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3478 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3480 @param Storage Pointer to the browser storage.
3481 @param ConfigRequest The pointer to the Request element.
3485 RemoveConfigRequest (
3486 BROWSER_STORAGE
*Storage
,
3487 CHAR16
*ConfigRequest
3490 CHAR16
*RequestElement
;
3491 CHAR16
*NextRequestElement
;
3494 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3496 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3501 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3503 SearchKey
= L
"&OFFSET";
3507 // Find SearchKey storage
3509 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3510 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3511 ASSERT (RequestElement
!= NULL
);
3512 RequestElement
= StrStr (RequestElement
, SearchKey
);
3514 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3517 while (RequestElement
!= NULL
) {
3519 // +1 to avoid find header itself.
3521 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3524 // The last Request element in configRequest string.
3526 if (NextRequestElement
!= NULL
) {
3528 // Replace "&" with '\0'.
3530 *NextRequestElement
= L
'\0';
3533 RemoveElement (Storage
, RequestElement
);
3535 if (NextRequestElement
!= NULL
) {
3537 // Restore '&' with '\0' for later used.
3539 *NextRequestElement
= L
'&';
3542 RequestElement
= NextRequestElement
;
3546 // If no request element remain, just remove the ConfigRequest string.
3548 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3549 FreePool (Storage
->ConfigRequest
);
3550 Storage
->ConfigRequest
= NULL
;
3551 Storage
->SpareStrLen
= 0;
3556 Base on the current formset info, clean the ConfigRequest string in browser storage.
3558 @param FormSet Pointer of the FormSet
3562 CleanBrowserStorage (
3563 IN OUT FORM_BROWSER_FORMSET
*FormSet
3567 FORMSET_STORAGE
*Storage
;
3569 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3570 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3571 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3572 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3574 if ((Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_BUFFER
) &&
3575 (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
)) {
3579 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3583 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
3588 Check whether current element in the ConfigReqeust string.
3590 @param BrowserStorage Storage which includes ConfigReqeust.
3591 @param RequestElement New element need to check.
3593 @retval TRUE The Element is in the ConfigReqeust string.
3594 @retval FALSE The Element not in the configReqeust String.
3599 BROWSER_STORAGE
*BrowserStorage
,
3600 CHAR16
*RequestElement
3603 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3607 Append the Request element to the Config Request.
3609 @param ConfigRequest Current ConfigRequest info.
3610 @param SpareStrLen Current remain free buffer for config reqeust.
3611 @param RequestElement New Request element.
3615 AppendConfigRequest (
3616 IN OUT CHAR16
**ConfigRequest
,
3617 IN OUT UINTN
*SpareStrLen
,
3618 IN CHAR16
*RequestElement
3625 StrLength
= StrLen (RequestElement
);
3628 // Append <RequestElement> to <ConfigRequest>
3630 if (StrLength
> *SpareStrLen
) {
3632 // Old String buffer is not sufficient for RequestElement, allocate a new one
3634 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3635 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3636 ASSERT (NewStr
!= NULL
);
3638 if (*ConfigRequest
!= NULL
) {
3639 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3640 FreePool (*ConfigRequest
);
3642 *ConfigRequest
= NewStr
;
3643 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3646 StrCat (*ConfigRequest
, RequestElement
);
3647 *SpareStrLen
-= StrLength
;
3651 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3653 @param Storage Form set Storage.
3654 @param ConfigRequest Return the ConfigRequest info.
3656 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3657 @retval FALSE All elements covered by current used elements.
3661 ConfigRequestAdjust (
3662 IN FORMSET_STORAGE
*Storage
,
3663 OUT CHAR16
**ConfigRequest
3666 CHAR16
*RequestElement
;
3667 CHAR16
*NextRequestElement
;
3677 if (Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3678 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3679 *ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3683 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3685 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3690 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3692 SearchKey
= L
"&OFFSET";
3696 // Prepare the config header.
3698 RetBuf
= AllocateCopyPool(StrSize (Storage
->BrowserStorage
->ConfigHdr
), Storage
->BrowserStorage
->ConfigHdr
);
3699 ASSERT (RetBuf
!= NULL
);
3702 // Find SearchKey storage
3704 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3705 RequestElement
= StrStr (Storage
->ConfigRequest
, L
"PATH");
3706 ASSERT (RequestElement
!= NULL
);
3707 RequestElement
= StrStr (RequestElement
, SearchKey
);
3709 RequestElement
= StrStr (Storage
->ConfigRequest
, SearchKey
);
3712 while (RequestElement
!= NULL
) {
3714 // +1 to avoid find header itself.
3716 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3719 // The last Request element in configRequest string.
3721 if (NextRequestElement
!= NULL
) {
3723 // Replace "&" with '\0'.
3725 *NextRequestElement
= L
'\0';
3728 if (!ElementValidation (Storage
->BrowserStorage
, RequestElement
)) {
3730 // Add this element to the Storage->BrowserStorage->AllRequestElement.
3732 AppendConfigRequest(&Storage
->BrowserStorage
->ConfigRequest
, &Storage
->BrowserStorage
->SpareStrLen
, RequestElement
);
3733 AppendConfigRequest (&RetBuf
, &SpareBufLen
, RequestElement
);
3737 if (NextRequestElement
!= NULL
) {
3739 // Restore '&' with '\0' for later used.
3741 *NextRequestElement
= L
'&';
3744 RequestElement
= NextRequestElement
;
3748 *ConfigRequest
= RetBuf
;
3757 Fill storage's edit copy with settings requested from Configuration Driver.
3759 @param FormSet FormSet data structure.
3760 @param Storage Buffer Storage.
3762 @retval EFI_SUCCESS The function completed successfully.
3767 IN FORM_BROWSER_FORMSET
*FormSet
,
3768 IN FORMSET_STORAGE
*Storage
3772 EFI_STRING Progress
;
3775 CHAR16
*ConfigRequest
;
3777 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3781 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3782 Status
= EFI_SUCCESS
;
3784 // EFI varstore data all get from variable, so no need to get again.
3786 if (Storage
->BrowserStorage
->ReferenceCount
== 1) {
3787 Status
= gRT
->GetVariable (
3788 Storage
->BrowserStorage
->Name
,
3789 &Storage
->BrowserStorage
->Guid
,
3791 (UINTN
*)&Storage
->BrowserStorage
->Size
,
3792 Storage
->BrowserStorage
->EditBuffer
3798 if (FormSet
->ConfigAccess
== NULL
) {
3799 return EFI_NOT_FOUND
;
3802 if (Storage
->ElementCount
== 0) {
3804 // Skip if there is no RequestElement
3810 // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig
3811 // will used to call ExtractConfig.
3813 if (!ConfigRequestAdjust(Storage
, &ConfigRequest
)) {
3818 // Request current settings from Configuration Driver
3820 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3821 FormSet
->ConfigAccess
,
3826 FreePool (ConfigRequest
);
3828 if (EFI_ERROR (Status
)) {
3833 // Convert Result from <ConfigAltResp> to <ConfigResp>
3835 StrPtr
= StrStr (Result
, L
"&GUID=");
3836 if (StrPtr
!= NULL
) {
3840 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
3846 Get current setting of Questions.
3848 @param FormSet FormSet data structure.
3850 @retval EFI_SUCCESS The function completed successfully.
3854 InitializeCurrentSetting (
3855 IN OUT FORM_BROWSER_FORMSET
*FormSet
3860 FORMSET_STORAGE
*Storage
;
3861 FORMSET_STORAGE
*StorageSrc
;
3862 FORMSET_STORAGE
*OldStorage
;
3863 FORM_BROWSER_FORM
*Form
;
3864 FORM_BROWSER_FORM
*Form2
;
3868 // Extract default from IFR binary for no storage questions.
3870 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
3873 // Request current settings from Configuration Driver
3875 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3876 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3877 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3880 if (gOldFormSet
!= NULL
) {
3882 // Try to find the Storage in backup formset gOldFormSet
3884 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3885 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3886 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3888 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3889 OldStorage
= StorageSrc
;
3893 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3898 // Storage is not found in backup formset and current global storage not has other driver used,
3899 // request it from ConfigDriver
3901 if (OldStorage
== NULL
) {
3902 Status
= LoadStorage (FormSet
, Storage
);
3904 if (EFI_ERROR (Status
)) {
3906 // If get last time changed value failed, extract default from IFR binary
3908 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
3910 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3911 // in current situation.
3913 UpdateNvInfoInForm (FormSet
, FALSE
);
3917 // Now Edit Buffer is filled with default values(lower priority) or current
3918 // settings(higher priority), sychronize it to shadow Buffer
3920 SynchronizeStorage (Storage
->BrowserStorage
, TRUE
);
3923 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3927 // If has old formset, get the old nv update status.
3929 if (gOldFormSet
!= NULL
) {
3930 Link
= GetFirstNode (&FormSet
->FormListHead
);
3931 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3932 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3934 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3935 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3936 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3938 if (Form
->FormId
== Form2
->FormId
) {
3939 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3943 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3945 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3954 Fetch the Ifr binary data of a FormSet.
3956 @param Handle PackageList Handle
3957 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3958 specified (NULL or zero GUID), take the first
3959 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3960 found in package list.
3961 On output, GUID of the formset found(if not NULL).
3962 @param BinaryLength The length of the FormSet IFR binary.
3963 @param BinaryData The buffer designed to receive the FormSet.
3965 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3966 BufferLength was updated.
3967 @retval EFI_INVALID_PARAMETER The handle is unknown.
3968 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3969 be found with the requested FormId.
3974 IN EFI_HII_HANDLE Handle
,
3975 IN OUT EFI_GUID
*FormSetGuid
,
3976 OUT UINTN
*BinaryLength
,
3977 OUT UINT8
**BinaryData
3981 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3987 UINT32 PackageListLength
;
3988 EFI_HII_PACKAGE_HEADER PackageHeader
;
3990 UINT8 NumberOfClassGuid
;
3991 BOOLEAN ClassGuidMatch
;
3992 EFI_GUID
*ClassGuid
;
3993 EFI_GUID
*ComparingGuid
;
3997 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4000 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4002 if (FormSetGuid
== NULL
) {
4003 ComparingGuid
= &gZeroGuid
;
4005 ComparingGuid
= FormSetGuid
;
4009 // Get HII PackageList
4012 HiiPackageList
= NULL
;
4013 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4014 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4015 HiiPackageList
= AllocatePool (BufferSize
);
4016 ASSERT (HiiPackageList
!= NULL
);
4018 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4020 if (EFI_ERROR (Status
)) {
4023 ASSERT (HiiPackageList
!= NULL
);
4026 // Get Form package from this HII package List
4028 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4030 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4032 ClassGuidMatch
= FALSE
;
4033 while (Offset
< PackageListLength
) {
4034 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4035 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4037 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4039 // Search FormSet in this Form Package
4041 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4042 while (Offset2
< PackageHeader
.Length
) {
4043 OpCodeData
= Package
+ Offset2
;
4045 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4047 // Try to compare against formset GUID
4049 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4050 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4054 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4056 // Try to compare against formset class GUID
4058 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4059 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4060 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4061 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4062 ClassGuidMatch
= TRUE
;
4066 if (ClassGuidMatch
) {
4069 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4070 ClassGuidMatch
= TRUE
;
4075 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4078 if (Offset2
< PackageHeader
.Length
) {
4080 // Target formset found
4086 Offset
+= PackageHeader
.Length
;
4089 if (Offset
>= PackageListLength
) {
4091 // Form package not found in this Package List
4093 FreePool (HiiPackageList
);
4094 return EFI_NOT_FOUND
;
4097 if (FormSetGuid
!= NULL
) {
4099 // Return the FormSet GUID
4101 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4105 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4106 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4107 // of the Form Package.
4109 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4110 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4112 FreePool (HiiPackageList
);
4114 if (*BinaryData
== NULL
) {
4115 return EFI_OUT_OF_RESOURCES
;
4123 Initialize the internal data structure of a FormSet.
4125 @param Handle PackageList Handle
4126 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4127 specified (NULL or zero GUID), take the first
4128 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4129 found in package list.
4130 On output, GUID of the formset found(if not NULL).
4131 @param FormSet FormSet data structure.
4132 @param UpdateGlobalVar Whether need to update the global variable.
4134 @retval EFI_SUCCESS The function completed successfully.
4135 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4140 IN EFI_HII_HANDLE Handle
,
4141 IN OUT EFI_GUID
*FormSetGuid
,
4142 OUT FORM_BROWSER_FORMSET
*FormSet
,
4143 IN BOOLEAN UpdateGlobalVar
4147 EFI_HANDLE DriverHandle
;
4150 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4151 if (EFI_ERROR (Status
)) {
4155 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4156 FormSet
->HiiHandle
= Handle
;
4157 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4160 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4162 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4163 if (EFI_ERROR (Status
)) {
4166 FormSet
->DriverHandle
= DriverHandle
;
4167 Status
= gBS
->HandleProtocol (
4169 &gEfiHiiConfigAccessProtocolGuid
,
4170 (VOID
**) &FormSet
->ConfigAccess
4172 if (EFI_ERROR (Status
)) {
4174 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4175 // list, then there will be no configuration action required
4177 FormSet
->ConfigAccess
= NULL
;
4181 // Parse the IFR binary OpCodes
4183 Status
= ParseOpCodes (FormSet
);
4184 if (EFI_ERROR (Status
)) {
4189 // If not need to update the global variable, just return.
4191 if (!UpdateGlobalVar
) {
4196 // Set VFR type by FormSet SubClass field
4198 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
4199 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
4200 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
4204 // Set VFR type by FormSet class guid
4206 for (Index
= 0; Index
< 3; Index
++) {
4207 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
4208 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
4213 gFunctionKeySetting
= ENABLE_FUNCTION_KEY_SETTING
;
4215 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
4216 gFrontPageHandle
= FormSet
->HiiHandle
;
4217 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
4221 // Match GUID to find out the function key setting. If match fail, use the default setting.
4223 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
4224 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
4226 // Update the function key setting.
4228 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
4237 Save globals used by previous call to SendForm(). SendForm() may be called from
4238 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4239 So, save globals of previous call to SendForm() and restore them upon exit.
4243 SaveBrowserContext (
4247 BROWSER_CONTEXT
*Context
;
4249 gBrowserContextCount
++;
4250 if (gBrowserContextCount
== 1) {
4252 // This is not reentry of SendForm(), no context to save
4257 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4258 ASSERT (Context
!= NULL
);
4260 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4263 // Save FormBrowser context
4265 Context
->BannerData
= gBannerData
;
4266 Context
->ClassOfVfr
= gClassOfVfr
;
4267 Context
->FunctionKeySetting
= gFunctionKeySetting
;
4268 Context
->ResetRequired
= gResetRequired
;
4269 Context
->Direction
= gDirection
;
4270 Context
->EnterString
= gEnterString
;
4271 Context
->EnterCommitString
= gEnterCommitString
;
4272 Context
->EnterEscapeString
= gEnterEscapeString
;
4273 Context
->EscapeString
= gEscapeString
;
4274 Context
->MoveHighlight
= gMoveHighlight
;
4275 Context
->MakeSelection
= gMakeSelection
;
4276 Context
->DecNumericInput
= gDecNumericInput
;
4277 Context
->HexNumericInput
= gHexNumericInput
;
4278 Context
->ToggleCheckBox
= gToggleCheckBox
;
4279 Context
->PromptForData
= gPromptForData
;
4280 Context
->PromptForPassword
= gPromptForPassword
;
4281 Context
->PromptForNewPassword
= gPromptForNewPassword
;
4282 Context
->ConfirmPassword
= gConfirmPassword
;
4283 Context
->ConfirmError
= gConfirmError
;
4284 Context
->PassowordInvalid
= gPassowordInvalid
;
4285 Context
->PressEnter
= gPressEnter
;
4286 Context
->EmptyString
= gEmptyString
;
4287 Context
->AreYouSure
= gAreYouSure
;
4288 Context
->YesResponse
= gYesResponse
;
4289 Context
->NoResponse
= gNoResponse
;
4290 Context
->MiniString
= gMiniString
;
4291 Context
->PlusString
= gPlusString
;
4292 Context
->MinusString
= gMinusString
;
4293 Context
->AdjustNumber
= gAdjustNumber
;
4294 Context
->SaveChanges
= gSaveChanges
;
4295 Context
->OptionMismatch
= gOptionMismatch
;
4296 Context
->FormSuppress
= gFormSuppress
;
4297 Context
->PromptBlockWidth
= gPromptBlockWidth
;
4298 Context
->OptionBlockWidth
= gOptionBlockWidth
;
4299 Context
->HelpBlockWidth
= gHelpBlockWidth
;
4300 Context
->OldFormSet
= gOldFormSet
;
4301 Context
->MenuRefreshHead
= gMenuRefreshHead
;
4302 Context
->ProtocolNotFound
= gProtocolNotFound
;
4304 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
4305 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
4308 // Insert to FormBrowser context list
4310 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4315 Restore globals used by previous call to SendForm().
4319 RestoreBrowserContext (
4324 BROWSER_CONTEXT
*Context
;
4326 ASSERT (gBrowserContextCount
!= 0);
4327 gBrowserContextCount
--;
4328 if (gBrowserContextCount
== 0) {
4330 // This is not reentry of SendForm(), no context to restore
4335 ASSERT (!IsListEmpty (&gBrowserContextList
));
4337 Link
= GetFirstNode (&gBrowserContextList
);
4338 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4341 // Restore FormBrowser context
4343 gBannerData
= Context
->BannerData
;
4344 gClassOfVfr
= Context
->ClassOfVfr
;
4345 gFunctionKeySetting
= Context
->FunctionKeySetting
;
4346 gResetRequired
= Context
->ResetRequired
;
4347 gDirection
= Context
->Direction
;
4348 gEnterString
= Context
->EnterString
;
4349 gEnterCommitString
= Context
->EnterCommitString
;
4350 gEnterEscapeString
= Context
->EnterEscapeString
;
4351 gEscapeString
= Context
->EscapeString
;
4352 gMoveHighlight
= Context
->MoveHighlight
;
4353 gMakeSelection
= Context
->MakeSelection
;
4354 gDecNumericInput
= Context
->DecNumericInput
;
4355 gHexNumericInput
= Context
->HexNumericInput
;
4356 gToggleCheckBox
= Context
->ToggleCheckBox
;
4357 gPromptForData
= Context
->PromptForData
;
4358 gPromptForPassword
= Context
->PromptForPassword
;
4359 gPromptForNewPassword
= Context
->PromptForNewPassword
;
4360 gConfirmPassword
= Context
->ConfirmPassword
;
4361 gConfirmError
= Context
->ConfirmError
;
4362 gPassowordInvalid
= Context
->PassowordInvalid
;
4363 gPressEnter
= Context
->PressEnter
;
4364 gEmptyString
= Context
->EmptyString
;
4365 gAreYouSure
= Context
->AreYouSure
;
4366 gYesResponse
= Context
->YesResponse
;
4367 gNoResponse
= Context
->NoResponse
;
4368 gMiniString
= Context
->MiniString
;
4369 gPlusString
= Context
->PlusString
;
4370 gMinusString
= Context
->MinusString
;
4371 gAdjustNumber
= Context
->AdjustNumber
;
4372 gSaveChanges
= Context
->SaveChanges
;
4373 gOptionMismatch
= Context
->OptionMismatch
;
4374 gFormSuppress
= Context
->FormSuppress
;
4375 gPromptBlockWidth
= Context
->PromptBlockWidth
;
4376 gOptionBlockWidth
= Context
->OptionBlockWidth
;
4377 gHelpBlockWidth
= Context
->HelpBlockWidth
;
4378 gOldFormSet
= Context
->OldFormSet
;
4379 gMenuRefreshHead
= Context
->MenuRefreshHead
;
4380 gProtocolNotFound
= Context
->ProtocolNotFound
;
4382 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
4383 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
4386 // Remove from FormBrowser context list
4388 RemoveEntryList (&Context
->Link
);
4389 gBS
->FreePool (Context
);
4393 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4395 @param Handle The Hii Handle.
4397 @return the found FormSet context. If no found, NULL will return.
4400 FORM_BROWSER_FORMSET
*
4401 GetFormSetFromHiiHandle (
4402 EFI_HII_HANDLE Handle
4406 FORM_BROWSER_FORMSET
*FormSet
;
4408 Link
= GetFirstNode (&gBrowserFormSetList
);
4409 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4410 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4411 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4412 if (!ValidateFormSet(FormSet
)) {
4415 if (FormSet
->HiiHandle
== Handle
) {
4424 Check whether the input HII handle is the FormSet that is being used.
4426 @param Handle The Hii Handle.
4428 @retval TRUE HII handle is being used.
4429 @retval FALSE HII handle is not being used.
4433 IsHiiHandleInBrowserContext (
4434 EFI_HII_HANDLE Handle
4438 BROWSER_CONTEXT
*Context
;
4441 // HiiHandle is Current FormSet.
4443 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
4448 // Check whether HiiHandle is in BrowserContext.
4450 Link
= GetFirstNode (&gBrowserContextList
);
4451 while (!IsNull (&gBrowserContextList
, Link
)) {
4452 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4453 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
4455 // HiiHandle is in BrowserContext
4459 Link
= GetNextNode (&gBrowserContextList
, Link
);
4466 Find the registered HotKey based on KeyData.
4468 @param[in] KeyData A pointer to a buffer that describes the keystroke
4469 information for the hot key.
4471 @return The registered HotKey context. If no found, NULL will return.
4474 GetHotKeyFromRegisterList (
4475 IN EFI_INPUT_KEY
*KeyData
4479 BROWSER_HOT_KEY
*HotKey
;
4481 Link
= GetFirstNode (&gBrowserHotKeyList
);
4482 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4483 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4484 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4487 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4494 Configure what scope the hot key will impact.
4495 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4496 If no scope is set, the default scope will be FormSet level.
4497 After all registered hot keys are removed, previous Scope can reset to another level.
4499 @param[in] Scope Scope level to be set.
4501 @retval EFI_SUCCESS Scope is set correctly.
4502 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4503 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4509 IN BROWSER_SETTING_SCOPE Scope
4512 if (Scope
>= MaxLevel
) {
4513 return EFI_INVALID_PARAMETER
;
4517 // When no hot key registered in system or on the first setting,
4518 // Scope can be set.
4520 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4521 gBrowserSettingScope
= Scope
;
4522 mBrowserScopeFirstSet
= FALSE
;
4523 } else if (Scope
!= gBrowserSettingScope
) {
4524 return EFI_UNSUPPORTED
;
4531 Register the hot key with its browser action, or unregistered the hot key.
4532 Only support hot key that is not printable character (control key, function key, etc.).
4533 If the action value is zero, the hot key will be unregistered if it has been registered.
4534 If the same hot key has been registered, the new action and help string will override the previous ones.
4536 @param[in] KeyData A pointer to a buffer that describes the keystroke
4537 information for the hot key. Its type is EFI_INPUT_KEY to
4538 be supported by all ConsoleIn devices.
4539 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4540 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4541 @param[in] HelpString Help string that describes the hot key information.
4542 Its value may be NULL for the unregistered hot key.
4544 @retval EFI_SUCCESS Hot key is registered or unregistered.
4545 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4546 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4547 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4552 IN EFI_INPUT_KEY
*KeyData
,
4554 IN UINT16 DefaultId
,
4555 IN EFI_STRING HelpString OPTIONAL
4558 BROWSER_HOT_KEY
*HotKey
;
4561 // Check input parameters.
4563 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4564 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4565 return EFI_INVALID_PARAMETER
;
4569 // Check whether the input KeyData is in BrowserHotKeyList.
4571 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4574 // Unregister HotKey
4576 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4577 if (HotKey
!= NULL
) {
4579 // The registered HotKey is found.
4580 // Remove it from List, and free its resource.
4582 RemoveEntryList (&HotKey
->Link
);
4583 FreePool (HotKey
->KeyData
);
4584 FreePool (HotKey
->HelpString
);
4588 // The registered HotKey is not found.
4590 return EFI_NOT_FOUND
;
4595 // Register HotKey into List.
4597 if (HotKey
== NULL
) {
4599 // Create new Key, and add it into List.
4601 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4602 ASSERT (HotKey
!= NULL
);
4603 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4604 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4605 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4609 // Fill HotKey information.
4611 HotKey
->Action
= Action
;
4612 HotKey
->DefaultId
= DefaultId
;
4613 if (HotKey
->HelpString
!= NULL
) {
4614 FreePool (HotKey
->HelpString
);
4616 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4622 Register Exit handler function.
4623 When more than one handler function is registered, the latter one will override the previous one.
4624 When NULL handler is specified, the previous Exit handler will be unregistered.
4626 @param[in] Handler Pointer to handler function.
4631 RegiserExitHandler (
4632 IN EXIT_HANDLER Handler
4635 ExitHandlerFunction
= Handler
;
4640 Create reminder to let user to choose save or discard the changed browser data.
4641 Caller can use it to actively check the changed browser data.
4643 @retval BROWSER_NO_CHANGES No browser data is changed.
4644 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4645 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4655 FORM_BROWSER_FORMSET
*FormSet
;
4656 BOOLEAN IsDataChanged
;
4657 UINT32 DataSavedAction
;
4658 CHAR16
*YesResponse
;
4660 CHAR16
*EmptyString
;
4661 CHAR16
*ChangeReminderString
;
4662 CHAR16
*SaveConfirmString
;
4665 DataSavedAction
= BROWSER_NO_CHANGES
;
4666 IsDataChanged
= FALSE
;
4667 Link
= GetFirstNode (&gBrowserFormSetList
);
4668 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4669 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4670 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4671 if (!ValidateFormSet(FormSet
)) {
4674 if (IsNvUpdateRequired (FormSet
)) {
4675 IsDataChanged
= TRUE
;
4681 // No data is changed. No save is required.
4683 if (!IsDataChanged
) {
4684 return DataSavedAction
;
4688 // If data is changed, prompt user
4690 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4692 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4693 ASSERT (YesResponse
!= NULL
);
4694 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4695 ASSERT (NoResponse
!= NULL
);
4696 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4697 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4698 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4701 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4703 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4704 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4708 // If the user hits the YesResponse key
4710 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4711 SubmitForm (NULL
, NULL
, SystemLevel
);
4712 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4714 DiscardForm (NULL
, NULL
, SystemLevel
);
4715 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4716 gResetRequired
= FALSE
;
4719 FreePool (YesResponse
);
4720 FreePool (NoResponse
);
4721 FreePool (EmptyString
);
4722 FreePool (SaveConfirmString
);
4723 FreePool (ChangeReminderString
);
4725 return DataSavedAction
;