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
,
31 BROWSER_EXTENSION2_VERSION_1
,
35 IsBrowserDataModified
,
40 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
41 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
42 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
43 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
45 UINTN gBrowserContextCount
= 0;
46 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
47 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
48 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
49 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
51 BOOLEAN gResetRequired
;
52 BOOLEAN gExitRequired
;
53 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
54 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
55 EXIT_HANDLER ExitHandlerFunction
= NULL
;
58 // Browser Global Strings
61 CHAR16
*mUnknownString
= L
"!";
63 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
65 extern UINT32 gBrowserStatus
;
66 extern CHAR16
*gErrorInfo
;
67 extern EFI_GUID mCurrentFormSetGuid
;
68 extern EFI_HII_HANDLE mCurrentHiiHandle
;
69 extern UINT16 mCurrentFormId
;
70 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
73 Create a menu with specified formset GUID and form ID, and add it as a child
74 of the given parent menu.
76 @param HiiHandle Hii handle related to this formset.
77 @param FormSetGuid The Formset Guid of menu to be added.
78 @param FormId The Form ID of menu to be added.
79 @param QuestionId The question id of this menu to be added.
81 @return A pointer to the newly added menu or NULL if memory is insufficient.
86 IN EFI_HII_HANDLE HiiHandle
,
87 IN EFI_GUID
*FormSetGuid
,
92 FORM_ENTRY_INFO
*MenuList
;
94 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
95 if (MenuList
== NULL
) {
99 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
101 MenuList
->HiiHandle
= HiiHandle
;
102 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
103 MenuList
->FormId
= FormId
;
104 MenuList
->QuestionId
= QuestionId
;
107 // If parent is not specified, it is the root Form of a Formset
109 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
115 Return the form id for the input hiihandle and formset.
117 @param HiiHandle HiiHandle for FormSet.
118 @param FormSetGuid The Formset GUID of the menu to search.
120 @return First form's id for this form set.
125 IN EFI_HII_HANDLE HiiHandle
,
126 IN EFI_GUID
*FormSetGuid
130 FORM_BROWSER_FORM
*Form
;
132 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
133 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
139 Search Menu with given FormSetGuid and FormId in all cached menu list.
141 @param HiiHandle HiiHandle for FormSet.
142 @param FormSetGuid The Formset GUID of the menu to search.
143 @param FormId The Form ID of menu to search.
145 @return A pointer to menu found or NULL if not found.
150 IN EFI_HII_HANDLE HiiHandle
,
151 IN EFI_GUID
*FormSetGuid
,
156 FORM_ENTRY_INFO
*MenuList
;
157 FORM_ENTRY_INFO
*RetMenu
;
158 EFI_FORM_ID FirstFormId
;
162 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
163 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
164 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
165 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
168 // If already find the menu, free the menus behind it.
170 if (RetMenu
!= NULL
) {
171 RemoveEntryList (&MenuList
->Link
);
177 // Find the same FromSet.
179 if (MenuList
->HiiHandle
== HiiHandle
) {
180 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
182 // FormSetGuid is not specified.
185 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
186 if (MenuList
->FormId
== FormId
) {
188 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
189 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
190 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
202 Find parent menu for current menu.
204 @param CurrentMenu Current Menu
206 @retval The parent menu for current menu.
210 IN FORM_ENTRY_INFO
*CurrentMenu
213 FORM_ENTRY_INFO
*ParentMenu
;
216 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
217 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
224 Free Menu list linked list.
226 @param MenuListHead One Menu list point in the menu list.
231 LIST_ENTRY
*MenuListHead
234 FORM_ENTRY_INFO
*MenuList
;
236 while (!IsListEmpty (MenuListHead
)) {
237 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
238 RemoveEntryList (&MenuList
->Link
);
245 Load all hii formset to the browser.
253 FORM_BROWSER_FORMSET
*LocalFormSet
;
254 EFI_HII_HANDLE
*HiiHandles
;
260 // Get all the Hii handles
262 HiiHandles
= HiiGetHiiHandles (NULL
);
263 ASSERT (HiiHandles
!= NULL
);
266 // Search for formset of each class type
268 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
270 // Check HiiHandles[Index] does exist in global maintain list.
272 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
277 // Initilize FormSet Setting
279 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
280 ASSERT (LocalFormSet
!= NULL
);
281 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
282 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
283 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
284 DestroyFormSet (LocalFormSet
);
287 InitializeCurrentSetting (LocalFormSet
);
290 // Initilize Questions' Value
292 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
293 if (EFI_ERROR (Status
)) {
294 DestroyFormSet (LocalFormSet
);
300 // Free resources, and restore gOldFormSet and gClassOfVfr
302 FreePool (HiiHandles
);
306 This is the routine which an external caller uses to direct the browser
307 where to obtain it's information.
310 @param This The Form Browser protocol instanse.
311 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
312 display a list of the formsets for the handles specified.
313 @param HandleCount The number of Handles specified in Handle.
314 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
315 field in the EFI_IFR_FORM_SET op-code for the specified
316 forms-based package. If FormSetGuid is NULL, then this
317 function will display the first found forms package.
318 @param FormId This field specifies which EFI_IFR_FORM to render as the first
319 displayable page. If this field has a value of 0x0000, then
320 the forms browser will render the specified forms in their encoded order.
321 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
323 @param ActionRequest Points to the action recommended by the form.
325 @retval EFI_SUCCESS The function completed successfully.
326 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
327 @retval EFI_NOT_FOUND No valid forms could be found to display.
333 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
334 IN EFI_HII_HANDLE
*Handles
,
335 IN UINTN HandleCount
,
336 IN EFI_GUID
*FormSetGuid
, OPTIONAL
337 IN UINT16 FormId
, OPTIONAL
338 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
339 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
343 UI_MENU_SELECTION
*Selection
;
345 FORM_BROWSER_FORMSET
*FormSet
;
346 FORM_ENTRY_INFO
*MenuList
;
349 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
351 if (mFormDisplay
== NULL
) {
352 return EFI_UNSUPPORTED
;
356 // Save globals used by SendForm()
358 SaveBrowserContext ();
360 gResetRequired
= FALSE
;
361 gExitRequired
= FALSE
;
362 Status
= EFI_SUCCESS
;
364 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
366 for (Index
= 0; Index
< HandleCount
; Index
++) {
367 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
368 ASSERT (Selection
!= NULL
);
370 Selection
->Handle
= Handles
[Index
];
371 if (FormSetGuid
!= NULL
) {
372 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
373 Selection
->FormId
= FormId
;
375 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
379 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
380 ASSERT (FormSet
!= NULL
);
383 // Initialize internal data structures of FormSet
385 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
386 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
387 DestroyFormSet (FormSet
);
390 Selection
->FormSet
= FormSet
;
393 // Display this formset
395 gCurrentSelection
= Selection
;
397 Status
= SetupBrowser (Selection
);
399 gCurrentSelection
= NULL
;
402 // If no data is changed, don't need to save current FormSet into the maintain list.
404 if (!IsNvUpdateRequiredForFormSet (FormSet
) && !IsStorageDataChangedForFormSet(FormSet
)) {
405 CleanBrowserStorage(FormSet
);
406 RemoveEntryList (&FormSet
->Link
);
407 DestroyFormSet (FormSet
);
410 if (EFI_ERROR (Status
)) {
413 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
415 FreePool (Selection
);
419 // Still has error info, pop up a message.
421 if (gBrowserStatus
!= BROWSER_SUCCESS
) {
422 gDisplayFormData
.BrowserStatus
= gBrowserStatus
;
423 gDisplayFormData
.ErrorString
= gErrorInfo
;
425 gBrowserStatus
= BROWSER_SUCCESS
;
428 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
431 if (ActionRequest
!= NULL
) {
432 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
433 if (gResetRequired
) {
434 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
438 mFormDisplay
->ExitDisplay();
441 // Clear the menu history data.
443 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
444 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
445 RemoveEntryList (&MenuList
->Link
);
450 // Restore globals used by SendForm()
452 RestoreBrowserContext ();
458 Get or set data to the storage.
460 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
461 @param ResultsData A string returned from an IFR browser or
462 equivalent. The results string will have no
463 routing information in them.
464 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
465 (if RetrieveData = TRUE) data from the uncommitted
466 browser state information or set (if RetrieveData
467 = FALSE) data in the uncommitted browser state
469 @param Storage The pointer to the storage.
471 @retval EFI_SUCCESS The results have been distributed or are awaiting
477 IN OUT UINTN
*ResultsDataSize
,
478 IN OUT EFI_STRING
*ResultsData
,
479 IN BOOLEAN RetrieveData
,
480 IN BROWSER_STORAGE
*Storage
491 // Generate <ConfigResp>
493 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
494 if (EFI_ERROR (Status
)) {
499 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
500 // Also need to consider add "\0" at first time.
502 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
503 BufferSize
= StrSize (StrPtr
);
507 // Copy the data if the input buffer is bigger enough.
509 if (*ResultsDataSize
>= BufferSize
) {
510 StrCpy (*ResultsData
, StrPtr
);
513 *ResultsDataSize
= BufferSize
;
514 FreePool (ConfigResp
);
517 // Prepare <ConfigResp>
519 TmpSize
= StrLen (*ResultsData
);
520 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
521 ConfigResp
= AllocateZeroPool (BufferSize
);
522 ASSERT (ConfigResp
!= NULL
);
524 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
525 StrCat (ConfigResp
, L
"&");
526 StrCat (ConfigResp
, *ResultsData
);
529 // Update Browser uncommited data
531 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
532 FreePool (ConfigResp
);
533 if (EFI_ERROR (Status
)) {
542 This routine called this service in the browser to retrieve or set certain uncommitted
543 state information that resides in the open formsets.
545 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
547 @param ResultsDataSize A pointer to the size of the buffer associated
549 @param ResultsData A string returned from an IFR browser or
550 equivalent. The results string will have no
551 routing information in them.
552 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
553 (if RetrieveData = TRUE) data from the uncommitted
554 browser state information or set (if RetrieveData
555 = FALSE) data in the uncommitted browser state
557 @param VariableGuid An optional field to indicate the target variable
559 @param VariableName An optional field to indicate the target
560 human-readable variable name.
562 @retval EFI_SUCCESS The results have been distributed or are awaiting
564 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
565 contain the results data.
571 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
572 IN OUT UINTN
*ResultsDataSize
,
573 IN OUT EFI_STRING ResultsData
,
574 IN BOOLEAN RetrieveData
,
575 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
576 IN CONST CHAR16
*VariableName OPTIONAL
581 BROWSER_STORAGE
*Storage
;
582 FORMSET_STORAGE
*FormsetStorage
;
583 FORM_BROWSER_FORMSET
*FormSet
;
587 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
588 return EFI_INVALID_PARAMETER
;
591 TotalSize
= *ResultsDataSize
;
594 Status
= EFI_SUCCESS
;
597 // If set browser data, pre load all hii formset to avoid set the varstore which is not
600 if (!RetrieveData
&& (gBrowserSettingScope
== SystemLevel
)) {
604 if (VariableGuid
!= NULL
) {
606 // Try to find target storage in the current formset.
608 Link
= GetFirstNode (&gBrowserStorageList
);
609 while (!IsNull (&gBrowserStorageList
, Link
)) {
610 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
611 Link
= GetNextNode (&gBrowserStorageList
, Link
);
613 // Check the current storage.
615 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
619 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
620 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
622 // Buffer storage require both GUID and Name
624 if (VariableName
== NULL
) {
625 return EFI_NOT_FOUND
;
628 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
633 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
634 if (EFI_ERROR (Status
)) {
639 // Different formsets may have same varstore, so here just set the flag
640 // not exit the circle.
647 return EFI_NOT_FOUND
;
651 // GUID/Name is not specified, take the first storage in FormSet
653 if (gCurrentSelection
== NULL
) {
654 return EFI_NOT_READY
;
658 // Generate <ConfigResp>
660 FormSet
= gCurrentSelection
->FormSet
;
661 Link
= GetFirstNode (&FormSet
->StorageListHead
);
662 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
663 return EFI_UNSUPPORTED
;
666 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
668 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
669 if (EFI_ERROR (Status
)) {
675 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
676 *ResultsDataSize
= TotalSize
;
685 Callback function for SimpleTextInEx protocol install events
687 @param Event the event that is signaled.
688 @param Context not used here.
693 FormDisplayCallback (
700 if (mFormDisplay
!= NULL
) {
704 Status
= gBS
->LocateProtocol (
705 &gEdkiiFormDisplayEngineProtocolGuid
,
707 (VOID
**) &mFormDisplay
712 Initialize Setup Browser driver.
714 @param ImageHandle The image handle.
715 @param SystemTable The system table.
717 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
718 @return Other value if failed to initialize the Setup Browser module.
724 IN EFI_HANDLE ImageHandle
,
725 IN EFI_SYSTEM_TABLE
*SystemTable
732 // Locate required Hii relative protocols
734 Status
= gBS
->LocateProtocol (
735 &gEfiHiiDatabaseProtocolGuid
,
737 (VOID
**) &mHiiDatabase
739 ASSERT_EFI_ERROR (Status
);
741 Status
= gBS
->LocateProtocol (
742 &gEfiHiiConfigRoutingProtocolGuid
,
744 (VOID
**) &mHiiConfigRouting
746 ASSERT_EFI_ERROR (Status
);
748 Status
= gBS
->LocateProtocol (
749 &gEfiDevicePathFromTextProtocolGuid
,
751 (VOID
**) &mPathFromText
755 // Install FormBrowser2 protocol
757 mPrivateData
.Handle
= NULL
;
758 Status
= gBS
->InstallProtocolInterface (
759 &mPrivateData
.Handle
,
760 &gEfiFormBrowser2ProtocolGuid
,
761 EFI_NATIVE_INTERFACE
,
762 &mPrivateData
.FormBrowser2
764 ASSERT_EFI_ERROR (Status
);
767 // Install FormBrowserEx2 protocol
769 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
770 mPrivateData
.Handle
= NULL
;
771 Status
= gBS
->InstallProtocolInterface (
772 &mPrivateData
.Handle
,
773 &gEdkiiFormBrowserEx2ProtocolGuid
,
774 EFI_NATIVE_INTERFACE
,
775 &mPrivateData
.FormBrowserEx2
777 ASSERT_EFI_ERROR (Status
);
779 Status
= gBS
->InstallProtocolInterface (
780 &mPrivateData
.Handle
,
781 &gEfiFormBrowserExProtocolGuid
,
782 EFI_NATIVE_INTERFACE
,
783 &mPrivateData
.FormBrowserEx
785 ASSERT_EFI_ERROR (Status
);
787 InitializeDisplayFormData ();
789 Status
= gBS
->LocateProtocol (
790 &gEdkiiFormDisplayEngineProtocolGuid
,
792 (VOID
**) &mFormDisplay
795 if (EFI_ERROR (Status
)) {
796 EfiCreateProtocolNotifyEvent (
797 &gEdkiiFormDisplayEngineProtocolGuid
,
810 Create a new string in HII Package List.
812 @param String The String to be added
813 @param HiiHandle The package list in the HII database to insert the
816 @return The output string.
822 IN EFI_HII_HANDLE HiiHandle
825 EFI_STRING_ID StringId
;
827 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
828 ASSERT (StringId
!= 0);
835 Delete a string from HII Package List.
837 @param StringId Id of the string in HII database.
838 @param HiiHandle The HII package list handle.
840 @retval EFI_SUCCESS The string was deleted successfully.
845 IN EFI_STRING_ID StringId
,
846 IN EFI_HII_HANDLE HiiHandle
851 NullChar
= CHAR_NULL
;
852 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
858 Get the string based on the StringId and HII Package List Handle.
860 @param Token The String's ID.
861 @param HiiHandle The package list in the HII database to search for
862 the specified string.
864 @return The output string.
869 IN EFI_STRING_ID Token
,
870 IN EFI_HII_HANDLE HiiHandle
875 if (HiiHandle
== NULL
) {
879 String
= HiiGetString (HiiHandle
, Token
, NULL
);
880 if (String
== NULL
) {
881 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
882 ASSERT (String
!= NULL
);
884 return (CHAR16
*) String
;
889 Allocate new memory and then copy the Unicode string Source to Destination.
891 @param Dest Location to copy string
892 @param Src String to copy
897 IN OUT CHAR16
**Dest
,
904 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
905 ASSERT (*Dest
!= NULL
);
910 Allocate new memory and concatinate Source on the end of Destination.
912 @param Dest String to added to the end of.
913 @param Src String to concatinate.
918 IN OUT CHAR16
**Dest
,
926 NewStringCpy (Dest
, Src
);
930 TmpSize
= StrSize (*Dest
);
931 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
932 ASSERT (NewString
!= NULL
);
934 StrCpy (NewString
, *Dest
);
935 StrCat (NewString
, Src
);
942 Get Value for given Name from a NameValue Storage.
944 @param Storage The NameValue Storage.
945 @param Name The Name.
946 @param Value The retured Value.
947 @param GetValueFrom Where to get source value, from EditValue or Value.
949 @retval EFI_SUCCESS Value found for given Name.
950 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
955 IN BROWSER_STORAGE
*Storage
,
957 IN OUT CHAR16
**Value
,
958 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
962 NAME_VALUE_NODE
*Node
;
964 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
965 return EFI_INVALID_PARAMETER
;
970 Link
= GetFirstNode (&Storage
->NameValueListHead
);
971 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
972 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
974 if (StrCmp (Name
, Node
->Name
) == 0) {
975 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
976 NewStringCpy (Value
, Node
->EditValue
);
978 NewStringCpy (Value
, Node
->Value
);
983 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
986 return EFI_NOT_FOUND
;
991 Set Value of given Name in a NameValue Storage.
993 @param Storage The NameValue Storage.
994 @param Name The Name.
995 @param Value The Value to set.
996 @param SetValueTo Whether update editValue or Value.
997 @param ReturnNode The node use the input name.
999 @retval EFI_SUCCESS Value found for given Name.
1000 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1005 IN BROWSER_STORAGE
*Storage
,
1008 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1009 OUT NAME_VALUE_NODE
**ReturnNode
1013 NAME_VALUE_NODE
*Node
;
1016 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1017 return EFI_INVALID_PARAMETER
;
1020 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1021 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1022 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1024 if (StrCmp (Name
, Node
->Name
) == 0) {
1025 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1026 Buffer
= Node
->EditValue
;
1028 Buffer
= Node
->Value
;
1030 if (Buffer
!= NULL
) {
1033 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1034 ASSERT (Buffer
!= NULL
);
1035 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1036 Node
->EditValue
= Buffer
;
1038 Node
->Value
= Buffer
;
1041 if (ReturnNode
!= NULL
) {
1048 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1051 return EFI_NOT_FOUND
;
1056 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1058 @param Storage The Storage to be conveted.
1059 @param ConfigResp The returned <ConfigResp>.
1060 @param ConfigRequest The ConfigRequest string.
1061 @param GetEditBuf Get the data from editbuffer or buffer.
1063 @retval EFI_SUCCESS Convert success.
1064 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1068 StorageToConfigResp (
1069 IN BROWSER_STORAGE
*Storage
,
1070 IN CHAR16
**ConfigResp
,
1071 IN CHAR16
*ConfigRequest
,
1072 IN BOOLEAN GetEditBuf
1076 EFI_STRING Progress
;
1078 NAME_VALUE_NODE
*Node
;
1081 Status
= EFI_SUCCESS
;
1083 switch (Storage
->Type
) {
1084 case EFI_HII_VARSTORE_BUFFER
:
1085 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1086 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1087 Status
= mHiiConfigRouting
->BlockToConfig (
1097 case EFI_HII_VARSTORE_NAME_VALUE
:
1099 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1101 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1102 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1103 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1105 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1106 NewStringCat (ConfigResp
, L
"&");
1107 NewStringCat (ConfigResp
, Node
->Name
);
1108 NewStringCat (ConfigResp
, L
"=");
1110 NewStringCat (ConfigResp
, Node
->EditValue
);
1112 NewStringCat (ConfigResp
, Node
->Value
);
1115 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1119 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1121 Status
= EFI_INVALID_PARAMETER
;
1130 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1132 @param Storage The Storage to receive the settings.
1133 @param ConfigResp The <ConfigResp> to be converted.
1135 @retval EFI_SUCCESS Convert success.
1136 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1140 ConfigRespToStorage (
1141 IN BROWSER_STORAGE
*Storage
,
1142 IN CHAR16
*ConfigResp
1146 EFI_STRING Progress
;
1152 Status
= EFI_SUCCESS
;
1154 switch (Storage
->Type
) {
1155 case EFI_HII_VARSTORE_BUFFER
:
1156 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1157 BufferSize
= Storage
->Size
;
1158 Status
= mHiiConfigRouting
->ConfigToBlock (
1161 Storage
->EditBuffer
,
1167 case EFI_HII_VARSTORE_NAME_VALUE
:
1168 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1169 if (StrPtr
== NULL
) {
1172 StrPtr
= StrStr (ConfigResp
, L
"&");
1173 while (StrPtr
!= NULL
) {
1177 StrPtr
= StrPtr
+ 1;
1179 StrPtr
= StrStr (StrPtr
, L
"=");
1180 if (StrPtr
== NULL
) {
1188 StrPtr
= StrPtr
+ 1;
1190 StrPtr
= StrStr (StrPtr
, L
"&");
1191 if (StrPtr
!= NULL
) {
1194 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1198 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1200 Status
= EFI_INVALID_PARAMETER
;
1209 Get Question's current Value.
1211 @param FormSet FormSet data structure.
1212 @param Form Form data structure.
1213 @param Question Question to be initialized.
1214 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1216 @retval EFI_SUCCESS The function completed successfully.
1221 IN FORM_BROWSER_FORMSET
*FormSet
,
1222 IN FORM_BROWSER_FORM
*Form
,
1223 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1224 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1233 BROWSER_STORAGE
*Storage
;
1234 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1235 CHAR16
*ConfigRequest
;
1243 BOOLEAN IsBufferStorage
;
1249 Status
= EFI_SUCCESS
;
1253 if (GetValueFrom
>= GetSetValueWithMax
) {
1254 return EFI_INVALID_PARAMETER
;
1258 // Question value is provided by an Expression, evaluate it
1260 if (Question
->ValueExpression
!= NULL
) {
1261 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1262 if (!EFI_ERROR (Status
)) {
1263 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1264 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1265 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1266 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1267 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1269 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1270 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1272 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1274 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1275 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1281 // Get question value by read expression.
1283 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1284 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1285 if (!EFI_ERROR (Status
) &&
1286 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1288 // Only update question value to the valid result.
1290 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1291 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1292 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1293 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1294 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1296 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1297 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1299 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1301 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1302 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1308 // Question value is provided by RTC
1310 Storage
= Question
->Storage
;
1311 QuestionValue
= &Question
->HiiValue
.Value
;
1312 if (Storage
== NULL
) {
1314 // It's a Question without storage, or RTC date/time
1316 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1318 // Date and time define the same Flags bit
1320 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1321 case QF_DATE_STORAGE_TIME
:
1322 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1325 case QF_DATE_STORAGE_WAKEUP
:
1326 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1329 case QF_DATE_STORAGE_NORMAL
:
1332 // For date/time without storage
1337 if (EFI_ERROR (Status
)) {
1341 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1342 QuestionValue
->date
.Year
= EfiTime
.Year
;
1343 QuestionValue
->date
.Month
= EfiTime
.Month
;
1344 QuestionValue
->date
.Day
= EfiTime
.Day
;
1346 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1347 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1348 QuestionValue
->time
.Second
= EfiTime
.Second
;
1356 // Question value is provided by EFI variable
1358 StorageWidth
= Question
->StorageWidth
;
1359 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1360 if (Question
->BufferValue
!= NULL
) {
1361 Dst
= Question
->BufferValue
;
1363 Dst
= (UINT8
*) QuestionValue
;
1366 Status
= gRT
->GetVariable (
1367 Question
->VariableName
,
1374 // Always return success, even this EFI variable doesn't exist
1380 // Question Value is provided by Buffer Storage or NameValue Storage
1382 if (Question
->BufferValue
!= NULL
) {
1384 // This Question is password or orderedlist
1386 Dst
= Question
->BufferValue
;
1389 // Other type of Questions
1391 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1394 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1395 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1396 IsBufferStorage
= TRUE
;
1398 IsBufferStorage
= FALSE
;
1400 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1401 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1402 if (IsBufferStorage
) {
1403 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1405 // Copy from storage Edit buffer
1407 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1410 // Copy from storage Edit buffer
1412 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1416 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1417 if (EFI_ERROR (Status
)) {
1421 ASSERT (Value
!= NULL
);
1422 LengthStr
= StrLen (Value
);
1423 Status
= EFI_SUCCESS
;
1426 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1427 // Add string tail char L'\0' into Length
1429 Length
= StorageWidth
+ sizeof (CHAR16
);
1430 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1431 Status
= EFI_BUFFER_TOO_SMALL
;
1433 StringPtr
= (CHAR16
*) Dst
;
1434 ZeroMem (TemStr
, sizeof (TemStr
));
1435 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1436 StrnCpy (TemStr
, Value
+ Index
, 4);
1437 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1440 // Add tailing L'\0' character
1442 StringPtr
[Index
/4] = L
'\0';
1445 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1446 Status
= EFI_BUFFER_TOO_SMALL
;
1448 ZeroMem (TemStr
, sizeof (TemStr
));
1449 for (Index
= 0; Index
< LengthStr
; Index
++) {
1450 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1451 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1452 if ((Index
& 1) == 0) {
1453 Dst
[Index
/2] = DigitUint8
;
1455 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1464 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1466 // Request current settings from Configuration Driver
1468 if (FormSet
->ConfigAccess
== NULL
) {
1469 return EFI_NOT_FOUND
;
1473 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1474 // <ConfigHdr> + "&" + <VariableName>
1476 if (IsBufferStorage
) {
1477 Length
= StrLen (Storage
->ConfigHdr
);
1478 Length
+= StrLen (Question
->BlockName
);
1480 Length
= StrLen (Storage
->ConfigHdr
);
1481 Length
+= StrLen (Question
->VariableName
) + 1;
1483 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1484 ASSERT (ConfigRequest
!= NULL
);
1486 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1487 if (IsBufferStorage
) {
1488 StrCat (ConfigRequest
, Question
->BlockName
);
1490 StrCat (ConfigRequest
, L
"&");
1491 StrCat (ConfigRequest
, Question
->VariableName
);
1494 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1495 FormSet
->ConfigAccess
,
1500 FreePool (ConfigRequest
);
1501 if (EFI_ERROR (Status
)) {
1506 // Skip <ConfigRequest>
1508 if (IsBufferStorage
) {
1509 Value
= StrStr (Result
, L
"&VALUE");
1510 if (Value
== NULL
) {
1512 return EFI_NOT_FOUND
;
1519 Value
= Result
+ Length
;
1521 if (*Value
!= '=') {
1523 return EFI_NOT_FOUND
;
1526 // Skip '=', point to value
1531 // Suppress <AltResp> if any
1534 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1539 LengthStr
= StrLen (Value
);
1540 Status
= EFI_SUCCESS
;
1541 if (!IsBufferStorage
&& IsString
) {
1543 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1544 // Add string tail char L'\0' into Length
1546 Length
= StorageWidth
+ sizeof (CHAR16
);
1547 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1548 Status
= EFI_BUFFER_TOO_SMALL
;
1550 StringPtr
= (CHAR16
*) Dst
;
1551 ZeroMem (TemStr
, sizeof (TemStr
));
1552 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1553 StrnCpy (TemStr
, Value
+ Index
, 4);
1554 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1557 // Add tailing L'\0' character
1559 StringPtr
[Index
/4] = L
'\0';
1562 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1563 Status
= EFI_BUFFER_TOO_SMALL
;
1565 ZeroMem (TemStr
, sizeof (TemStr
));
1566 for (Index
= 0; Index
< LengthStr
; Index
++) {
1567 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1568 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1569 if ((Index
& 1) == 0) {
1570 Dst
[Index
/2] = DigitUint8
;
1572 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1578 if (EFI_ERROR (Status
)) {
1582 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1584 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1585 if (TemBuffer
== NULL
) {
1586 Status
= EFI_OUT_OF_RESOURCES
;
1589 Length
= Storage
->Size
;
1590 Status
= gRT
->GetVariable (
1597 if (EFI_ERROR (Status
)) {
1598 FreePool (TemBuffer
);
1602 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1604 FreePool (TemBuffer
);
1608 // Synchronize Edit Buffer
1610 if (IsBufferStorage
) {
1611 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1613 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1616 if (Result
!= NULL
) {
1626 Save Question Value to edit copy(cached) or Storage(uncached).
1628 @param FormSet FormSet data structure.
1629 @param Form Form data structure.
1630 @param Question Pointer to the Question.
1631 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1633 @retval EFI_SUCCESS The function completed successfully.
1638 IN FORM_BROWSER_FORMSET
*FormSet
,
1639 IN FORM_BROWSER_FORM
*Form
,
1640 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1641 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1651 BROWSER_STORAGE
*Storage
;
1652 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1657 BOOLEAN IsBufferStorage
;
1663 NAME_VALUE_NODE
*Node
;
1665 Status
= EFI_SUCCESS
;
1668 if (SetValueTo
>= GetSetValueWithMax
) {
1669 return EFI_INVALID_PARAMETER
;
1673 // If Question value is provided by an Expression, then it is read only
1675 if (Question
->ValueExpression
!= NULL
) {
1680 // Before set question value, evaluate its write expression.
1682 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1683 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1684 if (EFI_ERROR (Status
)) {
1690 // Question value is provided by RTC
1692 Storage
= Question
->Storage
;
1693 QuestionValue
= &Question
->HiiValue
.Value
;
1694 if (Storage
== NULL
) {
1696 // It's a Question without storage, or RTC date/time
1698 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1700 // Date and time define the same Flags bit
1702 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1703 case QF_DATE_STORAGE_TIME
:
1704 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1707 case QF_DATE_STORAGE_WAKEUP
:
1708 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1711 case QF_DATE_STORAGE_NORMAL
:
1714 // For date/time without storage
1719 if (EFI_ERROR (Status
)) {
1723 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1724 EfiTime
.Year
= QuestionValue
->date
.Year
;
1725 EfiTime
.Month
= QuestionValue
->date
.Month
;
1726 EfiTime
.Day
= QuestionValue
->date
.Day
;
1728 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1729 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1730 EfiTime
.Second
= QuestionValue
->time
.Second
;
1733 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1734 Status
= gRT
->SetTime (&EfiTime
);
1736 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1744 // Question value is provided by EFI variable
1746 StorageWidth
= Question
->StorageWidth
;
1747 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1748 if (Question
->BufferValue
!= NULL
) {
1749 Src
= Question
->BufferValue
;
1751 Src
= (UINT8
*) QuestionValue
;
1754 Status
= gRT
->SetVariable (
1755 Question
->VariableName
,
1757 Storage
->Attributes
,
1765 // Question Value is provided by Buffer Storage or NameValue Storage
1767 if (Question
->BufferValue
!= NULL
) {
1768 Src
= Question
->BufferValue
;
1770 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1773 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1774 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1775 IsBufferStorage
= TRUE
;
1777 IsBufferStorage
= FALSE
;
1779 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1781 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1782 if (IsBufferStorage
) {
1783 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1785 // Copy to storage edit buffer
1787 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1788 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1790 // Copy to storage edit buffer
1792 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1795 // Check whether question value has been changed.
1797 if (CompareMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
) != 0) {
1798 Question
->ValueChanged
= TRUE
;
1800 Question
->ValueChanged
= FALSE
;
1805 // Allocate enough string buffer.
1808 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1809 Value
= AllocateZeroPool (BufferLen
);
1810 ASSERT (Value
!= NULL
);
1812 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1814 TemName
= (CHAR16
*) Src
;
1816 for (; *TemName
!= L
'\0'; TemName
++) {
1817 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1820 BufferLen
= StorageWidth
* 2 + 1;
1821 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1822 ASSERT (Value
!= NULL
);
1824 // Convert Buffer to Hex String
1826 TemBuffer
= Src
+ StorageWidth
- 1;
1828 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1829 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1833 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1835 if (EFI_ERROR (Status
)) {
1839 // Check whether question value has been changed.
1841 if (StrCmp (Node
->Value
, Node
->EditValue
) != 0) {
1842 Question
->ValueChanged
= TRUE
;
1844 Question
->ValueChanged
= FALSE
;
1847 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1848 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1850 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1851 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1853 if (IsBufferStorage
) {
1854 Length
= StrLen (Question
->BlockName
) + 7;
1856 Length
= StrLen (Question
->VariableName
) + 2;
1858 if (!IsBufferStorage
&& IsString
) {
1859 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1861 Length
+= (StorageWidth
* 2);
1863 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1864 ASSERT (ConfigResp
!= NULL
);
1866 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1867 if (IsBufferStorage
) {
1868 StrCat (ConfigResp
, Question
->BlockName
);
1869 StrCat (ConfigResp
, L
"&VALUE=");
1871 StrCat (ConfigResp
, L
"&");
1872 StrCat (ConfigResp
, Question
->VariableName
);
1873 StrCat (ConfigResp
, L
"=");
1876 Value
= ConfigResp
+ StrLen (ConfigResp
);
1878 if (!IsBufferStorage
&& IsString
) {
1880 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1882 TemName
= (CHAR16
*) Src
;
1884 for (; *TemName
!= L
'\0'; TemName
++) {
1885 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1889 // Convert Buffer to Hex String
1891 TemBuffer
= Src
+ StorageWidth
- 1;
1893 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1894 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1899 // Convert to lower char.
1901 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1902 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1903 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1908 // Submit Question Value to Configuration Driver
1910 if (FormSet
->ConfigAccess
!= NULL
) {
1911 Status
= FormSet
->ConfigAccess
->RouteConfig (
1912 FormSet
->ConfigAccess
,
1916 if (EFI_ERROR (Status
)) {
1917 FreePool (ConfigResp
);
1921 FreePool (ConfigResp
);
1923 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1925 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1926 if (TemBuffer
== NULL
) {
1927 Status
= EFI_OUT_OF_RESOURCES
;
1930 Length
= Storage
->Size
;
1931 Status
= gRT
->GetVariable (
1939 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1941 Status
= gRT
->SetVariable (
1944 Storage
->Attributes
,
1948 FreePool (TemBuffer
);
1949 if (EFI_ERROR (Status
)){
1954 // Sync storage, from editbuffer to buffer.
1956 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1964 Perform nosubmitif check for a Form.
1966 @param FormSet FormSet data structure.
1967 @param Form Form data structure.
1968 @param Question The Question to be validated.
1969 @param Type Validation type: NoSubmit
1971 @retval EFI_SUCCESS Form validation pass.
1972 @retval other Form validation failed.
1977 IN FORM_BROWSER_FORMSET
*FormSet
,
1978 IN FORM_BROWSER_FORM
*Form
,
1979 IN FORM_BROWSER_STATEMENT
*Question
,
1985 LIST_ENTRY
*ListHead
;
1987 FORM_EXPRESSION
*Expression
;
1989 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1990 ListHead
= &Question
->NoSubmitListHead
;
1992 return EFI_UNSUPPORTED
;
1995 Link
= GetFirstNode (ListHead
);
1996 while (!IsNull (ListHead
, Link
)) {
1997 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2000 // Evaluate the expression
2002 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2003 if (EFI_ERROR (Status
)) {
2007 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
2009 // Condition meet, show up error message
2011 if (Expression
->Error
!= 0) {
2012 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2013 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
2014 gBrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2019 return EFI_NOT_READY
;
2022 Link
= GetNextNode (ListHead
, Link
);
2030 Perform NoSubmit check for each Form in FormSet.
2032 @param FormSet FormSet data structure.
2033 @param CurrentForm Current input form data structure.
2035 @retval EFI_SUCCESS Form validation pass.
2036 @retval other Form validation failed.
2041 IN FORM_BROWSER_FORMSET
*FormSet
,
2042 IN FORM_BROWSER_FORM
*CurrentForm
2047 FORM_BROWSER_STATEMENT
*Question
;
2048 FORM_BROWSER_FORM
*Form
;
2049 LIST_ENTRY
*LinkForm
;
2051 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2052 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2053 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2054 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2056 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2060 Link
= GetFirstNode (&Form
->StatementListHead
);
2061 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2062 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2064 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2065 if (EFI_ERROR (Status
)) {
2069 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2077 Fill storage's edit copy with settings requested from Configuration Driver.
2079 @param FormSet FormSet data structure.
2080 @param Storage The storage which need to sync.
2081 @param ConfigRequest The config request string which used to sync storage.
2082 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2083 editbuffer to buffer
2084 if TRUE, copy the editbuffer to the buffer.
2085 if FALSE, copy the buffer to the editbuffer.
2087 @retval EFI_SUCCESS The function completed successfully.
2091 SynchronizeStorage (
2092 IN FORM_BROWSER_FORMSET
*FormSet
,
2093 OUT BROWSER_STORAGE
*Storage
,
2094 IN CHAR16
*ConfigRequest
,
2095 IN BOOLEAN SyncOrRestore
2099 EFI_STRING Progress
;
2103 NAME_VALUE_NODE
*Node
;
2107 Status
= EFI_SUCCESS
;
2110 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2111 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2112 BufferSize
= Storage
->Size
;
2114 if (SyncOrRestore
) {
2115 Src
= Storage
->EditBuffer
;
2116 Dst
= Storage
->Buffer
;
2118 Src
= Storage
->Buffer
;
2119 Dst
= Storage
->EditBuffer
;
2122 if (ConfigRequest
!= NULL
) {
2123 Status
= mHiiConfigRouting
->BlockToConfig(
2131 if (EFI_ERROR (Status
)) {
2135 Status
= mHiiConfigRouting
->ConfigToBlock (
2142 if (Result
!= NULL
) {
2146 CopyMem (Dst
, Src
, BufferSize
);
2148 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2149 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2150 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2151 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2153 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2154 (ConfigRequest
== NULL
)) {
2155 if (SyncOrRestore
) {
2156 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2158 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2162 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2170 When discard the question value, call the callback function with Changed type
2171 to inform the hii driver.
2173 @param FormSet FormSet data structure.
2174 @param Form Form data structure.
2178 SendDiscardInfoToDriver (
2179 IN FORM_BROWSER_FORMSET
*FormSet
,
2180 IN FORM_BROWSER_FORM
*Form
2184 FORM_BROWSER_STATEMENT
*Question
;
2185 EFI_IFR_TYPE_VALUE
*TypeValue
;
2186 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2188 Link
= GetFirstNode (&Form
->StatementListHead
);
2189 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2190 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2191 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2193 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2197 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2201 if (!Question
->ValueChanged
) {
2205 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2206 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2208 TypeValue
= &Question
->HiiValue
.Value
;
2211 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2212 FormSet
->ConfigAccess
->Callback (
2213 FormSet
->ConfigAccess
,
2214 EFI_BROWSER_ACTION_CHANGED
,
2215 Question
->QuestionId
,
2216 Question
->HiiValue
.Type
,
2224 Validate the FormSet. If the formset is not validate, remove it from the list.
2226 @param FormSet The input FormSet which need to validate.
2228 @retval TRUE The handle is validate.
2229 @retval FALSE The handle is invalidate.
2234 FORM_BROWSER_FORMSET
*FormSet
2237 EFI_HII_HANDLE
*HiiHandles
;
2241 ASSERT (FormSet
!= NULL
);
2244 // Get all the Hii handles
2246 HiiHandles
= HiiGetHiiHandles (NULL
);
2247 ASSERT (HiiHandles
!= NULL
);
2250 // Search for formset of each class type
2252 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2253 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2260 CleanBrowserStorage(FormSet
);
2261 RemoveEntryList (&FormSet
->Link
);
2262 DestroyFormSet (FormSet
);
2265 FreePool (HiiHandles
);
2270 Check whether need to enable the reset flag in form level.
2271 Also clean all ValueChanged flag in question.
2273 @param SetFlag Whether need to set the Reset Flag.
2274 @param Form Form data structure.
2280 IN FORM_BROWSER_FORM
*Form
2284 FORM_BROWSER_STATEMENT
*Question
;
2288 Link
= GetFirstNode (&Form
->StatementListHead
);
2289 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2290 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2292 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2293 gResetRequired
= TRUE
;
2296 if (Question
->ValueChanged
) {
2297 Question
->ValueChanged
= FALSE
;
2300 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2305 Check whether need to enable the reset flag.
2306 Also clean ValueChanged flag for all statements.
2308 Form level or formset level, only one.
2310 @param SetFlag Whether need to set the Reset Flag.
2311 @param FormSet FormSet data structure.
2312 @param Form Form data structure.
2316 ValueChangeResetFlagUpdate (
2318 IN FORM_BROWSER_FORMSET
*FormSet
,
2319 IN FORM_BROWSER_FORM
*Form
2322 FORM_BROWSER_FORM
*CurrentForm
;
2326 // Form != NULL means only check form level.
2329 UpdateFlagForForm(SetFlag
, Form
);
2333 Link
= GetFirstNode (&FormSet
->FormListHead
);
2334 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2335 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2336 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2338 UpdateFlagForForm(SetFlag
, CurrentForm
);
2343 Discard data based on the input setting scope (Form, FormSet or System).
2345 @param FormSet FormSet data structure.
2346 @param Form Form data structure.
2347 @param SettingScope Setting Scope for Discard action.
2349 @retval EFI_SUCCESS The function completed successfully.
2350 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2355 IN FORM_BROWSER_FORMSET
*FormSet
,
2356 IN FORM_BROWSER_FORM
*Form
,
2357 IN BROWSER_SETTING_SCOPE SettingScope
2361 FORMSET_STORAGE
*Storage
;
2362 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2363 FORM_BROWSER_FORMSET
*LocalFormSet
;
2366 // Check the supported setting level.
2368 if (SettingScope
>= MaxLevel
) {
2369 return EFI_UNSUPPORTED
;
2372 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2374 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2375 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2376 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2377 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2379 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2384 // Skip if there is no RequestElement
2386 if (ConfigInfo
->ElementCount
== 0) {
2391 // Prepare <ConfigResp>
2393 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2396 // Call callback with Changed type to inform the driver.
2398 SendDiscardInfoToDriver (FormSet
, Form
);
2401 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2402 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2405 // Discard Buffer storage or Name/Value storage
2407 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2408 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2409 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2410 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2412 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2417 // Skip if there is no RequestElement
2419 if (Storage
->ElementCount
== 0) {
2423 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2426 Link
= GetFirstNode (&FormSet
->FormListHead
);
2427 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2428 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2429 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2432 // Call callback with Changed type to inform the driver.
2434 SendDiscardInfoToDriver (FormSet
, Form
);
2437 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2438 } else if (SettingScope
== SystemLevel
) {
2440 // System Level Discard.
2444 // Discard changed value for each FormSet in the maintain list.
2446 Link
= GetFirstNode (&gBrowserFormSetList
);
2447 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2448 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2449 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2450 if (!ValidateFormSet(LocalFormSet
)) {
2453 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2454 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2456 // Remove maintain backup list after discard except for the current using FormSet.
2458 CleanBrowserStorage(LocalFormSet
);
2459 RemoveEntryList (&LocalFormSet
->Link
);
2460 DestroyFormSet (LocalFormSet
);
2469 Submit data based on the input Setting level (Form, FormSet or System).
2471 @param FormSet FormSet data structure.
2472 @param Form Form data structure.
2473 @param SettingScope Setting Scope for Submit action.
2475 @retval EFI_SUCCESS The function completed successfully.
2476 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2481 IN FORM_BROWSER_FORMSET
*FormSet
,
2482 IN FORM_BROWSER_FORM
*Form
,
2483 IN BROWSER_SETTING_SCOPE SettingScope
2488 EFI_STRING ConfigResp
;
2489 EFI_STRING Progress
;
2490 BROWSER_STORAGE
*Storage
;
2491 FORMSET_STORAGE
*FormSetStorage
;
2494 FORM_BROWSER_FORMSET
*LocalFormSet
;
2495 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2498 // Check the supported setting level.
2500 if (SettingScope
>= MaxLevel
) {
2501 return EFI_UNSUPPORTED
;
2505 // Validate the Form by NoSubmit check
2507 Status
= EFI_SUCCESS
;
2508 if (SettingScope
== FormLevel
) {
2509 Status
= NoSubmitCheck (FormSet
, Form
);
2510 } else if (SettingScope
== FormSetLevel
) {
2511 Status
= NoSubmitCheck (FormSet
, NULL
);
2513 if (EFI_ERROR (Status
)) {
2517 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2519 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2520 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2521 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2522 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2524 Storage
= ConfigInfo
->Storage
;
2525 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2530 // Skip if there is no RequestElement
2532 if (ConfigInfo
->ElementCount
== 0) {
2537 // 1. Prepare <ConfigResp>
2539 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2540 if (EFI_ERROR (Status
)) {
2545 // 2. Set value to hii driver or efi variable.
2547 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2548 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2550 // Send <ConfigResp> to Configuration Driver
2552 if (FormSet
->ConfigAccess
!= NULL
) {
2553 Status
= FormSet
->ConfigAccess
->RouteConfig (
2554 FormSet
->ConfigAccess
,
2558 if (EFI_ERROR (Status
)) {
2559 FreePool (ConfigResp
);
2563 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2565 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2566 if (TmpBuf
== NULL
) {
2567 Status
= EFI_OUT_OF_RESOURCES
;
2571 BufferSize
= Storage
->Size
;
2572 Status
= gRT
->GetVariable (
2579 if (EFI_ERROR (Status
)) {
2581 FreePool (ConfigResp
);
2584 ASSERT (BufferSize
== Storage
->Size
);
2585 Status
= mHiiConfigRouting
->ConfigToBlock (
2592 if (EFI_ERROR (Status
)) {
2594 FreePool (ConfigResp
);
2598 Status
= gRT
->SetVariable (
2601 Storage
->Attributes
,
2606 if (EFI_ERROR (Status
)) {
2607 FreePool (ConfigResp
);
2611 FreePool (ConfigResp
);
2613 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2615 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2619 // 4. Update the NV flag.
2621 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2622 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2624 // Submit Buffer storage or Name/Value storage
2626 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2627 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2628 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2629 Storage
= FormSetStorage
->BrowserStorage
;
2630 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2632 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2637 // Skip if there is no RequestElement
2639 if (FormSetStorage
->ElementCount
== 0) {
2644 // 1. Prepare <ConfigResp>
2646 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2647 if (EFI_ERROR (Status
)) {
2651 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2652 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2655 // 2. Send <ConfigResp> to Configuration Driver
2657 if (FormSet
->ConfigAccess
!= NULL
) {
2658 Status
= FormSet
->ConfigAccess
->RouteConfig (
2659 FormSet
->ConfigAccess
,
2663 if (EFI_ERROR (Status
)) {
2664 FreePool (ConfigResp
);
2668 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2670 // 1&2. Set the edit data to the variable.
2673 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2674 if (TmpBuf
== NULL
) {
2675 Status
= EFI_OUT_OF_RESOURCES
;
2678 BufferSize
= Storage
->Size
;
2679 Status
= gRT
->GetVariable (
2686 ASSERT (BufferSize
== Storage
->Size
);
2687 Status
= mHiiConfigRouting
->ConfigToBlock (
2694 if (EFI_ERROR (Status
)) {
2696 FreePool (ConfigResp
);
2700 Status
= gRT
->SetVariable (
2703 Storage
->Attributes
,
2707 if (EFI_ERROR (Status
)) {
2709 FreePool (ConfigResp
);
2714 FreePool (ConfigResp
);
2716 // 3. Config success, update storage shadow Buffer
2718 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2722 // 4. Update the NV flag.
2724 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2725 } else if (SettingScope
== SystemLevel
) {
2727 // System Level Save.
2731 // Save changed value for each FormSet in the maintain list.
2733 Link
= GetFirstNode (&gBrowserFormSetList
);
2734 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2735 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2736 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2737 if (!ValidateFormSet(LocalFormSet
)) {
2740 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2741 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2743 // Remove maintain backup list after save except for the current using FormSet.
2745 CleanBrowserStorage(LocalFormSet
);
2746 RemoveEntryList (&LocalFormSet
->Link
);
2747 DestroyFormSet (LocalFormSet
);
2756 Get Question default value from AltCfg string.
2758 @param FormSet The form set.
2759 @param Question The question.
2760 @param DefaultId The default Id.
2762 @retval EFI_SUCCESS Question is reset to default value.
2766 GetDefaultValueFromAltCfg (
2767 IN FORM_BROWSER_FORMSET
*FormSet
,
2768 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2772 BOOLEAN IsBufferStorage
;
2775 BROWSER_STORAGE
*Storage
;
2776 CHAR16
*ConfigRequest
;
2789 Status
= EFI_NOT_FOUND
;
2792 ConfigRequest
= NULL
;
2796 Storage
= Question
->Storage
;
2798 if ((Storage
== NULL
) ||
2799 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2800 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2805 // Question Value is provided by Buffer Storage or NameValue Storage
2807 if (Question
->BufferValue
!= NULL
) {
2809 // This Question is password or orderedlist
2811 Dst
= Question
->BufferValue
;
2814 // Other type of Questions
2816 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2819 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2820 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2823 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2824 // <ConfigHdr> + "&" + <VariableName>
2826 if (IsBufferStorage
) {
2827 Length
= StrLen (Storage
->ConfigHdr
);
2828 Length
+= StrLen (Question
->BlockName
);
2830 Length
= StrLen (Storage
->ConfigHdr
);
2831 Length
+= StrLen (Question
->VariableName
) + 1;
2833 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2834 ASSERT (ConfigRequest
!= NULL
);
2836 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2837 if (IsBufferStorage
) {
2838 StrCat (ConfigRequest
, Question
->BlockName
);
2840 StrCat (ConfigRequest
, L
"&");
2841 StrCat (ConfigRequest
, Question
->VariableName
);
2844 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2845 FormSet
->ConfigAccess
,
2850 if (EFI_ERROR (Status
)) {
2855 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2856 // Get the default configuration string according to the default ID.
2858 Status
= mHiiConfigRouting
->GetAltConfig (
2864 &DefaultId
, // it can be NULL to get the current setting.
2869 // The required setting can't be found. So, it is not required to be validated and set.
2871 if (EFI_ERROR (Status
)) {
2876 // Skip <ConfigRequest>
2878 if (IsBufferStorage
) {
2879 Value
= StrStr (ConfigResp
, L
"&VALUE");
2880 ASSERT (Value
!= NULL
);
2886 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2887 ASSERT (Value
!= NULL
);
2889 Value
= Value
+ StrLen (Question
->VariableName
);
2891 if (*Value
!= '=') {
2892 Status
= EFI_NOT_FOUND
;
2896 // Skip '=', point to value
2901 // Suppress <AltResp> if any
2904 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2909 LengthStr
= StrLen (Value
);
2910 if (!IsBufferStorage
&& IsString
) {
2911 StringPtr
= (CHAR16
*) Dst
;
2912 ZeroMem (TemStr
, sizeof (TemStr
));
2913 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2914 StrnCpy (TemStr
, Value
+ Index
, 4);
2915 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2918 // Add tailing L'\0' character
2920 StringPtr
[Index
/4] = L
'\0';
2922 ZeroMem (TemStr
, sizeof (TemStr
));
2923 for (Index
= 0; Index
< LengthStr
; Index
++) {
2924 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2925 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2926 if ((Index
& 1) == 0) {
2927 Dst
[Index
/2] = DigitUint8
;
2929 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2935 if (ConfigRequest
!= NULL
){
2936 FreePool (ConfigRequest
);
2939 if (ConfigResp
!= NULL
) {
2940 FreePool (ConfigResp
);
2943 if (Result
!= NULL
) {
2951 Get default Id value used for browser.
2953 @param DefaultId The default id value used by hii.
2955 @retval Browser used default value.
2959 GetDefaultIdForCallBack (
2963 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2964 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2965 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2966 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2967 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2968 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2969 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2970 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2971 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2972 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2973 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2974 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2983 Return data element in an Array by its Index.
2985 @param Array The data array.
2986 @param Type Type of the data in this array.
2987 @param Index Zero based index for data in this array.
2989 @retval Value The data to be returned
3001 ASSERT (Array
!= NULL
);
3005 case EFI_IFR_TYPE_NUM_SIZE_8
:
3006 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3009 case EFI_IFR_TYPE_NUM_SIZE_16
:
3010 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3013 case EFI_IFR_TYPE_NUM_SIZE_32
:
3014 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3017 case EFI_IFR_TYPE_NUM_SIZE_64
:
3018 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3030 Set value of a data element in an Array by its Index.
3032 @param Array The data array.
3033 @param Type Type of the data in this array.
3034 @param Index Zero based index for data in this array.
3035 @param Value The value to be set.
3047 ASSERT (Array
!= NULL
);
3050 case EFI_IFR_TYPE_NUM_SIZE_8
:
3051 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3054 case EFI_IFR_TYPE_NUM_SIZE_16
:
3055 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3058 case EFI_IFR_TYPE_NUM_SIZE_32
:
3059 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3062 case EFI_IFR_TYPE_NUM_SIZE_64
:
3063 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3072 Search an Option of a Question by its value.
3074 @param Question The Question
3075 @param OptionValue Value for Option to be searched.
3077 @retval Pointer Pointer to the found Option.
3078 @retval NULL Option not found.
3083 IN FORM_BROWSER_STATEMENT
*Question
,
3084 IN EFI_HII_VALUE
*OptionValue
3088 QUESTION_OPTION
*Option
;
3091 Link
= GetFirstNode (&Question
->OptionListHead
);
3092 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3093 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3095 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3097 // Check the suppressif condition, only a valid option can be return.
3099 if ((Option
->SuppressExpression
== NULL
) ||
3100 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3105 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3113 Reset Question to its default value.
3115 @param FormSet The form set.
3116 @param Form The form.
3117 @param Question The question.
3118 @param DefaultId The Class of the default.
3120 @retval EFI_SUCCESS Question is reset to default value.
3124 GetQuestionDefault (
3125 IN FORM_BROWSER_FORMSET
*FormSet
,
3126 IN FORM_BROWSER_FORM
*Form
,
3127 IN FORM_BROWSER_STATEMENT
*Question
,
3133 QUESTION_DEFAULT
*Default
;
3134 QUESTION_OPTION
*Option
;
3135 EFI_HII_VALUE
*HiiValue
;
3137 EFI_STRING StrValue
;
3138 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3139 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3142 Status
= EFI_NOT_FOUND
;
3146 // Statement don't have storage, skip them
3148 if (Question
->QuestionId
== 0) {
3153 // There are Five ways to specify default value for a Question:
3154 // 1, use call back function (highest priority)
3155 // 2, use ExtractConfig function
3156 // 3, use nested EFI_IFR_DEFAULT
3157 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3158 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3160 HiiValue
= &Question
->HiiValue
;
3163 // Get Question defaut value from call back function.
3165 ConfigAccess
= FormSet
->ConfigAccess
;
3166 Action
= GetDefaultIdForCallBack (DefaultId
);
3167 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3168 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3169 Status
= ConfigAccess
->Callback (
3172 Question
->QuestionId
,
3177 if (!EFI_ERROR (Status
)) {
3183 // Get default value from altcfg string.
3185 if (ConfigAccess
!= NULL
) {
3186 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3187 if (!EFI_ERROR (Status
)) {
3193 // EFI_IFR_DEFAULT has highest priority
3195 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3196 Link
= GetFirstNode (&Question
->DefaultListHead
);
3197 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3198 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3200 if (Default
->DefaultId
== DefaultId
) {
3201 if (Default
->ValueExpression
!= NULL
) {
3203 // Default is provided by an Expression, evaluate it
3205 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3206 if (EFI_ERROR (Status
)) {
3210 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3211 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3212 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3213 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3214 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3216 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3217 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3219 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3221 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3222 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3225 // Default value is embedded in EFI_IFR_DEFAULT
3227 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3230 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3231 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3232 if (StrValue
== NULL
) {
3233 return EFI_NOT_FOUND
;
3235 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3236 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3238 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3245 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3250 // EFI_ONE_OF_OPTION
3252 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3253 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3255 // OneOfOption could only provide Standard and Manufacturing default
3257 Link
= GetFirstNode (&Question
->OptionListHead
);
3258 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3259 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3260 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3262 if ((Option
->SuppressExpression
!= NULL
) &&
3263 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3267 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3268 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3270 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3279 // EFI_IFR_CHECKBOX - lowest priority
3281 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3282 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3284 // Checkbox could only provide Standard and Manufacturing default
3286 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3287 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3289 HiiValue
->Value
.b
= TRUE
;
3291 HiiValue
->Value
.b
= FALSE
;
3299 // For Questions without default
3301 Status
= EFI_NOT_FOUND
;
3302 switch (Question
->Operand
) {
3303 case EFI_IFR_NUMERIC_OP
:
3305 // Take minimum value as numeric default value
3307 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3308 HiiValue
->Value
.u64
= Question
->Minimum
;
3309 Status
= EFI_SUCCESS
;
3313 case EFI_IFR_ONE_OF_OP
:
3315 // Take first oneof option as oneof's default value
3317 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3318 Link
= GetFirstNode (&Question
->OptionListHead
);
3319 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3320 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3321 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3323 if ((Option
->SuppressExpression
!= NULL
) &&
3324 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3328 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3329 Status
= EFI_SUCCESS
;
3335 case EFI_IFR_ORDERED_LIST_OP
:
3337 // Take option sequence in IFR as ordered list's default value
3340 Link
= GetFirstNode (&Question
->OptionListHead
);
3341 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3342 Status
= EFI_SUCCESS
;
3343 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3344 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3346 if ((Option
->SuppressExpression
!= NULL
) &&
3347 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3351 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3354 if (Index
>= Question
->MaxContainers
) {
3369 Reset Questions to their initial value or default value in a Form, Formset or System.
3371 GetDefaultValueScope parameter decides which questions will reset
3372 to its default value.
3374 @param FormSet FormSet data structure.
3375 @param Form Form data structure.
3376 @param DefaultId The Class of the default.
3377 @param SettingScope Setting Scope for Default action.
3378 @param GetDefaultValueScope Get default value scope.
3379 @param Storage Get default value only for this storage.
3380 @param RetrieveValueFirst Whether call the retrieve call back to
3381 get the initial value before get default
3384 @retval EFI_SUCCESS The function completed successfully.
3385 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3390 IN FORM_BROWSER_FORMSET
*FormSet
,
3391 IN FORM_BROWSER_FORM
*Form
,
3392 IN UINT16 DefaultId
,
3393 IN BROWSER_SETTING_SCOPE SettingScope
,
3394 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3395 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3396 IN BOOLEAN RetrieveValueFirst
3400 LIST_ENTRY
*FormLink
;
3402 FORM_BROWSER_STATEMENT
*Question
;
3403 FORM_BROWSER_FORMSET
*LocalFormSet
;
3405 Status
= EFI_SUCCESS
;
3408 // Check the supported setting level.
3410 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3411 return EFI_UNSUPPORTED
;
3414 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3415 return EFI_UNSUPPORTED
;
3418 if (SettingScope
== FormLevel
) {
3420 // Extract Form default
3422 Link
= GetFirstNode (&Form
->StatementListHead
);
3423 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3424 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3425 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3428 // If get default value only for this storage, check the storage first.
3430 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3435 // If get default value only for no storage question, just skip the question which has storage.
3437 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3442 // If Question is disabled, don't reset it to default
3444 if (Question
->Expression
!= NULL
) {
3445 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3450 if (RetrieveValueFirst
) {
3452 // Call the Retrieve call back to get the initial question value.
3454 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3458 // If not request to get the initial value or get initial value fail, then get default value.
3460 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3461 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3462 if (EFI_ERROR (Status
)) {
3468 // Synchronize Buffer storage's Edit buffer
3470 if ((Question
->Storage
!= NULL
) &&
3471 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3472 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3475 } else if (SettingScope
== FormSetLevel
) {
3476 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3477 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3478 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3479 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3480 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3482 } else if (SettingScope
== SystemLevel
) {
3484 // Preload all Hii formset.
3486 LoadAllHiiFormset();
3489 // Set Default Value for each FormSet in the maintain list.
3491 Link
= GetFirstNode (&gBrowserFormSetList
);
3492 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3493 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3494 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3495 if (!ValidateFormSet(LocalFormSet
)) {
3498 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3507 Validate whether this question's value has changed.
3509 @param FormSet FormSet data structure.
3510 @param Form Form data structure.
3511 @param Question Question to be initialized.
3512 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3514 @retval TRUE Question's value has changed.
3515 @retval FALSE Question's value has not changed
3519 IsQuestionValueChanged (
3520 IN FORM_BROWSER_FORMSET
*FormSet
,
3521 IN FORM_BROWSER_FORM
*Form
,
3522 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3523 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3526 EFI_HII_VALUE BackUpValue
;
3527 CHAR8
*BackUpBuffer
;
3529 BOOLEAN ValueChanged
;
3533 // For quetion without storage, always mark it as data not changed.
3535 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3539 BackUpBuffer
= NULL
;
3540 ValueChanged
= FALSE
;
3542 switch (Question
->Operand
) {
3543 case EFI_IFR_ORDERED_LIST_OP
:
3544 BufferWidth
= Question
->StorageWidth
;
3545 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3546 ASSERT (BackUpBuffer
!= NULL
);
3549 case EFI_IFR_STRING_OP
:
3550 case EFI_IFR_PASSWORD_OP
:
3551 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3552 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3553 ASSERT (BackUpBuffer
!= NULL
);
3560 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3562 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3563 ASSERT_EFI_ERROR(Status
);
3565 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3566 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3567 ValueChanged
= TRUE
;
3570 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3571 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3573 if (BackUpBuffer
!= NULL
) {
3574 FreePool (BackUpBuffer
);
3577 return ValueChanged
;
3581 Initialize Question's Edit copy from Storage.
3583 @param Selection Selection contains the information about
3584 the Selection, form and formset to be displayed.
3585 Selection action may be updated in retrieve callback.
3586 If Selection is NULL, only initialize Question value.
3587 @param FormSet FormSet data structure.
3588 @param Form Form data structure.
3590 @retval EFI_SUCCESS The function completed successfully.
3595 IN OUT UI_MENU_SELECTION
*Selection
,
3596 IN FORM_BROWSER_FORMSET
*FormSet
,
3597 IN FORM_BROWSER_FORM
*Form
3602 FORM_BROWSER_STATEMENT
*Question
;
3606 Link
= GetFirstNode (&Form
->StatementListHead
);
3607 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3608 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3611 // Initialize local copy of Value for each Question
3613 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3614 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3616 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3618 if (EFI_ERROR (Status
)) {
3622 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3623 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3627 // Call the Retrieve call back function for all questions.
3629 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3630 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3632 // Check QuestionValue does exist.
3634 StorageWidth
= Question
->StorageWidth
;
3635 if (Question
->BufferValue
!= NULL
) {
3636 BufferValue
= Question
->BufferValue
;
3638 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3642 // For efivarstore storage, initial question value first.
3644 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3645 Status
= gRT
->GetVariable (
3646 Question
->VariableName
,
3647 &Question
->Storage
->Guid
,
3654 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3658 // Update Question Value changed flag.
3660 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
3662 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3669 Initialize Question's Edit copy from Storage for the whole Formset.
3671 @param Selection Selection contains the information about
3672 the Selection, form and formset to be displayed.
3673 Selection action may be updated in retrieve callback.
3674 If Selection is NULL, only initialize Question value.
3675 @param FormSet FormSet data structure.
3677 @retval EFI_SUCCESS The function completed successfully.
3682 IN OUT UI_MENU_SELECTION
*Selection
,
3683 IN FORM_BROWSER_FORMSET
*FormSet
3688 FORM_BROWSER_FORM
*Form
;
3690 Link
= GetFirstNode (&FormSet
->FormListHead
);
3691 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3692 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3695 // Initialize local copy of Value for each Form
3697 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3698 if (EFI_ERROR (Status
)) {
3702 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3706 // Finished question initialization.
3708 FormSet
->QuestionInited
= TRUE
;
3714 Remove the Request element from the Config Request.
3716 @param Storage Pointer to the browser storage.
3717 @param RequestElement The pointer to the Request element.
3722 IN OUT BROWSER_STORAGE
*Storage
,
3723 IN CHAR16
*RequestElement
3729 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3731 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3733 if (NewStr
== NULL
) {
3738 // Remove this element from this ConfigRequest.
3741 NewStr
+= StrLen (RequestElement
);
3742 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3744 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3748 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3750 @param Storage Pointer to the browser storage.
3751 @param ConfigRequest The pointer to the Request element.
3755 RemoveConfigRequest (
3756 BROWSER_STORAGE
*Storage
,
3757 CHAR16
*ConfigRequest
3760 CHAR16
*RequestElement
;
3761 CHAR16
*NextRequestElement
;
3765 // No request element in it, just return.
3767 if (ConfigRequest
== NULL
) {
3771 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3773 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3778 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3780 SearchKey
= L
"&OFFSET";
3784 // Find SearchKey storage
3786 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3787 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3788 ASSERT (RequestElement
!= NULL
);
3789 RequestElement
= StrStr (RequestElement
, SearchKey
);
3791 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3794 while (RequestElement
!= NULL
) {
3796 // +1 to avoid find header itself.
3798 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3801 // The last Request element in configRequest string.
3803 if (NextRequestElement
!= NULL
) {
3805 // Replace "&" with '\0'.
3807 *NextRequestElement
= L
'\0';
3810 RemoveElement (Storage
, RequestElement
);
3812 if (NextRequestElement
!= NULL
) {
3814 // Restore '&' with '\0' for later used.
3816 *NextRequestElement
= L
'&';
3819 RequestElement
= NextRequestElement
;
3823 // If no request element remain, just remove the ConfigRequest string.
3825 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3826 FreePool (Storage
->ConfigRequest
);
3827 Storage
->ConfigRequest
= NULL
;
3828 Storage
->SpareStrLen
= 0;
3833 Base on the current formset info, clean the ConfigRequest string in browser storage.
3835 @param FormSet Pointer of the FormSet
3839 CleanBrowserStorage (
3840 IN OUT FORM_BROWSER_FORMSET
*FormSet
3844 FORMSET_STORAGE
*Storage
;
3845 CHAR16
*ConfigRequest
;
3847 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3848 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3849 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3850 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3852 if ((Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_BUFFER
) &&
3853 (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) &&
3854 (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3858 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3862 ConfigRequest
= FormSet
->QuestionInited
? Storage
->ConfigRequest
: Storage
->ConfigElements
;
3863 RemoveConfigRequest (Storage
->BrowserStorage
, ConfigRequest
);
3868 Check whether current element in the ConfigReqeust string.
3870 @param BrowserStorage Storage which includes ConfigReqeust.
3871 @param RequestElement New element need to check.
3873 @retval TRUE The Element is in the ConfigReqeust string.
3874 @retval FALSE The Element not in the configReqeust String.
3879 BROWSER_STORAGE
*BrowserStorage
,
3880 CHAR16
*RequestElement
3883 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3887 Append the Request element to the Config Request.
3889 @param ConfigRequest Current ConfigRequest info.
3890 @param SpareStrLen Current remain free buffer for config reqeust.
3891 @param RequestElement New Request element.
3895 AppendConfigRequest (
3896 IN OUT CHAR16
**ConfigRequest
,
3897 IN OUT UINTN
*SpareStrLen
,
3898 IN CHAR16
*RequestElement
3905 StrLength
= StrLen (RequestElement
);
3908 // Append <RequestElement> to <ConfigRequest>
3910 if (StrLength
> *SpareStrLen
) {
3912 // Old String buffer is not sufficient for RequestElement, allocate a new one
3914 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3915 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3916 ASSERT (NewStr
!= NULL
);
3918 if (*ConfigRequest
!= NULL
) {
3919 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3920 FreePool (*ConfigRequest
);
3922 *ConfigRequest
= NewStr
;
3923 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3926 StrCat (*ConfigRequest
, RequestElement
);
3927 *SpareStrLen
-= StrLength
;
3931 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3933 @param Storage Form set Storage.
3935 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3936 @retval FALSE All elements covered by current used elements.
3940 ConfigRequestAdjust (
3941 IN FORMSET_STORAGE
*Storage
3944 CHAR16
*RequestElement
;
3945 CHAR16
*NextRequestElement
;
3955 if (Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3956 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3957 if (Storage
->ConfigElements
!= NULL
) {
3958 FreePool (Storage
->ConfigElements
);
3960 Storage
->ConfigElements
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3964 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3966 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3971 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3973 SearchKey
= L
"&OFFSET";
3977 // Prepare the config header.
3979 RetBuf
= AllocateCopyPool(StrSize (Storage
->BrowserStorage
->ConfigHdr
), Storage
->BrowserStorage
->ConfigHdr
);
3980 ASSERT (RetBuf
!= NULL
);
3983 // Find SearchKey storage
3985 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3986 RequestElement
= StrStr (Storage
->ConfigRequest
, L
"PATH");
3987 ASSERT (RequestElement
!= NULL
);
3988 RequestElement
= StrStr (RequestElement
, SearchKey
);
3990 RequestElement
= StrStr (Storage
->ConfigRequest
, SearchKey
);
3993 while (RequestElement
!= NULL
) {
3995 // +1 to avoid find header itself.
3997 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4000 // The last Request element in configRequest string.
4002 if (NextRequestElement
!= NULL
) {
4004 // Replace "&" with '\0'.
4006 *NextRequestElement
= L
'\0';
4009 if (!ElementValidation (Storage
->BrowserStorage
, RequestElement
)) {
4011 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4013 AppendConfigRequest(&Storage
->BrowserStorage
->ConfigRequest
, &Storage
->BrowserStorage
->SpareStrLen
, RequestElement
);
4014 AppendConfigRequest (&RetBuf
, &SpareBufLen
, RequestElement
);
4018 if (NextRequestElement
!= NULL
) {
4020 // Restore '&' with '\0' for later used.
4022 *NextRequestElement
= L
'&';
4025 RequestElement
= NextRequestElement
;
4029 if (Storage
->ConfigElements
!= NULL
) {
4030 FreePool (Storage
->ConfigElements
);
4032 Storage
->ConfigElements
= RetBuf
;
4042 Base on ConfigRequest info to get default value for current formset.
4044 ConfigRequest info include the info about which questions in current formset need to
4045 get default value. This function only get these questions default value.
4047 @param FormSet FormSet data structure.
4048 @param Storage Storage need to update value.
4049 @param ConfigRequest The config request string.
4053 GetDefaultForFormset (
4054 IN FORM_BROWSER_FORMSET
*FormSet
,
4055 IN BROWSER_STORAGE
*Storage
,
4056 IN CHAR16
*ConfigRequest
4061 LIST_ENTRY BackUpList
;
4062 NAME_VALUE_NODE
*Node
;
4064 LIST_ENTRY
*NodeLink
;
4065 NAME_VALUE_NODE
*TmpNode
;
4067 EFI_STRING Progress
;
4071 InitializeListHead(&BackUpList
);
4074 // Back update the edit buffer.
4076 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4077 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4078 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4079 ASSERT (BackUpBuf
!= NULL
);
4080 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4081 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4082 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4083 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4084 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4087 // Only back Node belong to this formset.
4089 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4093 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4094 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4095 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4097 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4102 // Get default value.
4104 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4107 // Update the question value based on the input ConfigRequest.
4109 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4110 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4111 ASSERT (BackUpBuf
!= NULL
);
4112 BufferSize
= Storage
->Size
;
4113 Status
= mHiiConfigRouting
->BlockToConfig(
4116 Storage
->EditBuffer
,
4121 ASSERT_EFI_ERROR (Status
);
4123 Status
= mHiiConfigRouting
->ConfigToBlock (
4130 ASSERT_EFI_ERROR (Status
);
4132 if (Result
!= NULL
) {
4136 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4137 FreePool (BackUpBuf
);
4138 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4140 // Update question value, only element in ConfigReqeust will be update.
4142 Link
= GetFirstNode (&BackUpList
);
4143 while (!IsNull (&BackUpList
, Link
)) {
4144 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4145 Link
= GetNextNode (&BackUpList
, Link
);
4147 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4151 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4152 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4153 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4154 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4156 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4160 FreePool (TmpNode
->EditValue
);
4161 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4163 RemoveEntryList (&Node
->Link
);
4164 FreePool (Node
->EditValue
);
4165 FreePool (Node
->Name
);
4171 // Restore the Name/Value node.
4173 Link
= GetFirstNode (&BackUpList
);
4174 while (!IsNull (&BackUpList
, Link
)) {
4175 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4176 Link
= GetNextNode (&BackUpList
, Link
);
4181 RemoveEntryList (&Node
->Link
);
4182 FreePool (Node
->EditValue
);
4183 FreePool (Node
->Name
);
4190 Fill storage's edit copy with settings requested from Configuration Driver.
4192 @param FormSet FormSet data structure.
4193 @param Storage Buffer Storage.
4198 IN FORM_BROWSER_FORMSET
*FormSet
,
4199 IN FORMSET_STORAGE
*Storage
4203 EFI_STRING Progress
;
4207 switch (Storage
->BrowserStorage
->Type
) {
4208 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4211 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4212 if (Storage
->BrowserStorage
->ReferenceCount
> 1) {
4213 ConfigRequestAdjust(Storage
);
4217 Status
= gRT
->GetVariable (
4218 Storage
->BrowserStorage
->Name
,
4219 &Storage
->BrowserStorage
->Guid
,
4221 (UINTN
*)&Storage
->BrowserStorage
->Size
,
4222 Storage
->BrowserStorage
->EditBuffer
4225 // If get variable fail, extract default from IFR binary
4227 if (EFI_ERROR (Status
)) {
4228 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4231 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4233 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4235 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4238 case EFI_HII_VARSTORE_BUFFER
:
4239 case EFI_HII_VARSTORE_NAME_VALUE
:
4241 // Skip if there is no RequestElement
4243 if (Storage
->ElementCount
== 0) {
4248 // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig
4249 // will used to call ExtractConfig.
4250 // If not elements need to udpate, return.
4252 if (!ConfigRequestAdjust(Storage
)) {
4255 ASSERT (Storage
->ConfigElements
!= NULL
);
4257 Status
= EFI_NOT_FOUND
;
4258 if (FormSet
->ConfigAccess
!= NULL
) {
4260 // Request current settings from Configuration Driver
4262 Status
= FormSet
->ConfigAccess
->ExtractConfig (
4263 FormSet
->ConfigAccess
,
4264 Storage
->ConfigElements
,
4269 if (!EFI_ERROR (Status
)) {
4271 // Convert Result from <ConfigAltResp> to <ConfigResp>
4273 StrPtr
= StrStr (Result
, L
"&GUID=");
4274 if (StrPtr
!= NULL
) {
4278 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4283 if (EFI_ERROR (Status
)) {
4285 // Base on the configRequest string to get default value.
4287 GetDefaultForFormset (FormSet
, Storage
->BrowserStorage
, Storage
->ConfigElements
);
4290 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigElements
, TRUE
);
4299 Get current setting of Questions.
4301 @param FormSet FormSet data structure.
4305 InitializeCurrentSetting (
4306 IN OUT FORM_BROWSER_FORMSET
*FormSet
4310 FORMSET_STORAGE
*Storage
;
4311 FORM_BROWSER_FORMSET
*OldFormSet
;
4314 // Extract default from IFR binary for no storage questions.
4316 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4319 // Request current settings from Configuration Driver
4321 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4322 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4323 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4325 LoadStorage (FormSet
, Storage
);
4327 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4331 // Try to find pre FormSet in the maintain backup list.
4332 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4334 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4335 if (OldFormSet
!= NULL
) {
4336 RemoveEntryList (&OldFormSet
->Link
);
4337 DestroyFormSet (OldFormSet
);
4339 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4344 Fetch the Ifr binary data of a FormSet.
4346 @param Handle PackageList Handle
4347 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4348 specified (NULL or zero GUID), take the first
4349 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4350 found in package list.
4351 On output, GUID of the formset found(if not NULL).
4352 @param BinaryLength The length of the FormSet IFR binary.
4353 @param BinaryData The buffer designed to receive the FormSet.
4355 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4356 BufferLength was updated.
4357 @retval EFI_INVALID_PARAMETER The handle is unknown.
4358 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4359 be found with the requested FormId.
4364 IN EFI_HII_HANDLE Handle
,
4365 IN OUT EFI_GUID
*FormSetGuid
,
4366 OUT UINTN
*BinaryLength
,
4367 OUT UINT8
**BinaryData
4371 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4377 UINT32 PackageListLength
;
4378 EFI_HII_PACKAGE_HEADER PackageHeader
;
4380 UINT8 NumberOfClassGuid
;
4381 BOOLEAN ClassGuidMatch
;
4382 EFI_GUID
*ClassGuid
;
4383 EFI_GUID
*ComparingGuid
;
4387 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4390 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4392 if (FormSetGuid
== NULL
) {
4393 ComparingGuid
= &gZeroGuid
;
4395 ComparingGuid
= FormSetGuid
;
4399 // Get HII PackageList
4402 HiiPackageList
= NULL
;
4403 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4404 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4405 HiiPackageList
= AllocatePool (BufferSize
);
4406 ASSERT (HiiPackageList
!= NULL
);
4408 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4410 if (EFI_ERROR (Status
)) {
4413 ASSERT (HiiPackageList
!= NULL
);
4416 // Get Form package from this HII package List
4418 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4420 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4422 ClassGuidMatch
= FALSE
;
4423 while (Offset
< PackageListLength
) {
4424 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4425 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4427 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4429 // Search FormSet in this Form Package
4431 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4432 while (Offset2
< PackageHeader
.Length
) {
4433 OpCodeData
= Package
+ Offset2
;
4435 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4437 // Try to compare against formset GUID
4439 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4440 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4444 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4446 // Try to compare against formset class GUID
4448 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4449 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4450 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4451 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4452 ClassGuidMatch
= TRUE
;
4456 if (ClassGuidMatch
) {
4459 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4460 ClassGuidMatch
= TRUE
;
4465 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4468 if (Offset2
< PackageHeader
.Length
) {
4470 // Target formset found
4476 Offset
+= PackageHeader
.Length
;
4479 if (Offset
>= PackageListLength
) {
4481 // Form package not found in this Package List
4483 FreePool (HiiPackageList
);
4484 return EFI_NOT_FOUND
;
4487 if (FormSetGuid
!= NULL
) {
4489 // Return the FormSet GUID
4491 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4495 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4496 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4497 // of the Form Package.
4499 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4500 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4502 FreePool (HiiPackageList
);
4504 if (*BinaryData
== NULL
) {
4505 return EFI_OUT_OF_RESOURCES
;
4513 Initialize the internal data structure of a FormSet.
4515 @param Handle PackageList Handle
4516 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4517 specified (NULL or zero GUID), take the first
4518 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4519 found in package list.
4520 On output, GUID of the formset found(if not NULL).
4521 @param FormSet FormSet data structure.
4523 @retval EFI_SUCCESS The function completed successfully.
4524 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4529 IN EFI_HII_HANDLE Handle
,
4530 IN OUT EFI_GUID
*FormSetGuid
,
4531 OUT FORM_BROWSER_FORMSET
*FormSet
4535 EFI_HANDLE DriverHandle
;
4537 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4538 if (EFI_ERROR (Status
)) {
4542 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4543 FormSet
->HiiHandle
= Handle
;
4544 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4545 FormSet
->QuestionInited
= FALSE
;
4548 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4550 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4551 if (EFI_ERROR (Status
)) {
4554 FormSet
->DriverHandle
= DriverHandle
;
4555 Status
= gBS
->HandleProtocol (
4557 &gEfiHiiConfigAccessProtocolGuid
,
4558 (VOID
**) &FormSet
->ConfigAccess
4560 if (EFI_ERROR (Status
)) {
4562 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4563 // list, then there will be no configuration action required
4565 FormSet
->ConfigAccess
= NULL
;
4569 // Parse the IFR binary OpCodes
4571 Status
= ParseOpCodes (FormSet
);
4578 Save globals used by previous call to SendForm(). SendForm() may be called from
4579 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4580 So, save globals of previous call to SendForm() and restore them upon exit.
4584 SaveBrowserContext (
4588 BROWSER_CONTEXT
*Context
;
4589 FORM_ENTRY_INFO
*MenuList
;
4591 gBrowserContextCount
++;
4592 if (gBrowserContextCount
== 1) {
4594 // This is not reentry of SendForm(), no context to save
4599 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4600 ASSERT (Context
!= NULL
);
4602 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4605 // Save FormBrowser context
4607 Context
->Selection
= gCurrentSelection
;
4608 Context
->ResetRequired
= gResetRequired
;
4609 Context
->ExitRequired
= gExitRequired
;
4610 Context
->HiiHandle
= mCurrentHiiHandle
;
4611 Context
->FormId
= mCurrentFormId
;
4612 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4615 // Save the menu history data.
4617 InitializeListHead(&Context
->FormHistoryList
);
4618 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4619 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4620 RemoveEntryList (&MenuList
->Link
);
4622 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4626 // Insert to FormBrowser context list
4628 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4633 Restore globals used by previous call to SendForm().
4637 RestoreBrowserContext (
4642 BROWSER_CONTEXT
*Context
;
4643 FORM_ENTRY_INFO
*MenuList
;
4645 ASSERT (gBrowserContextCount
!= 0);
4646 gBrowserContextCount
--;
4647 if (gBrowserContextCount
== 0) {
4649 // This is not reentry of SendForm(), no context to restore
4654 ASSERT (!IsListEmpty (&gBrowserContextList
));
4656 Link
= GetFirstNode (&gBrowserContextList
);
4657 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4660 // Restore FormBrowser context
4662 gCurrentSelection
= Context
->Selection
;
4663 gResetRequired
= Context
->ResetRequired
;
4664 gExitRequired
= Context
->ExitRequired
;
4665 mCurrentHiiHandle
= Context
->HiiHandle
;
4666 mCurrentFormId
= Context
->FormId
;
4667 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4670 // Restore the menu history data.
4672 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4673 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4674 RemoveEntryList (&MenuList
->Link
);
4676 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4680 // Remove from FormBrowser context list
4682 RemoveEntryList (&Context
->Link
);
4683 gBS
->FreePool (Context
);
4687 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4689 @param Handle The Hii Handle.
4691 @return the found FormSet context. If no found, NULL will return.
4694 FORM_BROWSER_FORMSET
*
4695 GetFormSetFromHiiHandle (
4696 EFI_HII_HANDLE Handle
4700 FORM_BROWSER_FORMSET
*FormSet
;
4702 Link
= GetFirstNode (&gBrowserFormSetList
);
4703 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4704 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4705 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4706 if (!ValidateFormSet(FormSet
)) {
4709 if (FormSet
->HiiHandle
== Handle
) {
4718 Check whether the input HII handle is the FormSet that is being used.
4720 @param Handle The Hii Handle.
4722 @retval TRUE HII handle is being used.
4723 @retval FALSE HII handle is not being used.
4727 IsHiiHandleInBrowserContext (
4728 EFI_HII_HANDLE Handle
4732 BROWSER_CONTEXT
*Context
;
4735 // HiiHandle is Current FormSet.
4737 if (mCurrentHiiHandle
== Handle
) {
4742 // Check whether HiiHandle is in BrowserContext.
4744 Link
= GetFirstNode (&gBrowserContextList
);
4745 while (!IsNull (&gBrowserContextList
, Link
)) {
4746 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4747 if (Context
->HiiHandle
== Handle
) {
4749 // HiiHandle is in BrowserContext
4753 Link
= GetNextNode (&gBrowserContextList
, Link
);
4760 Perform Password check.
4761 Passwork may be encrypted by driver that requires the specific check.
4763 @param Form Form where Password Statement is in.
4764 @param Statement Password statement
4765 @param PasswordString Password string to be checked. It may be NULL.
4766 NULL means to restore password.
4767 "" string can be used to checked whether old password does exist.
4769 @return Status Status of Password check.
4774 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4775 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4776 IN EFI_STRING PasswordString OPTIONAL
4780 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4781 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4782 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4783 FORM_BROWSER_STATEMENT
*Question
;
4785 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4786 Question
= GetBrowserStatement(Statement
);
4787 ASSERT (Question
!= NULL
);
4789 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4790 if (ConfigAccess
== NULL
) {
4791 return EFI_UNSUPPORTED
;
4794 if (PasswordString
== NULL
) {
4798 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4801 return EFI_NOT_READY
;
4806 // Prepare password string in HII database
4808 if (PasswordString
!= NULL
) {
4809 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4811 IfrTypeValue
.string
= 0;
4815 // Send password to Configuration Driver for validation
4817 Status
= ConfigAccess
->Callback (
4819 EFI_BROWSER_ACTION_CHANGING
,
4820 Question
->QuestionId
,
4821 Question
->HiiValue
.Type
,
4827 // Remove password string from HII database
4829 if (PasswordString
!= NULL
) {
4830 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4837 Find the registered HotKey based on KeyData.
4839 @param[in] KeyData A pointer to a buffer that describes the keystroke
4840 information for the hot key.
4842 @return The registered HotKey context. If no found, NULL will return.
4845 GetHotKeyFromRegisterList (
4846 IN EFI_INPUT_KEY
*KeyData
4850 BROWSER_HOT_KEY
*HotKey
;
4852 Link
= GetFirstNode (&gBrowserHotKeyList
);
4853 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4854 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4855 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4858 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4865 Configure what scope the hot key will impact.
4866 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4867 If no scope is set, the default scope will be FormSet level.
4868 After all registered hot keys are removed, previous Scope can reset to another level.
4870 @param[in] Scope Scope level to be set.
4872 @retval EFI_SUCCESS Scope is set correctly.
4873 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4874 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4880 IN BROWSER_SETTING_SCOPE Scope
4883 if (Scope
>= MaxLevel
) {
4884 return EFI_INVALID_PARAMETER
;
4888 // When no hot key registered in system or on the first setting,
4889 // Scope can be set.
4891 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4892 gBrowserSettingScope
= Scope
;
4893 mBrowserScopeFirstSet
= FALSE
;
4894 } else if (Scope
!= gBrowserSettingScope
) {
4895 return EFI_UNSUPPORTED
;
4902 Register the hot key with its browser action, or unregistered the hot key.
4903 Only support hot key that is not printable character (control key, function key, etc.).
4904 If the action value is zero, the hot key will be unregistered if it has been registered.
4905 If the same hot key has been registered, the new action and help string will override the previous ones.
4907 @param[in] KeyData A pointer to a buffer that describes the keystroke
4908 information for the hot key. Its type is EFI_INPUT_KEY to
4909 be supported by all ConsoleIn devices.
4910 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4911 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4912 @param[in] HelpString Help string that describes the hot key information.
4913 Its value may be NULL for the unregistered hot key.
4915 @retval EFI_SUCCESS Hot key is registered or unregistered.
4916 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4917 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4918 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4923 IN EFI_INPUT_KEY
*KeyData
,
4925 IN UINT16 DefaultId
,
4926 IN EFI_STRING HelpString OPTIONAL
4929 BROWSER_HOT_KEY
*HotKey
;
4932 // Check input parameters.
4934 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4935 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4936 return EFI_INVALID_PARAMETER
;
4940 // Check whether the input KeyData is in BrowserHotKeyList.
4942 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4945 // Unregister HotKey
4947 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4948 if (HotKey
!= NULL
) {
4950 // The registered HotKey is found.
4951 // Remove it from List, and free its resource.
4953 RemoveEntryList (&HotKey
->Link
);
4954 FreePool (HotKey
->KeyData
);
4955 FreePool (HotKey
->HelpString
);
4959 // The registered HotKey is not found.
4961 return EFI_NOT_FOUND
;
4966 // Register HotKey into List.
4968 if (HotKey
== NULL
) {
4970 // Create new Key, and add it into List.
4972 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4973 ASSERT (HotKey
!= NULL
);
4974 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4975 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4976 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4980 // Fill HotKey information.
4982 HotKey
->Action
= Action
;
4983 HotKey
->DefaultId
= DefaultId
;
4984 if (HotKey
->HelpString
!= NULL
) {
4985 FreePool (HotKey
->HelpString
);
4987 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4993 Register Exit handler function.
4994 When more than one handler function is registered, the latter one will override the previous one.
4995 When NULL handler is specified, the previous Exit handler will be unregistered.
4997 @param[in] Handler Pointer to handler function.
5002 RegiserExitHandler (
5003 IN EXIT_HANDLER Handler
5006 ExitHandlerFunction
= Handler
;
5011 Check whether the browser data has been modified.
5013 @retval TRUE Browser data is modified.
5014 @retval FALSE No browser data is modified.
5019 IsBrowserDataModified (
5024 FORM_BROWSER_FORMSET
*FormSet
;
5026 if (gCurrentSelection
== NULL
) {
5030 switch (gBrowserSettingScope
) {
5032 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5035 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5038 Link
= GetFirstNode (&gBrowserFormSetList
);
5039 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5040 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5041 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5044 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5054 Execute the action requested by the Action parameter.
5056 @param[in] Action Execute the request action.
5057 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5059 @retval EFI_SUCCESS Execute the request action succss.
5060 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5072 if (gCurrentSelection
== NULL
) {
5073 return EFI_NOT_READY
;
5076 Status
= EFI_SUCCESS
;
5079 // Executet the discard action.
5081 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5082 Status
= DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5083 if (EFI_ERROR (Status
)) {
5089 // Executet the difault action.
5091 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5092 Status
= ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5093 if (EFI_ERROR (Status
)) {
5099 // Executet the submit action.
5101 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5102 Status
= SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5103 if (EFI_ERROR (Status
)) {
5109 // Executet the reset action.
5111 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5112 gResetRequired
= TRUE
;
5116 // Executet the exit action.
5118 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5119 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5120 if (gBrowserSettingScope
== SystemLevel
) {
5121 if (ExitHandlerFunction
!= NULL
) {
5122 ExitHandlerFunction ();
5126 gExitRequired
= TRUE
;
5133 Create reminder to let user to choose save or discard the changed browser data.
5134 Caller can use it to actively check the changed browser data.
5136 @retval BROWSER_NO_CHANGES No browser data is changed.
5137 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5138 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5148 FORM_BROWSER_FORMSET
*FormSet
;
5149 BOOLEAN IsDataChanged
;
5150 UINT32 DataSavedAction
;
5152 DataSavedAction
= BROWSER_NO_CHANGES
;
5153 IsDataChanged
= FALSE
;
5154 Link
= GetFirstNode (&gBrowserFormSetList
);
5155 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5156 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5157 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5158 if (!ValidateFormSet(FormSet
)) {
5161 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5162 IsDataChanged
= TRUE
;
5168 // No data is changed. No save is required.
5170 if (!IsDataChanged
) {
5171 return DataSavedAction
;
5175 // If data is changed, prompt user to save or discard it.
5178 DataSavedAction
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5180 if (DataSavedAction
== BROWSER_SAVE_CHANGES
) {
5181 SubmitForm (NULL
, NULL
, SystemLevel
);
5183 } else if (DataSavedAction
== BROWSER_DISCARD_CHANGES
) {
5184 DiscardForm (NULL
, NULL
, SystemLevel
);
5189 return DataSavedAction
;