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 gFinishRetrieveCall
;
52 BOOLEAN gResetRequired
;
53 BOOLEAN gExitRequired
;
54 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
55 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
56 EXIT_HANDLER ExitHandlerFunction
= NULL
;
57 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
60 // Browser Global Strings
63 CHAR16
*mUnknownString
= L
"!";
65 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
67 extern UINT32 gBrowserStatus
;
68 extern CHAR16
*gErrorInfo
;
69 extern EFI_GUID mCurrentFormSetGuid
;
70 extern EFI_HII_HANDLE mCurrentHiiHandle
;
71 extern UINT16 mCurrentFormId
;
72 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
75 Create a menu with specified formset GUID and form ID, and add it as a child
76 of the given parent menu.
78 @param HiiHandle Hii handle related to this formset.
79 @param FormSetGuid The Formset Guid of menu to be added.
80 @param FormId The Form ID of menu to be added.
81 @param QuestionId The question id of this menu to be added.
83 @return A pointer to the newly added menu or NULL if memory is insufficient.
88 IN EFI_HII_HANDLE HiiHandle
,
89 IN EFI_GUID
*FormSetGuid
,
94 FORM_ENTRY_INFO
*MenuList
;
96 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
97 if (MenuList
== NULL
) {
101 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
103 MenuList
->HiiHandle
= HiiHandle
;
104 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
105 MenuList
->FormId
= FormId
;
106 MenuList
->QuestionId
= QuestionId
;
109 // If parent is not specified, it is the root Form of a Formset
111 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
117 Return the form id for the input hiihandle and formset.
119 @param HiiHandle HiiHandle for FormSet.
120 @param FormSetGuid The Formset GUID of the menu to search.
122 @return First form's id for this form set.
127 IN EFI_HII_HANDLE HiiHandle
,
128 IN EFI_GUID
*FormSetGuid
132 FORM_BROWSER_FORM
*Form
;
134 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
135 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
141 Search Menu with given FormSetGuid and FormId in all cached menu list.
143 @param HiiHandle HiiHandle for FormSet.
144 @param FormSetGuid The Formset GUID of the menu to search.
145 @param FormId The Form ID of menu to search.
147 @return A pointer to menu found or NULL if not found.
152 IN EFI_HII_HANDLE HiiHandle
,
153 IN EFI_GUID
*FormSetGuid
,
158 FORM_ENTRY_INFO
*MenuList
;
159 FORM_ENTRY_INFO
*RetMenu
;
160 EFI_FORM_ID FirstFormId
;
164 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
165 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
166 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
167 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
170 // If already find the menu, free the menus behind it.
172 if (RetMenu
!= NULL
) {
173 RemoveEntryList (&MenuList
->Link
);
179 // Find the same FromSet.
181 if (MenuList
->HiiHandle
== HiiHandle
) {
182 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
184 // FormSetGuid is not specified.
187 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
188 if (MenuList
->FormId
== FormId
) {
190 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
191 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
192 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
204 Find parent menu for current menu.
206 @param CurrentMenu Current Menu
208 @retval The parent menu for current menu.
212 IN FORM_ENTRY_INFO
*CurrentMenu
215 FORM_ENTRY_INFO
*ParentMenu
;
218 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
219 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
226 Free Menu list linked list.
228 @param MenuListHead One Menu list point in the menu list.
233 LIST_ENTRY
*MenuListHead
236 FORM_ENTRY_INFO
*MenuList
;
238 while (!IsListEmpty (MenuListHead
)) {
239 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
240 RemoveEntryList (&MenuList
->Link
);
247 Load all hii formset to the browser.
255 FORM_BROWSER_FORMSET
*LocalFormSet
;
256 EFI_HII_HANDLE
*HiiHandles
;
260 FORM_BROWSER_FORMSET
*OldFormset
;
261 BOOLEAN OldRetrieveValue
;
263 OldFormset
= mSystemLevelFormSet
;
264 OldRetrieveValue
= gFinishRetrieveCall
;
265 gFinishRetrieveCall
= FALSE
;
268 // Get all the Hii handles
270 HiiHandles
= HiiGetHiiHandles (NULL
);
271 ASSERT (HiiHandles
!= NULL
);
274 // Search for formset of each class type
276 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
278 // Check HiiHandles[Index] does exist in global maintain list.
280 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
285 // Initilize FormSet Setting
287 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
288 ASSERT (LocalFormSet
!= NULL
);
289 mSystemLevelFormSet
= LocalFormSet
;
291 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
292 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
293 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
294 DestroyFormSet (LocalFormSet
);
297 InitializeCurrentSetting (LocalFormSet
);
300 // Initilize Questions' Value
302 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
303 if (EFI_ERROR (Status
)) {
304 DestroyFormSet (LocalFormSet
);
310 // Free resources, and restore gOldFormSet and gClassOfVfr
312 FreePool (HiiHandles
);
314 gFinishRetrieveCall
= OldRetrieveValue
;
315 mSystemLevelFormSet
= OldFormset
;
319 This is the routine which an external caller uses to direct the browser
320 where to obtain it's information.
323 @param This The Form Browser protocol instanse.
324 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
325 display a list of the formsets for the handles specified.
326 @param HandleCount The number of Handles specified in Handle.
327 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
328 field in the EFI_IFR_FORM_SET op-code for the specified
329 forms-based package. If FormSetGuid is NULL, then this
330 function will display the first found forms package.
331 @param FormId This field specifies which EFI_IFR_FORM to render as the first
332 displayable page. If this field has a value of 0x0000, then
333 the forms browser will render the specified forms in their encoded order.
334 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
336 @param ActionRequest Points to the action recommended by the form.
338 @retval EFI_SUCCESS The function completed successfully.
339 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
340 @retval EFI_NOT_FOUND No valid forms could be found to display.
346 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
347 IN EFI_HII_HANDLE
*Handles
,
348 IN UINTN HandleCount
,
349 IN EFI_GUID
*FormSetGuid
, OPTIONAL
350 IN UINT16 FormId
, OPTIONAL
351 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
352 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
356 UI_MENU_SELECTION
*Selection
;
358 FORM_BROWSER_FORMSET
*FormSet
;
359 FORM_ENTRY_INFO
*MenuList
;
362 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
364 if (mFormDisplay
== NULL
) {
365 return EFI_UNSUPPORTED
;
369 // Save globals used by SendForm()
371 SaveBrowserContext ();
373 gFinishRetrieveCall
= FALSE
;
374 gResetRequired
= FALSE
;
375 gExitRequired
= FALSE
;
376 Status
= EFI_SUCCESS
;
378 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
380 for (Index
= 0; Index
< HandleCount
; Index
++) {
381 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
382 ASSERT (Selection
!= NULL
);
384 Selection
->Handle
= Handles
[Index
];
385 if (FormSetGuid
!= NULL
) {
386 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
387 Selection
->FormId
= FormId
;
389 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
393 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
394 ASSERT (FormSet
!= NULL
);
397 // Initialize internal data structures of FormSet
399 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
400 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
401 DestroyFormSet (FormSet
);
404 Selection
->FormSet
= FormSet
;
405 mSystemLevelFormSet
= FormSet
;
408 // Display this formset
410 gCurrentSelection
= Selection
;
412 Status
= SetupBrowser (Selection
);
414 gCurrentSelection
= NULL
;
415 mSystemLevelFormSet
= NULL
;
418 // If no data is changed, don't need to save current FormSet into the maintain list.
420 if (!IsNvUpdateRequiredForFormSet (FormSet
) && !IsStorageDataChangedForFormSet(FormSet
)) {
421 CleanBrowserStorage(FormSet
);
422 RemoveEntryList (&FormSet
->Link
);
423 DestroyFormSet (FormSet
);
426 if (EFI_ERROR (Status
)) {
429 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
431 FreePool (Selection
);
435 // Still has error info, pop up a message.
437 if (gBrowserStatus
!= BROWSER_SUCCESS
) {
438 gDisplayFormData
.BrowserStatus
= gBrowserStatus
;
439 gDisplayFormData
.ErrorString
= gErrorInfo
;
441 gBrowserStatus
= BROWSER_SUCCESS
;
444 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
447 if (ActionRequest
!= NULL
) {
448 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
449 if (gResetRequired
) {
450 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
454 mFormDisplay
->ExitDisplay();
457 // Clear the menu history data.
459 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
460 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
461 RemoveEntryList (&MenuList
->Link
);
466 // Restore globals used by SendForm()
468 RestoreBrowserContext ();
474 Get or set data to the storage.
476 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
477 @param ResultsData A string returned from an IFR browser or
478 equivalent. The results string will have no
479 routing information in them.
480 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
481 (if RetrieveData = TRUE) data from the uncommitted
482 browser state information or set (if RetrieveData
483 = FALSE) data in the uncommitted browser state
485 @param Storage The pointer to the storage.
487 @retval EFI_SUCCESS The results have been distributed or are awaiting
493 IN OUT UINTN
*ResultsDataSize
,
494 IN OUT EFI_STRING
*ResultsData
,
495 IN BOOLEAN RetrieveData
,
496 IN BROWSER_STORAGE
*Storage
507 // Generate <ConfigResp>
509 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
510 if (EFI_ERROR (Status
)) {
515 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
516 // Also need to consider add "\0" at first time.
518 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
519 BufferSize
= StrSize (StrPtr
);
523 // Copy the data if the input buffer is bigger enough.
525 if (*ResultsDataSize
>= BufferSize
) {
526 StrCpy (*ResultsData
, StrPtr
);
529 *ResultsDataSize
= BufferSize
;
530 FreePool (ConfigResp
);
533 // Prepare <ConfigResp>
535 TmpSize
= StrLen (*ResultsData
);
536 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
537 ConfigResp
= AllocateZeroPool (BufferSize
);
538 ASSERT (ConfigResp
!= NULL
);
540 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
541 StrCat (ConfigResp
, L
"&");
542 StrCat (ConfigResp
, *ResultsData
);
545 // Update Browser uncommited data
547 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
548 FreePool (ConfigResp
);
549 if (EFI_ERROR (Status
)) {
558 This routine called this service in the browser to retrieve or set certain uncommitted
559 state information that resides in the open formsets.
561 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
563 @param ResultsDataSize A pointer to the size of the buffer associated
565 @param ResultsData A string returned from an IFR browser or
566 equivalent. The results string will have no
567 routing information in them.
568 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
569 (if RetrieveData = TRUE) data from the uncommitted
570 browser state information or set (if RetrieveData
571 = FALSE) data in the uncommitted browser state
573 @param VariableGuid An optional field to indicate the target variable
575 @param VariableName An optional field to indicate the target
576 human-readable variable name.
578 @retval EFI_SUCCESS The results have been distributed or are awaiting
580 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
581 contain the results data.
587 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
588 IN OUT UINTN
*ResultsDataSize
,
589 IN OUT EFI_STRING ResultsData
,
590 IN BOOLEAN RetrieveData
,
591 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
592 IN CONST CHAR16
*VariableName OPTIONAL
597 BROWSER_STORAGE
*Storage
;
598 FORMSET_STORAGE
*FormsetStorage
;
602 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
603 return EFI_INVALID_PARAMETER
;
606 TotalSize
= *ResultsDataSize
;
609 Status
= EFI_SUCCESS
;
612 // If set browser data, pre load all hii formset to avoid set the varstore which is not
615 if (!RetrieveData
&& (gBrowserSettingScope
== SystemLevel
)) {
619 if (VariableGuid
!= NULL
) {
621 // Try to find target storage in the current formset.
623 Link
= GetFirstNode (&gBrowserStorageList
);
624 while (!IsNull (&gBrowserStorageList
, Link
)) {
625 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
626 Link
= GetNextNode (&gBrowserStorageList
, Link
);
628 // Check the current storage.
630 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
634 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
635 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
637 // Buffer storage require both GUID and Name
639 if (VariableName
== NULL
) {
640 return EFI_NOT_FOUND
;
643 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
648 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
649 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
650 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
651 return EFI_NOT_FOUND
;
654 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
659 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
660 if (EFI_ERROR (Status
)) {
665 // Different formsets may have same varstore, so here just set the flag
666 // not exit the circle.
673 return EFI_NOT_FOUND
;
677 // GUID/Name is not specified, take the first storage in FormSet
679 if (mSystemLevelFormSet
== NULL
) {
680 return EFI_NOT_READY
;
684 // Generate <ConfigResp>
686 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
687 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
688 return EFI_UNSUPPORTED
;
691 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
693 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
694 if (EFI_ERROR (Status
)) {
700 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
701 *ResultsDataSize
= TotalSize
;
710 Callback function for SimpleTextInEx protocol install events
712 @param Event the event that is signaled.
713 @param Context not used here.
718 FormDisplayCallback (
725 if (mFormDisplay
!= NULL
) {
729 Status
= gBS
->LocateProtocol (
730 &gEdkiiFormDisplayEngineProtocolGuid
,
732 (VOID
**) &mFormDisplay
737 Initialize Setup Browser driver.
739 @param ImageHandle The image handle.
740 @param SystemTable The system table.
742 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
743 @return Other value if failed to initialize the Setup Browser module.
749 IN EFI_HANDLE ImageHandle
,
750 IN EFI_SYSTEM_TABLE
*SystemTable
757 // Locate required Hii relative protocols
759 Status
= gBS
->LocateProtocol (
760 &gEfiHiiDatabaseProtocolGuid
,
762 (VOID
**) &mHiiDatabase
764 ASSERT_EFI_ERROR (Status
);
766 Status
= gBS
->LocateProtocol (
767 &gEfiHiiConfigRoutingProtocolGuid
,
769 (VOID
**) &mHiiConfigRouting
771 ASSERT_EFI_ERROR (Status
);
773 Status
= gBS
->LocateProtocol (
774 &gEfiDevicePathFromTextProtocolGuid
,
776 (VOID
**) &mPathFromText
780 // Install FormBrowser2 protocol
782 mPrivateData
.Handle
= NULL
;
783 Status
= gBS
->InstallProtocolInterface (
784 &mPrivateData
.Handle
,
785 &gEfiFormBrowser2ProtocolGuid
,
786 EFI_NATIVE_INTERFACE
,
787 &mPrivateData
.FormBrowser2
789 ASSERT_EFI_ERROR (Status
);
792 // Install FormBrowserEx2 protocol
794 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
795 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
796 mPrivateData
.Handle
= NULL
;
797 Status
= gBS
->InstallProtocolInterface (
798 &mPrivateData
.Handle
,
799 &gEdkiiFormBrowserEx2ProtocolGuid
,
800 EFI_NATIVE_INTERFACE
,
801 &mPrivateData
.FormBrowserEx2
803 ASSERT_EFI_ERROR (Status
);
805 Status
= gBS
->InstallProtocolInterface (
806 &mPrivateData
.Handle
,
807 &gEfiFormBrowserExProtocolGuid
,
808 EFI_NATIVE_INTERFACE
,
809 &mPrivateData
.FormBrowserEx
811 ASSERT_EFI_ERROR (Status
);
813 InitializeDisplayFormData ();
815 Status
= gBS
->LocateProtocol (
816 &gEdkiiFormDisplayEngineProtocolGuid
,
818 (VOID
**) &mFormDisplay
821 if (EFI_ERROR (Status
)) {
822 EfiCreateProtocolNotifyEvent (
823 &gEdkiiFormDisplayEngineProtocolGuid
,
836 Create a new string in HII Package List.
838 @param String The String to be added
839 @param HiiHandle The package list in the HII database to insert the
842 @return The output string.
848 IN EFI_HII_HANDLE HiiHandle
851 EFI_STRING_ID StringId
;
853 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
854 ASSERT (StringId
!= 0);
861 Delete a string from HII Package List.
863 @param StringId Id of the string in HII database.
864 @param HiiHandle The HII package list handle.
866 @retval EFI_SUCCESS The string was deleted successfully.
871 IN EFI_STRING_ID StringId
,
872 IN EFI_HII_HANDLE HiiHandle
877 NullChar
= CHAR_NULL
;
878 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
884 Get the string based on the StringId and HII Package List Handle.
886 @param Token The String's ID.
887 @param HiiHandle The package list in the HII database to search for
888 the specified string.
890 @return The output string.
895 IN EFI_STRING_ID Token
,
896 IN EFI_HII_HANDLE HiiHandle
901 if (HiiHandle
== NULL
) {
905 String
= HiiGetString (HiiHandle
, Token
, NULL
);
906 if (String
== NULL
) {
907 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
908 ASSERT (String
!= NULL
);
910 return (CHAR16
*) String
;
915 Allocate new memory and then copy the Unicode string Source to Destination.
917 @param Dest Location to copy string
918 @param Src String to copy
923 IN OUT CHAR16
**Dest
,
930 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
931 ASSERT (*Dest
!= NULL
);
936 Allocate new memory and concatinate Source on the end of Destination.
938 @param Dest String to added to the end of.
939 @param Src String to concatinate.
944 IN OUT CHAR16
**Dest
,
952 NewStringCpy (Dest
, Src
);
956 TmpSize
= StrSize (*Dest
);
957 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
958 ASSERT (NewString
!= NULL
);
960 StrCpy (NewString
, *Dest
);
961 StrCat (NewString
, Src
);
968 Get Value for given Name from a NameValue Storage.
970 @param Storage The NameValue Storage.
971 @param Name The Name.
972 @param Value The retured Value.
973 @param GetValueFrom Where to get source value, from EditValue or Value.
975 @retval EFI_SUCCESS Value found for given Name.
976 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
981 IN BROWSER_STORAGE
*Storage
,
983 IN OUT CHAR16
**Value
,
984 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
988 NAME_VALUE_NODE
*Node
;
990 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
991 return EFI_INVALID_PARAMETER
;
996 Link
= GetFirstNode (&Storage
->NameValueListHead
);
997 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
998 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1000 if (StrCmp (Name
, Node
->Name
) == 0) {
1001 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1002 NewStringCpy (Value
, Node
->EditValue
);
1004 NewStringCpy (Value
, Node
->Value
);
1009 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1012 return EFI_NOT_FOUND
;
1017 Set Value of given Name in a NameValue Storage.
1019 @param Storage The NameValue Storage.
1020 @param Name The Name.
1021 @param Value The Value to set.
1022 @param SetValueTo Whether update editValue or Value.
1023 @param ReturnNode The node use the input name.
1025 @retval EFI_SUCCESS Value found for given Name.
1026 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1031 IN BROWSER_STORAGE
*Storage
,
1034 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1035 OUT NAME_VALUE_NODE
**ReturnNode
1039 NAME_VALUE_NODE
*Node
;
1042 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1043 return EFI_INVALID_PARAMETER
;
1046 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1047 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1048 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1050 if (StrCmp (Name
, Node
->Name
) == 0) {
1051 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1052 Buffer
= Node
->EditValue
;
1054 Buffer
= Node
->Value
;
1056 if (Buffer
!= NULL
) {
1059 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1060 ASSERT (Buffer
!= NULL
);
1061 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1062 Node
->EditValue
= Buffer
;
1064 Node
->Value
= Buffer
;
1067 if (ReturnNode
!= NULL
) {
1074 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1077 return EFI_NOT_FOUND
;
1082 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1084 @param Storage The Storage to be conveted.
1085 @param ConfigResp The returned <ConfigResp>.
1086 @param ConfigRequest The ConfigRequest string.
1087 @param GetEditBuf Get the data from editbuffer or buffer.
1089 @retval EFI_SUCCESS Convert success.
1090 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1094 StorageToConfigResp (
1095 IN BROWSER_STORAGE
*Storage
,
1096 IN CHAR16
**ConfigResp
,
1097 IN CHAR16
*ConfigRequest
,
1098 IN BOOLEAN GetEditBuf
1102 EFI_STRING Progress
;
1104 NAME_VALUE_NODE
*Node
;
1107 Status
= EFI_SUCCESS
;
1109 switch (Storage
->Type
) {
1110 case EFI_HII_VARSTORE_BUFFER
:
1111 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1112 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1113 Status
= mHiiConfigRouting
->BlockToConfig (
1123 case EFI_HII_VARSTORE_NAME_VALUE
:
1125 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1127 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1128 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1129 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1131 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1132 NewStringCat (ConfigResp
, L
"&");
1133 NewStringCat (ConfigResp
, Node
->Name
);
1134 NewStringCat (ConfigResp
, L
"=");
1136 NewStringCat (ConfigResp
, Node
->EditValue
);
1138 NewStringCat (ConfigResp
, Node
->Value
);
1141 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1145 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1147 Status
= EFI_INVALID_PARAMETER
;
1156 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1158 @param Storage The Storage to receive the settings.
1159 @param ConfigResp The <ConfigResp> to be converted.
1161 @retval EFI_SUCCESS Convert success.
1162 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1166 ConfigRespToStorage (
1167 IN BROWSER_STORAGE
*Storage
,
1168 IN CHAR16
*ConfigResp
1172 EFI_STRING Progress
;
1178 Status
= EFI_SUCCESS
;
1180 switch (Storage
->Type
) {
1181 case EFI_HII_VARSTORE_BUFFER
:
1182 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1183 BufferSize
= Storage
->Size
;
1184 Status
= mHiiConfigRouting
->ConfigToBlock (
1187 Storage
->EditBuffer
,
1193 case EFI_HII_VARSTORE_NAME_VALUE
:
1194 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1195 if (StrPtr
== NULL
) {
1198 StrPtr
= StrStr (ConfigResp
, L
"&");
1199 while (StrPtr
!= NULL
) {
1203 StrPtr
= StrPtr
+ 1;
1205 StrPtr
= StrStr (StrPtr
, L
"=");
1206 if (StrPtr
== NULL
) {
1214 StrPtr
= StrPtr
+ 1;
1216 StrPtr
= StrStr (StrPtr
, L
"&");
1217 if (StrPtr
!= NULL
) {
1220 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1224 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1226 Status
= EFI_INVALID_PARAMETER
;
1235 Get Question's current Value.
1237 @param FormSet FormSet data structure.
1238 @param Form Form data structure.
1239 @param Question Question to be initialized.
1240 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1242 @retval EFI_SUCCESS The function completed successfully.
1247 IN FORM_BROWSER_FORMSET
*FormSet
,
1248 IN FORM_BROWSER_FORM
*Form
,
1249 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1250 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1259 BROWSER_STORAGE
*Storage
;
1260 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1261 CHAR16
*ConfigRequest
;
1269 BOOLEAN IsBufferStorage
;
1274 Status
= EFI_SUCCESS
;
1278 if (GetValueFrom
>= GetSetValueWithMax
) {
1279 return EFI_INVALID_PARAMETER
;
1283 // Question value is provided by an Expression, evaluate it
1285 if (Question
->ValueExpression
!= NULL
) {
1286 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1287 if (!EFI_ERROR (Status
)) {
1288 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1289 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1290 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1291 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1292 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1294 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1295 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1297 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1299 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1300 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1306 // Get question value by read expression.
1308 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1309 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1310 if (!EFI_ERROR (Status
) &&
1311 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1313 // Only update question value to the valid result.
1315 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1316 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1317 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1318 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1319 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1321 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1322 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1324 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1326 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1327 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1333 // Question value is provided by RTC
1335 Storage
= Question
->Storage
;
1336 QuestionValue
= &Question
->HiiValue
.Value
;
1337 if (Storage
== NULL
) {
1339 // It's a Question without storage, or RTC date/time
1341 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1343 // Date and time define the same Flags bit
1345 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1346 case QF_DATE_STORAGE_TIME
:
1347 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1350 case QF_DATE_STORAGE_WAKEUP
:
1351 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1354 case QF_DATE_STORAGE_NORMAL
:
1357 // For date/time without storage
1362 if (EFI_ERROR (Status
)) {
1366 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1367 QuestionValue
->date
.Year
= EfiTime
.Year
;
1368 QuestionValue
->date
.Month
= EfiTime
.Month
;
1369 QuestionValue
->date
.Day
= EfiTime
.Day
;
1371 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1372 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1373 QuestionValue
->time
.Second
= EfiTime
.Second
;
1381 // Question value is provided by EFI variable
1383 StorageWidth
= Question
->StorageWidth
;
1384 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1385 if (Question
->BufferValue
!= NULL
) {
1386 Dst
= Question
->BufferValue
;
1388 Dst
= (UINT8
*) QuestionValue
;
1391 Status
= gRT
->GetVariable (
1392 Question
->VariableName
,
1399 // Always return success, even this EFI variable doesn't exist
1405 // Question Value is provided by Buffer Storage or NameValue Storage
1407 if (Question
->BufferValue
!= NULL
) {
1409 // This Question is password or orderedlist
1411 Dst
= Question
->BufferValue
;
1414 // Other type of Questions
1416 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1419 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1420 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1421 IsBufferStorage
= TRUE
;
1423 IsBufferStorage
= FALSE
;
1425 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1426 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1427 if (IsBufferStorage
) {
1428 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1430 // Copy from storage Edit buffer
1432 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1435 // Copy from storage Edit buffer
1437 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1441 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1442 if (EFI_ERROR (Status
)) {
1446 ASSERT (Value
!= NULL
);
1447 LengthStr
= StrLen (Value
);
1448 Status
= EFI_SUCCESS
;
1451 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1452 // Add string tail char L'\0' into Length
1454 Length
= StorageWidth
+ sizeof (CHAR16
);
1455 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1456 Status
= EFI_BUFFER_TOO_SMALL
;
1458 StringPtr
= (CHAR16
*) Dst
;
1459 ZeroMem (TemStr
, sizeof (TemStr
));
1460 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1461 StrnCpy (TemStr
, Value
+ Index
, 4);
1462 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1465 // Add tailing L'\0' character
1467 StringPtr
[Index
/4] = L
'\0';
1470 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1471 Status
= EFI_BUFFER_TOO_SMALL
;
1473 ZeroMem (TemStr
, sizeof (TemStr
));
1474 for (Index
= 0; Index
< LengthStr
; Index
++) {
1475 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1476 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1477 if ((Index
& 1) == 0) {
1478 Dst
[Index
/2] = DigitUint8
;
1480 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1490 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1491 // <ConfigHdr> + "&" + <VariableName>
1493 if (IsBufferStorage
) {
1494 Length
= StrLen (Storage
->ConfigHdr
);
1495 Length
+= StrLen (Question
->BlockName
);
1497 Length
= StrLen (Storage
->ConfigHdr
);
1498 Length
+= StrLen (Question
->VariableName
) + 1;
1500 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1501 ASSERT (ConfigRequest
!= NULL
);
1503 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1504 if (IsBufferStorage
) {
1505 StrCat (ConfigRequest
, Question
->BlockName
);
1507 StrCat (ConfigRequest
, L
"&");
1508 StrCat (ConfigRequest
, Question
->VariableName
);
1512 // Request current settings from Configuration Driver
1514 Status
= mHiiConfigRouting
->ExtractConfig (
1520 FreePool (ConfigRequest
);
1521 if (EFI_ERROR (Status
)) {
1526 // Skip <ConfigRequest>
1528 if (IsBufferStorage
) {
1529 Value
= StrStr (Result
, L
"&VALUE");
1530 if (Value
== NULL
) {
1532 return EFI_NOT_FOUND
;
1539 Value
= Result
+ Length
;
1541 if (*Value
!= '=') {
1543 return EFI_NOT_FOUND
;
1546 // Skip '=', point to value
1551 // Suppress <AltResp> if any
1554 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1559 LengthStr
= StrLen (Value
);
1560 Status
= EFI_SUCCESS
;
1561 if (!IsBufferStorage
&& IsString
) {
1563 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1564 // Add string tail char L'\0' into Length
1566 Length
= StorageWidth
+ sizeof (CHAR16
);
1567 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1568 Status
= EFI_BUFFER_TOO_SMALL
;
1570 StringPtr
= (CHAR16
*) Dst
;
1571 ZeroMem (TemStr
, sizeof (TemStr
));
1572 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1573 StrnCpy (TemStr
, Value
+ Index
, 4);
1574 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1577 // Add tailing L'\0' character
1579 StringPtr
[Index
/4] = L
'\0';
1582 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1583 Status
= EFI_BUFFER_TOO_SMALL
;
1585 ZeroMem (TemStr
, sizeof (TemStr
));
1586 for (Index
= 0; Index
< LengthStr
; Index
++) {
1587 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1588 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1589 if ((Index
& 1) == 0) {
1590 Dst
[Index
/2] = DigitUint8
;
1592 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1598 if (EFI_ERROR (Status
)) {
1604 // Synchronize Edit Buffer
1606 if (IsBufferStorage
) {
1607 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1609 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1612 if (Result
!= NULL
) {
1622 Save Question Value to edit copy(cached) or Storage(uncached).
1624 @param FormSet FormSet data structure.
1625 @param Form Form data structure.
1626 @param Question Pointer to the Question.
1627 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1629 @retval EFI_SUCCESS The function completed successfully.
1634 IN FORM_BROWSER_FORMSET
*FormSet
,
1635 IN FORM_BROWSER_FORM
*Form
,
1636 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1637 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1647 BROWSER_STORAGE
*Storage
;
1648 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1653 BOOLEAN IsBufferStorage
;
1659 NAME_VALUE_NODE
*Node
;
1661 Status
= EFI_SUCCESS
;
1664 if (SetValueTo
>= GetSetValueWithMax
) {
1665 return EFI_INVALID_PARAMETER
;
1669 // If Question value is provided by an Expression, then it is read only
1671 if (Question
->ValueExpression
!= NULL
) {
1676 // Before set question value, evaluate its write expression.
1678 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1679 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1680 if (EFI_ERROR (Status
)) {
1686 // Question value is provided by RTC
1688 Storage
= Question
->Storage
;
1689 QuestionValue
= &Question
->HiiValue
.Value
;
1690 if (Storage
== NULL
) {
1692 // It's a Question without storage, or RTC date/time
1694 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1696 // Date and time define the same Flags bit
1698 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1699 case QF_DATE_STORAGE_TIME
:
1700 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1703 case QF_DATE_STORAGE_WAKEUP
:
1704 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1707 case QF_DATE_STORAGE_NORMAL
:
1710 // For date/time without storage
1715 if (EFI_ERROR (Status
)) {
1719 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1720 EfiTime
.Year
= QuestionValue
->date
.Year
;
1721 EfiTime
.Month
= QuestionValue
->date
.Month
;
1722 EfiTime
.Day
= QuestionValue
->date
.Day
;
1724 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1725 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1726 EfiTime
.Second
= QuestionValue
->time
.Second
;
1729 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1730 Status
= gRT
->SetTime (&EfiTime
);
1732 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1740 // Question value is provided by EFI variable
1742 StorageWidth
= Question
->StorageWidth
;
1743 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1744 if (Question
->BufferValue
!= NULL
) {
1745 Src
= Question
->BufferValue
;
1747 Src
= (UINT8
*) QuestionValue
;
1750 Status
= gRT
->SetVariable (
1751 Question
->VariableName
,
1753 Storage
->Attributes
,
1761 // Question Value is provided by Buffer Storage or NameValue Storage
1763 if (Question
->BufferValue
!= NULL
) {
1764 Src
= Question
->BufferValue
;
1766 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1769 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1770 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1771 IsBufferStorage
= TRUE
;
1773 IsBufferStorage
= FALSE
;
1775 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1777 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1778 if (IsBufferStorage
) {
1779 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1781 // Copy to storage edit buffer
1783 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1784 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1786 // Copy to storage edit buffer
1788 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1791 // Check whether question value has been changed.
1793 if (CompareMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
) != 0) {
1794 Question
->ValueChanged
= TRUE
;
1796 Question
->ValueChanged
= FALSE
;
1801 // Allocate enough string buffer.
1804 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1805 Value
= AllocateZeroPool (BufferLen
);
1806 ASSERT (Value
!= NULL
);
1808 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1810 TemName
= (CHAR16
*) Src
;
1812 for (; *TemName
!= L
'\0'; TemName
++) {
1813 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1816 BufferLen
= StorageWidth
* 2 + 1;
1817 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1818 ASSERT (Value
!= NULL
);
1820 // Convert Buffer to Hex String
1822 TemBuffer
= Src
+ StorageWidth
- 1;
1824 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1825 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1829 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1831 if (EFI_ERROR (Status
)) {
1835 // Check whether question value has been changed.
1837 if (StrCmp (Node
->Value
, Node
->EditValue
) != 0) {
1838 Question
->ValueChanged
= TRUE
;
1840 Question
->ValueChanged
= FALSE
;
1843 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1845 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1846 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1848 if (IsBufferStorage
) {
1849 Length
= StrLen (Question
->BlockName
) + 7;
1851 Length
= StrLen (Question
->VariableName
) + 2;
1853 if (!IsBufferStorage
&& IsString
) {
1854 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1856 Length
+= (StorageWidth
* 2);
1858 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1859 ASSERT (ConfigResp
!= NULL
);
1861 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1862 if (IsBufferStorage
) {
1863 StrCat (ConfigResp
, Question
->BlockName
);
1864 StrCat (ConfigResp
, L
"&VALUE=");
1866 StrCat (ConfigResp
, L
"&");
1867 StrCat (ConfigResp
, Question
->VariableName
);
1868 StrCat (ConfigResp
, L
"=");
1871 Value
= ConfigResp
+ StrLen (ConfigResp
);
1873 if (!IsBufferStorage
&& IsString
) {
1875 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1877 TemName
= (CHAR16
*) Src
;
1879 for (; *TemName
!= L
'\0'; TemName
++) {
1880 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1884 // Convert Buffer to Hex String
1886 TemBuffer
= Src
+ StorageWidth
- 1;
1888 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1889 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1894 // Convert to lower char.
1896 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1897 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1898 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1903 // Submit Question Value to Configuration Driver
1905 Status
= mHiiConfigRouting
->RouteConfig (
1910 if (EFI_ERROR (Status
)) {
1911 FreePool (ConfigResp
);
1914 FreePool (ConfigResp
);
1917 // Sync storage, from editbuffer to buffer.
1919 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1927 Perform nosubmitif check for a Form.
1929 @param FormSet FormSet data structure.
1930 @param Form Form data structure.
1931 @param Question The Question to be validated.
1932 @param Type Validation type: NoSubmit
1934 @retval EFI_SUCCESS Form validation pass.
1935 @retval other Form validation failed.
1940 IN FORM_BROWSER_FORMSET
*FormSet
,
1941 IN FORM_BROWSER_FORM
*Form
,
1942 IN FORM_BROWSER_STATEMENT
*Question
,
1948 LIST_ENTRY
*ListHead
;
1950 FORM_EXPRESSION
*Expression
;
1952 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1953 ListHead
= &Question
->NoSubmitListHead
;
1955 return EFI_UNSUPPORTED
;
1958 Link
= GetFirstNode (ListHead
);
1959 while (!IsNull (ListHead
, Link
)) {
1960 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1963 // Evaluate the expression
1965 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1966 if (EFI_ERROR (Status
)) {
1970 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1972 // Condition meet, show up error message
1974 if (Expression
->Error
!= 0) {
1975 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1976 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1977 gBrowserStatus
= BROWSER_NO_SUBMIT_IF
;
1982 return EFI_NOT_READY
;
1985 Link
= GetNextNode (ListHead
, Link
);
1993 Perform NoSubmit check for each Form in FormSet.
1995 @param FormSet FormSet data structure.
1996 @param CurrentForm Current input form data structure.
1998 @retval EFI_SUCCESS Form validation pass.
1999 @retval other Form validation failed.
2004 IN FORM_BROWSER_FORMSET
*FormSet
,
2005 IN FORM_BROWSER_FORM
*CurrentForm
2010 FORM_BROWSER_STATEMENT
*Question
;
2011 FORM_BROWSER_FORM
*Form
;
2012 LIST_ENTRY
*LinkForm
;
2014 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2015 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2016 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2017 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2019 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2023 Link
= GetFirstNode (&Form
->StatementListHead
);
2024 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2025 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2027 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2028 if (EFI_ERROR (Status
)) {
2032 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2040 Fill storage's edit copy with settings requested from Configuration Driver.
2042 @param FormSet FormSet data structure.
2043 @param Storage The storage which need to sync.
2044 @param ConfigRequest The config request string which used to sync storage.
2045 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2046 editbuffer to buffer
2047 if TRUE, copy the editbuffer to the buffer.
2048 if FALSE, copy the buffer to the editbuffer.
2050 @retval EFI_SUCCESS The function completed successfully.
2054 SynchronizeStorage (
2055 IN FORM_BROWSER_FORMSET
*FormSet
,
2056 OUT BROWSER_STORAGE
*Storage
,
2057 IN CHAR16
*ConfigRequest
,
2058 IN BOOLEAN SyncOrRestore
2062 EFI_STRING Progress
;
2066 NAME_VALUE_NODE
*Node
;
2070 Status
= EFI_SUCCESS
;
2073 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2074 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2075 BufferSize
= Storage
->Size
;
2077 if (SyncOrRestore
) {
2078 Src
= Storage
->EditBuffer
;
2079 Dst
= Storage
->Buffer
;
2081 Src
= Storage
->Buffer
;
2082 Dst
= Storage
->EditBuffer
;
2085 if (ConfigRequest
!= NULL
) {
2086 Status
= mHiiConfigRouting
->BlockToConfig(
2094 if (EFI_ERROR (Status
)) {
2098 Status
= mHiiConfigRouting
->ConfigToBlock (
2105 if (Result
!= NULL
) {
2109 CopyMem (Dst
, Src
, BufferSize
);
2111 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2112 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2113 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2114 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2116 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2117 (ConfigRequest
== NULL
)) {
2118 if (SyncOrRestore
) {
2119 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2121 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2125 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2133 When discard the question value, call the callback function with Changed type
2134 to inform the hii driver.
2136 @param FormSet FormSet data structure.
2137 @param Form Form data structure.
2141 SendDiscardInfoToDriver (
2142 IN FORM_BROWSER_FORMSET
*FormSet
,
2143 IN FORM_BROWSER_FORM
*Form
2147 FORM_BROWSER_STATEMENT
*Question
;
2148 EFI_IFR_TYPE_VALUE
*TypeValue
;
2149 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2151 Link
= GetFirstNode (&Form
->StatementListHead
);
2152 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2153 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2154 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2156 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2160 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2164 if (!Question
->ValueChanged
) {
2168 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2169 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2171 TypeValue
= &Question
->HiiValue
.Value
;
2174 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2175 FormSet
->ConfigAccess
->Callback (
2176 FormSet
->ConfigAccess
,
2177 EFI_BROWSER_ACTION_CHANGED
,
2178 Question
->QuestionId
,
2179 Question
->HiiValue
.Type
,
2187 Validate the FormSet. If the formset is not validate, remove it from the list.
2189 @param FormSet The input FormSet which need to validate.
2191 @retval TRUE The handle is validate.
2192 @retval FALSE The handle is invalidate.
2197 FORM_BROWSER_FORMSET
*FormSet
2200 EFI_HII_HANDLE
*HiiHandles
;
2204 ASSERT (FormSet
!= NULL
);
2207 // Get all the Hii handles
2209 HiiHandles
= HiiGetHiiHandles (NULL
);
2210 ASSERT (HiiHandles
!= NULL
);
2213 // Search for formset of each class type
2215 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2216 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2223 CleanBrowserStorage(FormSet
);
2224 RemoveEntryList (&FormSet
->Link
);
2225 DestroyFormSet (FormSet
);
2228 FreePool (HiiHandles
);
2233 Check whether need to enable the reset flag in form level.
2234 Also clean all ValueChanged flag in question.
2236 @param SetFlag Whether need to set the Reset Flag.
2237 @param Form Form data structure.
2243 IN FORM_BROWSER_FORM
*Form
2247 FORM_BROWSER_STATEMENT
*Question
;
2251 Link
= GetFirstNode (&Form
->StatementListHead
);
2252 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2253 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2255 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2256 gResetRequired
= TRUE
;
2259 if (Question
->ValueChanged
) {
2260 Question
->ValueChanged
= FALSE
;
2263 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2268 Check whether need to enable the reset flag.
2269 Also clean ValueChanged flag for all statements.
2271 Form level or formset level, only one.
2273 @param SetFlag Whether need to set the Reset Flag.
2274 @param FormSet FormSet data structure.
2275 @param Form Form data structure.
2279 ValueChangeResetFlagUpdate (
2281 IN FORM_BROWSER_FORMSET
*FormSet
,
2282 IN FORM_BROWSER_FORM
*Form
2285 FORM_BROWSER_FORM
*CurrentForm
;
2289 // Form != NULL means only check form level.
2292 UpdateFlagForForm(SetFlag
, Form
);
2296 Link
= GetFirstNode (&FormSet
->FormListHead
);
2297 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2298 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2299 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2301 UpdateFlagForForm(SetFlag
, CurrentForm
);
2306 Discard data based on the input setting scope (Form, FormSet or System).
2308 @param FormSet FormSet data structure.
2309 @param Form Form data structure.
2310 @param SettingScope Setting Scope for Discard action.
2312 @retval EFI_SUCCESS The function completed successfully.
2313 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2318 IN FORM_BROWSER_FORMSET
*FormSet
,
2319 IN FORM_BROWSER_FORM
*Form
,
2320 IN BROWSER_SETTING_SCOPE SettingScope
2324 FORMSET_STORAGE
*Storage
;
2325 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2326 FORM_BROWSER_FORMSET
*LocalFormSet
;
2327 FORM_BROWSER_FORMSET
*OldFormSet
;
2330 // Check the supported setting level.
2332 if (SettingScope
>= MaxLevel
) {
2333 return EFI_UNSUPPORTED
;
2336 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2338 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2339 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2340 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2341 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2343 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2348 // Skip if there is no RequestElement
2350 if (ConfigInfo
->ElementCount
== 0) {
2355 // Prepare <ConfigResp>
2357 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2360 // Call callback with Changed type to inform the driver.
2362 SendDiscardInfoToDriver (FormSet
, Form
);
2365 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2366 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2369 // Discard Buffer storage or Name/Value storage
2371 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2372 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2373 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2374 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2376 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2381 // Skip if there is no RequestElement
2383 if (Storage
->ElementCount
== 0) {
2387 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2390 Link
= GetFirstNode (&FormSet
->FormListHead
);
2391 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2392 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2393 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2396 // Call callback with Changed type to inform the driver.
2398 SendDiscardInfoToDriver (FormSet
, Form
);
2401 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2402 } else if (SettingScope
== SystemLevel
) {
2404 // System Level Discard.
2406 OldFormSet
= mSystemLevelFormSet
;
2409 // Discard changed value for each FormSet in the maintain list.
2411 Link
= GetFirstNode (&gBrowserFormSetList
);
2412 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2413 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2414 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2415 if (!ValidateFormSet(LocalFormSet
)) {
2419 mSystemLevelFormSet
= LocalFormSet
;
2421 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2422 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2424 // Remove maintain backup list after discard except for the current using FormSet.
2426 CleanBrowserStorage(LocalFormSet
);
2427 RemoveEntryList (&LocalFormSet
->Link
);
2428 DestroyFormSet (LocalFormSet
);
2432 mSystemLevelFormSet
= OldFormSet
;
2439 Submit data based on the input Setting level (Form, FormSet or System).
2441 @param FormSet FormSet data structure.
2442 @param Form Form data structure.
2443 @param SettingScope Setting Scope for Submit action.
2445 @retval EFI_SUCCESS The function completed successfully.
2446 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2451 IN FORM_BROWSER_FORMSET
*FormSet
,
2452 IN FORM_BROWSER_FORM
*Form
,
2453 IN BROWSER_SETTING_SCOPE SettingScope
2458 EFI_STRING ConfigResp
;
2459 EFI_STRING Progress
;
2460 BROWSER_STORAGE
*Storage
;
2461 FORMSET_STORAGE
*FormSetStorage
;
2462 FORM_BROWSER_FORMSET
*LocalFormSet
;
2463 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2466 // Check the supported setting level.
2468 if (SettingScope
>= MaxLevel
) {
2469 return EFI_UNSUPPORTED
;
2473 // Validate the Form by NoSubmit check
2475 Status
= EFI_SUCCESS
;
2476 if (SettingScope
== FormLevel
) {
2477 Status
= NoSubmitCheck (FormSet
, Form
);
2478 } else if (SettingScope
== FormSetLevel
) {
2479 Status
= NoSubmitCheck (FormSet
, NULL
);
2481 if (EFI_ERROR (Status
)) {
2485 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2487 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2488 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2489 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2490 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2492 Storage
= ConfigInfo
->Storage
;
2493 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2498 // Skip if there is no RequestElement
2500 if (ConfigInfo
->ElementCount
== 0) {
2505 // 1. Prepare <ConfigResp>
2507 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2508 if (EFI_ERROR (Status
)) {
2513 // 2. Set value to hii config routine protocol.
2515 Status
= mHiiConfigRouting
->RouteConfig (
2520 if (EFI_ERROR (Status
)) {
2521 FreePool (ConfigResp
);
2525 FreePool (ConfigResp
);
2527 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2529 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2533 // 4. Update the NV flag.
2535 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2536 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2538 // Submit Buffer storage or Name/Value storage
2540 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2541 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2542 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2543 Storage
= FormSetStorage
->BrowserStorage
;
2544 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2546 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2551 // Skip if there is no RequestElement
2553 if (FormSetStorage
->ElementCount
== 0) {
2558 // 1. Prepare <ConfigResp>
2560 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2561 if (EFI_ERROR (Status
)) {
2566 // 2. Send <ConfigResp> to Routine config Protocol.
2568 Status
= mHiiConfigRouting
->RouteConfig (
2573 if (EFI_ERROR (Status
)) {
2574 FreePool (ConfigResp
);
2578 FreePool (ConfigResp
);
2580 // 3. Config success, update storage shadow Buffer
2582 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2586 // 4. Update the NV flag.
2588 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2589 } else if (SettingScope
== SystemLevel
) {
2591 // System Level Save.
2595 // Save changed value for each FormSet in the maintain list.
2597 Link
= GetFirstNode (&gBrowserFormSetList
);
2598 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2599 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2600 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2601 if (!ValidateFormSet(LocalFormSet
)) {
2604 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2605 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2607 // Remove maintain backup list after save except for the current using FormSet.
2609 CleanBrowserStorage(LocalFormSet
);
2610 RemoveEntryList (&LocalFormSet
->Link
);
2611 DestroyFormSet (LocalFormSet
);
2620 Get Question default value from AltCfg string.
2622 @param FormSet The form set.
2623 @param Question The question.
2624 @param DefaultId The default Id.
2626 @retval EFI_SUCCESS Question is reset to default value.
2630 GetDefaultValueFromAltCfg (
2631 IN FORM_BROWSER_FORMSET
*FormSet
,
2632 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2636 BOOLEAN IsBufferStorage
;
2639 BROWSER_STORAGE
*Storage
;
2640 CHAR16
*ConfigRequest
;
2653 Status
= EFI_NOT_FOUND
;
2656 ConfigRequest
= NULL
;
2660 Storage
= Question
->Storage
;
2662 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2667 // Question Value is provided by Buffer Storage or NameValue Storage
2669 if (Question
->BufferValue
!= NULL
) {
2671 // This Question is password or orderedlist
2673 Dst
= Question
->BufferValue
;
2676 // Other type of Questions
2678 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2681 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2682 IsBufferStorage
= TRUE
;
2684 IsBufferStorage
= FALSE
;
2686 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2689 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2690 // <ConfigHdr> + "&" + <VariableName>
2692 if (IsBufferStorage
) {
2693 Length
= StrLen (Storage
->ConfigHdr
);
2694 Length
+= StrLen (Question
->BlockName
);
2696 Length
= StrLen (Storage
->ConfigHdr
);
2697 Length
+= StrLen (Question
->VariableName
) + 1;
2699 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2700 ASSERT (ConfigRequest
!= NULL
);
2702 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2703 if (IsBufferStorage
) {
2704 StrCat (ConfigRequest
, Question
->BlockName
);
2706 StrCat (ConfigRequest
, L
"&");
2707 StrCat (ConfigRequest
, Question
->VariableName
);
2710 Status
= mHiiConfigRouting
->ExtractConfig (
2716 if (EFI_ERROR (Status
)) {
2721 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2722 // Get the default configuration string according to the default ID.
2724 Status
= mHiiConfigRouting
->GetAltConfig (
2730 &DefaultId
, // it can be NULL to get the current setting.
2735 // The required setting can't be found. So, it is not required to be validated and set.
2737 if (EFI_ERROR (Status
)) {
2741 if (ConfigResp
== NULL
) {
2742 Status
= EFI_NOT_FOUND
;
2747 // Skip <ConfigRequest>
2749 if (IsBufferStorage
) {
2750 Value
= StrStr (ConfigResp
, L
"&VALUE");
2751 ASSERT (Value
!= NULL
);
2757 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2758 ASSERT (Value
!= NULL
);
2760 Value
= Value
+ StrLen (Question
->VariableName
);
2762 if (*Value
!= '=') {
2763 Status
= EFI_NOT_FOUND
;
2767 // Skip '=', point to value
2772 // Suppress <AltResp> if any
2775 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2780 LengthStr
= StrLen (Value
);
2781 if (!IsBufferStorage
&& IsString
) {
2782 StringPtr
= (CHAR16
*) Dst
;
2783 ZeroMem (TemStr
, sizeof (TemStr
));
2784 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2785 StrnCpy (TemStr
, Value
+ Index
, 4);
2786 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2789 // Add tailing L'\0' character
2791 StringPtr
[Index
/4] = L
'\0';
2793 ZeroMem (TemStr
, sizeof (TemStr
));
2794 for (Index
= 0; Index
< LengthStr
; Index
++) {
2795 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2796 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2797 if ((Index
& 1) == 0) {
2798 Dst
[Index
/2] = DigitUint8
;
2800 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2806 if (ConfigRequest
!= NULL
){
2807 FreePool (ConfigRequest
);
2810 if (ConfigResp
!= NULL
) {
2811 FreePool (ConfigResp
);
2814 if (Result
!= NULL
) {
2822 Get default Id value used for browser.
2824 @param DefaultId The default id value used by hii.
2826 @retval Browser used default value.
2830 GetDefaultIdForCallBack (
2834 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2835 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2836 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2837 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2838 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2839 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2840 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2841 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2842 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2843 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2844 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2845 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2854 Return data element in an Array by its Index.
2856 @param Array The data array.
2857 @param Type Type of the data in this array.
2858 @param Index Zero based index for data in this array.
2860 @retval Value The data to be returned
2872 ASSERT (Array
!= NULL
);
2876 case EFI_IFR_TYPE_NUM_SIZE_8
:
2877 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
2880 case EFI_IFR_TYPE_NUM_SIZE_16
:
2881 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
2884 case EFI_IFR_TYPE_NUM_SIZE_32
:
2885 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
2888 case EFI_IFR_TYPE_NUM_SIZE_64
:
2889 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
2901 Set value of a data element in an Array by its Index.
2903 @param Array The data array.
2904 @param Type Type of the data in this array.
2905 @param Index Zero based index for data in this array.
2906 @param Value The value to be set.
2918 ASSERT (Array
!= NULL
);
2921 case EFI_IFR_TYPE_NUM_SIZE_8
:
2922 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
2925 case EFI_IFR_TYPE_NUM_SIZE_16
:
2926 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
2929 case EFI_IFR_TYPE_NUM_SIZE_32
:
2930 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
2933 case EFI_IFR_TYPE_NUM_SIZE_64
:
2934 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
2943 Search an Option of a Question by its value.
2945 @param Question The Question
2946 @param OptionValue Value for Option to be searched.
2948 @retval Pointer Pointer to the found Option.
2949 @retval NULL Option not found.
2954 IN FORM_BROWSER_STATEMENT
*Question
,
2955 IN EFI_HII_VALUE
*OptionValue
2959 QUESTION_OPTION
*Option
;
2962 Link
= GetFirstNode (&Question
->OptionListHead
);
2963 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2964 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2966 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
2968 // Check the suppressif condition, only a valid option can be return.
2970 if ((Option
->SuppressExpression
== NULL
) ||
2971 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
2976 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2984 Reset Question to its default value.
2986 @param FormSet The form set.
2987 @param Form The form.
2988 @param Question The question.
2989 @param DefaultId The Class of the default.
2991 @retval EFI_SUCCESS Question is reset to default value.
2995 GetQuestionDefault (
2996 IN FORM_BROWSER_FORMSET
*FormSet
,
2997 IN FORM_BROWSER_FORM
*Form
,
2998 IN FORM_BROWSER_STATEMENT
*Question
,
3004 QUESTION_DEFAULT
*Default
;
3005 QUESTION_OPTION
*Option
;
3006 EFI_HII_VALUE
*HiiValue
;
3008 EFI_STRING StrValue
;
3009 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3010 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3013 Status
= EFI_NOT_FOUND
;
3017 // Statement don't have storage, skip them
3019 if (Question
->QuestionId
== 0) {
3024 // There are Five ways to specify default value for a Question:
3025 // 1, use call back function (highest priority)
3026 // 2, use ExtractConfig function
3027 // 3, use nested EFI_IFR_DEFAULT
3028 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3029 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3031 HiiValue
= &Question
->HiiValue
;
3034 // Get Question defaut value from call back function.
3036 ConfigAccess
= FormSet
->ConfigAccess
;
3037 Action
= GetDefaultIdForCallBack (DefaultId
);
3038 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3039 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3040 Status
= ConfigAccess
->Callback (
3043 Question
->QuestionId
,
3048 if (!EFI_ERROR (Status
)) {
3054 // Get default value from altcfg string.
3056 if (ConfigAccess
!= NULL
) {
3057 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3058 if (!EFI_ERROR (Status
)) {
3064 // EFI_IFR_DEFAULT has highest priority
3066 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3067 Link
= GetFirstNode (&Question
->DefaultListHead
);
3068 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3069 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3071 if (Default
->DefaultId
== DefaultId
) {
3072 if (Default
->ValueExpression
!= NULL
) {
3074 // Default is provided by an Expression, evaluate it
3076 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3077 if (EFI_ERROR (Status
)) {
3081 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3082 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3083 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3084 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3085 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3087 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3088 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3090 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3092 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3093 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3096 // Default value is embedded in EFI_IFR_DEFAULT
3098 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3101 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3102 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3103 if (StrValue
== NULL
) {
3104 return EFI_NOT_FOUND
;
3106 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3107 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3109 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3116 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3121 // EFI_ONE_OF_OPTION
3123 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3124 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3126 // OneOfOption could only provide Standard and Manufacturing default
3128 Link
= GetFirstNode (&Question
->OptionListHead
);
3129 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3130 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3131 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3133 if ((Option
->SuppressExpression
!= NULL
) &&
3134 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3138 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3139 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3141 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3150 // EFI_IFR_CHECKBOX - lowest priority
3152 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3153 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3155 // Checkbox could only provide Standard and Manufacturing default
3157 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3158 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3160 HiiValue
->Value
.b
= TRUE
;
3162 HiiValue
->Value
.b
= FALSE
;
3170 // For Questions without default
3172 Status
= EFI_NOT_FOUND
;
3173 switch (Question
->Operand
) {
3174 case EFI_IFR_NUMERIC_OP
:
3176 // Take minimum value as numeric default value
3178 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3179 HiiValue
->Value
.u64
= Question
->Minimum
;
3180 Status
= EFI_SUCCESS
;
3184 case EFI_IFR_ONE_OF_OP
:
3186 // Take first oneof option as oneof's default value
3188 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3189 Link
= GetFirstNode (&Question
->OptionListHead
);
3190 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3191 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3192 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3194 if ((Option
->SuppressExpression
!= NULL
) &&
3195 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3199 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3200 Status
= EFI_SUCCESS
;
3206 case EFI_IFR_ORDERED_LIST_OP
:
3208 // Take option sequence in IFR as ordered list's default value
3211 Link
= GetFirstNode (&Question
->OptionListHead
);
3212 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3213 Status
= EFI_SUCCESS
;
3214 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3215 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3217 if ((Option
->SuppressExpression
!= NULL
) &&
3218 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3222 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3225 if (Index
>= Question
->MaxContainers
) {
3240 Reset Questions to their initial value or default value in a Form, Formset or System.
3242 GetDefaultValueScope parameter decides which questions will reset
3243 to its default value.
3245 @param FormSet FormSet data structure.
3246 @param Form Form data structure.
3247 @param DefaultId The Class of the default.
3248 @param SettingScope Setting Scope for Default action.
3249 @param GetDefaultValueScope Get default value scope.
3250 @param Storage Get default value only for this storage.
3251 @param RetrieveValueFirst Whether call the retrieve call back to
3252 get the initial value before get default
3255 @retval EFI_SUCCESS The function completed successfully.
3256 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3261 IN FORM_BROWSER_FORMSET
*FormSet
,
3262 IN FORM_BROWSER_FORM
*Form
,
3263 IN UINT16 DefaultId
,
3264 IN BROWSER_SETTING_SCOPE SettingScope
,
3265 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3266 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3267 IN BOOLEAN RetrieveValueFirst
3271 LIST_ENTRY
*FormLink
;
3273 FORM_BROWSER_STATEMENT
*Question
;
3274 FORM_BROWSER_FORMSET
*LocalFormSet
;
3275 FORM_BROWSER_FORMSET
*OldFormSet
;
3277 Status
= EFI_SUCCESS
;
3280 // Check the supported setting level.
3282 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3283 return EFI_UNSUPPORTED
;
3286 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3287 return EFI_UNSUPPORTED
;
3290 if (SettingScope
== FormLevel
) {
3292 // Extract Form default
3294 Link
= GetFirstNode (&Form
->StatementListHead
);
3295 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3296 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3297 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3300 // If get default value only for this storage, check the storage first.
3302 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3307 // If get default value only for no storage question, just skip the question which has storage.
3309 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3314 // If Question is disabled, don't reset it to default
3316 if (Question
->Expression
!= NULL
) {
3317 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3322 if (RetrieveValueFirst
) {
3324 // Call the Retrieve call back to get the initial question value.
3326 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3330 // If not request to get the initial value or get initial value fail, then get default value.
3332 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3333 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3334 if (EFI_ERROR (Status
)) {
3340 // Synchronize Buffer storage's Edit buffer
3342 if ((Question
->Storage
!= NULL
) &&
3343 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3344 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3347 } else if (SettingScope
== FormSetLevel
) {
3348 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3349 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3350 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3351 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3352 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3354 } else if (SettingScope
== SystemLevel
) {
3356 // Preload all Hii formset.
3358 LoadAllHiiFormset();
3360 OldFormSet
= mSystemLevelFormSet
;
3363 // Set Default Value for each FormSet in the maintain list.
3365 Link
= GetFirstNode (&gBrowserFormSetList
);
3366 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3367 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3368 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3369 if (!ValidateFormSet(LocalFormSet
)) {
3373 mSystemLevelFormSet
= LocalFormSet
;
3375 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3378 mSystemLevelFormSet
= OldFormSet
;
3386 Validate whether this question's value has changed.
3388 @param FormSet FormSet data structure.
3389 @param Form Form data structure.
3390 @param Question Question to be initialized.
3391 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3393 @retval TRUE Question's value has changed.
3394 @retval FALSE Question's value has not changed
3398 IsQuestionValueChanged (
3399 IN FORM_BROWSER_FORMSET
*FormSet
,
3400 IN FORM_BROWSER_FORM
*Form
,
3401 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3402 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3405 EFI_HII_VALUE BackUpValue
;
3406 CHAR8
*BackUpBuffer
;
3408 BOOLEAN ValueChanged
;
3412 // For quetion without storage, always mark it as data not changed.
3414 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3418 BackUpBuffer
= NULL
;
3419 ValueChanged
= FALSE
;
3421 switch (Question
->Operand
) {
3422 case EFI_IFR_ORDERED_LIST_OP
:
3423 BufferWidth
= Question
->StorageWidth
;
3424 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3425 ASSERT (BackUpBuffer
!= NULL
);
3428 case EFI_IFR_STRING_OP
:
3429 case EFI_IFR_PASSWORD_OP
:
3430 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3431 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3432 ASSERT (BackUpBuffer
!= NULL
);
3439 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3441 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3442 ASSERT_EFI_ERROR(Status
);
3444 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3445 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3446 ValueChanged
= TRUE
;
3449 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3450 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3452 if (BackUpBuffer
!= NULL
) {
3453 FreePool (BackUpBuffer
);
3456 return ValueChanged
;
3460 Initialize Question's Edit copy from Storage.
3462 @param Selection Selection contains the information about
3463 the Selection, form and formset to be displayed.
3464 Selection action may be updated in retrieve callback.
3465 If Selection is NULL, only initialize Question value.
3466 @param FormSet FormSet data structure.
3467 @param Form Form data structure.
3469 @retval EFI_SUCCESS The function completed successfully.
3474 IN OUT UI_MENU_SELECTION
*Selection
,
3475 IN FORM_BROWSER_FORMSET
*FormSet
,
3476 IN FORM_BROWSER_FORM
*Form
3481 FORM_BROWSER_STATEMENT
*Question
;
3485 Link
= GetFirstNode (&Form
->StatementListHead
);
3486 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3487 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3490 // Initialize local copy of Value for each Question
3492 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3493 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3495 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3497 if (EFI_ERROR (Status
)) {
3501 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3502 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3506 // Call the Retrieve call back function for all questions.
3508 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3509 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
3510 !gFinishRetrieveCall
) {
3512 // Check QuestionValue does exist.
3514 StorageWidth
= Question
->StorageWidth
;
3515 if (Question
->BufferValue
!= NULL
) {
3516 BufferValue
= Question
->BufferValue
;
3518 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3522 // For efivarstore storage, initial question value first.
3524 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3525 Status
= gRT
->GetVariable (
3526 Question
->VariableName
,
3527 &Question
->Storage
->Guid
,
3534 Status
= ProcessCallBackFunction(Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3538 // Update Question Value changed flag.
3540 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
3542 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3549 Initialize Question's Edit copy from Storage for the whole Formset.
3551 @param Selection Selection contains the information about
3552 the Selection, form and formset to be displayed.
3553 Selection action may be updated in retrieve callback.
3554 If Selection is NULL, only initialize Question value.
3555 @param FormSet FormSet data structure.
3557 @retval EFI_SUCCESS The function completed successfully.
3562 IN OUT UI_MENU_SELECTION
*Selection
,
3563 IN FORM_BROWSER_FORMSET
*FormSet
3568 FORM_BROWSER_FORM
*Form
;
3570 Link
= GetFirstNode (&FormSet
->FormListHead
);
3571 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3572 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3575 // Initialize local copy of Value for each Form
3577 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3578 if (EFI_ERROR (Status
)) {
3582 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3586 // Finished question initialization.
3588 FormSet
->QuestionInited
= TRUE
;
3594 Remove the Request element from the Config Request.
3596 @param Storage Pointer to the browser storage.
3597 @param RequestElement The pointer to the Request element.
3602 IN OUT BROWSER_STORAGE
*Storage
,
3603 IN CHAR16
*RequestElement
3609 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3611 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3613 if (NewStr
== NULL
) {
3618 // Remove this element from this ConfigRequest.
3621 NewStr
+= StrLen (RequestElement
);
3622 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3624 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3628 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3630 @param Storage Pointer to the browser storage.
3631 @param ConfigRequest The pointer to the Request element.
3635 RemoveConfigRequest (
3636 BROWSER_STORAGE
*Storage
,
3637 CHAR16
*ConfigRequest
3640 CHAR16
*RequestElement
;
3641 CHAR16
*NextRequestElement
;
3645 // No request element in it, just return.
3647 if (ConfigRequest
== NULL
) {
3651 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3653 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3658 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3660 SearchKey
= L
"&OFFSET";
3664 // Find SearchKey storage
3666 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3667 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3668 ASSERT (RequestElement
!= NULL
);
3669 RequestElement
= StrStr (RequestElement
, SearchKey
);
3671 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3674 while (RequestElement
!= NULL
) {
3676 // +1 to avoid find header itself.
3678 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3681 // The last Request element in configRequest string.
3683 if (NextRequestElement
!= NULL
) {
3685 // Replace "&" with '\0'.
3687 *NextRequestElement
= L
'\0';
3690 RemoveElement (Storage
, RequestElement
);
3692 if (NextRequestElement
!= NULL
) {
3694 // Restore '&' with '\0' for later used.
3696 *NextRequestElement
= L
'&';
3699 RequestElement
= NextRequestElement
;
3703 // If no request element remain, just remove the ConfigRequest string.
3705 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3706 FreePool (Storage
->ConfigRequest
);
3707 Storage
->ConfigRequest
= NULL
;
3708 Storage
->SpareStrLen
= 0;
3713 Base on the current formset info, clean the ConfigRequest string in browser storage.
3715 @param FormSet Pointer of the FormSet
3719 CleanBrowserStorage (
3720 IN OUT FORM_BROWSER_FORMSET
*FormSet
3724 FORMSET_STORAGE
*Storage
;
3725 CHAR16
*ConfigRequest
;
3727 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3728 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3729 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3730 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3732 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3733 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3737 ConfigRequest
= FormSet
->QuestionInited
? Storage
->ConfigRequest
: Storage
->ConfigElements
;
3738 RemoveConfigRequest (Storage
->BrowserStorage
, ConfigRequest
);
3739 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3740 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3741 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
3742 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
3744 Storage
->BrowserStorage
->Initialized
= FALSE
;
3750 Check whether current element in the ConfigReqeust string.
3752 @param BrowserStorage Storage which includes ConfigReqeust.
3753 @param RequestElement New element need to check.
3755 @retval TRUE The Element is in the ConfigReqeust string.
3756 @retval FALSE The Element not in the configReqeust String.
3761 BROWSER_STORAGE
*BrowserStorage
,
3762 CHAR16
*RequestElement
3765 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3769 Append the Request element to the Config Request.
3771 @param ConfigRequest Current ConfigRequest info.
3772 @param SpareStrLen Current remain free buffer for config reqeust.
3773 @param RequestElement New Request element.
3777 AppendConfigRequest (
3778 IN OUT CHAR16
**ConfigRequest
,
3779 IN OUT UINTN
*SpareStrLen
,
3780 IN CHAR16
*RequestElement
3787 StrLength
= StrLen (RequestElement
);
3790 // Append <RequestElement> to <ConfigRequest>
3792 if (StrLength
> *SpareStrLen
) {
3794 // Old String buffer is not sufficient for RequestElement, allocate a new one
3796 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3797 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3798 ASSERT (NewStr
!= NULL
);
3800 if (*ConfigRequest
!= NULL
) {
3801 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3802 FreePool (*ConfigRequest
);
3804 *ConfigRequest
= NewStr
;
3805 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3808 StrCat (*ConfigRequest
, RequestElement
);
3809 *SpareStrLen
-= StrLength
;
3813 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3815 @param Storage Form set Storage.
3817 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3818 @retval FALSE All elements covered by current used elements.
3822 ConfigRequestAdjust (
3823 IN FORMSET_STORAGE
*Storage
3826 CHAR16
*RequestElement
;
3827 CHAR16
*NextRequestElement
;
3837 if (Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3838 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3839 if (Storage
->ConfigElements
!= NULL
) {
3840 FreePool (Storage
->ConfigElements
);
3842 Storage
->ConfigElements
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3846 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3848 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3853 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3855 SearchKey
= L
"&OFFSET";
3859 // Prepare the config header.
3861 RetBuf
= AllocateCopyPool(StrSize (Storage
->BrowserStorage
->ConfigHdr
), Storage
->BrowserStorage
->ConfigHdr
);
3862 ASSERT (RetBuf
!= NULL
);
3865 // Find SearchKey storage
3867 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3868 RequestElement
= StrStr (Storage
->ConfigRequest
, L
"PATH");
3869 ASSERT (RequestElement
!= NULL
);
3870 RequestElement
= StrStr (RequestElement
, SearchKey
);
3872 RequestElement
= StrStr (Storage
->ConfigRequest
, SearchKey
);
3875 while (RequestElement
!= NULL
) {
3877 // +1 to avoid find header itself.
3879 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3882 // The last Request element in configRequest string.
3884 if (NextRequestElement
!= NULL
) {
3886 // Replace "&" with '\0'.
3888 *NextRequestElement
= L
'\0';
3891 if (!ElementValidation (Storage
->BrowserStorage
, RequestElement
)) {
3893 // Add this element to the Storage->BrowserStorage->AllRequestElement.
3895 AppendConfigRequest(&Storage
->BrowserStorage
->ConfigRequest
, &Storage
->BrowserStorage
->SpareStrLen
, RequestElement
);
3896 AppendConfigRequest (&RetBuf
, &SpareBufLen
, RequestElement
);
3900 if (NextRequestElement
!= NULL
) {
3902 // Restore '&' with '\0' for later used.
3904 *NextRequestElement
= L
'&';
3907 RequestElement
= NextRequestElement
;
3911 if (Storage
->ConfigElements
!= NULL
) {
3912 FreePool (Storage
->ConfigElements
);
3914 Storage
->ConfigElements
= RetBuf
;
3924 Base on ConfigRequest info to get default value for current formset.
3926 ConfigRequest info include the info about which questions in current formset need to
3927 get default value. This function only get these questions default value.
3929 @param FormSet FormSet data structure.
3930 @param Storage Storage need to update value.
3931 @param ConfigRequest The config request string.
3935 GetDefaultForFormset (
3936 IN FORM_BROWSER_FORMSET
*FormSet
,
3937 IN BROWSER_STORAGE
*Storage
,
3938 IN CHAR16
*ConfigRequest
3943 LIST_ENTRY BackUpList
;
3944 NAME_VALUE_NODE
*Node
;
3946 LIST_ENTRY
*NodeLink
;
3947 NAME_VALUE_NODE
*TmpNode
;
3949 EFI_STRING Progress
;
3953 InitializeListHead(&BackUpList
);
3956 // Back update the edit buffer.
3958 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3959 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3960 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
3961 ASSERT (BackUpBuf
!= NULL
);
3962 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3963 Link
= GetFirstNode (&Storage
->NameValueListHead
);
3964 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
3965 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3966 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
3969 // Only back Node belong to this formset.
3971 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
3975 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
3976 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
3977 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
3979 InsertTailList(&BackUpList
, &TmpNode
->Link
);
3984 // Get default value.
3986 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3989 // Update the question value based on the input ConfigRequest.
3991 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3992 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3993 ASSERT (BackUpBuf
!= NULL
);
3994 BufferSize
= Storage
->Size
;
3995 Status
= mHiiConfigRouting
->BlockToConfig(
3998 Storage
->EditBuffer
,
4003 ASSERT_EFI_ERROR (Status
);
4005 Status
= mHiiConfigRouting
->ConfigToBlock (
4012 ASSERT_EFI_ERROR (Status
);
4014 if (Result
!= NULL
) {
4018 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4019 FreePool (BackUpBuf
);
4020 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4022 // Update question value, only element in ConfigReqeust will be update.
4024 Link
= GetFirstNode (&BackUpList
);
4025 while (!IsNull (&BackUpList
, Link
)) {
4026 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4027 Link
= GetNextNode (&BackUpList
, Link
);
4029 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4033 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4034 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4035 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4036 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4038 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4042 FreePool (TmpNode
->EditValue
);
4043 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4045 RemoveEntryList (&Node
->Link
);
4046 FreePool (Node
->EditValue
);
4047 FreePool (Node
->Name
);
4053 // Restore the Name/Value node.
4055 Link
= GetFirstNode (&BackUpList
);
4056 while (!IsNull (&BackUpList
, Link
)) {
4057 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4058 Link
= GetNextNode (&BackUpList
, Link
);
4063 RemoveEntryList (&Node
->Link
);
4064 FreePool (Node
->EditValue
);
4065 FreePool (Node
->Name
);
4072 Fill storage's edit copy with settings requested from Configuration Driver.
4074 @param FormSet FormSet data structure.
4075 @param Storage Buffer Storage.
4080 IN FORM_BROWSER_FORMSET
*FormSet
,
4081 IN FORMSET_STORAGE
*Storage
4085 EFI_STRING Progress
;
4089 switch (Storage
->BrowserStorage
->Type
) {
4090 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4093 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4094 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4095 ConfigRequestAdjust(Storage
);
4100 case EFI_HII_VARSTORE_BUFFER
:
4101 case EFI_HII_VARSTORE_NAME_VALUE
:
4103 // Skip if there is no RequestElement or data has initilized.
4105 if (Storage
->ElementCount
== 0 || Storage
->BrowserStorage
->Initialized
) {
4108 Storage
->BrowserStorage
->Initialized
= TRUE
;
4116 // Request current settings from Configuration Driver
4118 Status
= mHiiConfigRouting
->ExtractConfig (
4120 Storage
->ConfigRequest
,
4126 // If get value fail, extract default from IFR binary
4128 if (EFI_ERROR (Status
)) {
4129 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4132 // Convert Result from <ConfigAltResp> to <ConfigResp>
4134 StrPtr
= StrStr (Result
, L
"&GUID=");
4135 if (StrPtr
!= NULL
) {
4139 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4143 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4146 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4148 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4152 Get current setting of Questions.
4154 @param FormSet FormSet data structure.
4158 InitializeCurrentSetting (
4159 IN OUT FORM_BROWSER_FORMSET
*FormSet
4163 FORMSET_STORAGE
*Storage
;
4164 FORM_BROWSER_FORMSET
*OldFormSet
;
4167 // Try to find pre FormSet in the maintain backup list.
4168 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4170 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4171 if (OldFormSet
!= NULL
) {
4172 RemoveEntryList (&OldFormSet
->Link
);
4173 DestroyFormSet (OldFormSet
);
4175 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4178 // Extract default from IFR binary for no storage questions.
4180 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4183 // Request current settings from Configuration Driver
4185 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4186 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4187 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4189 LoadStorage (FormSet
, Storage
);
4191 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4197 Fetch the Ifr binary data of a FormSet.
4199 @param Handle PackageList Handle
4200 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4201 specified (NULL or zero GUID), take the first
4202 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4203 found in package list.
4204 On output, GUID of the formset found(if not NULL).
4205 @param BinaryLength The length of the FormSet IFR binary.
4206 @param BinaryData The buffer designed to receive the FormSet.
4208 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4209 BufferLength was updated.
4210 @retval EFI_INVALID_PARAMETER The handle is unknown.
4211 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4212 be found with the requested FormId.
4217 IN EFI_HII_HANDLE Handle
,
4218 IN OUT EFI_GUID
*FormSetGuid
,
4219 OUT UINTN
*BinaryLength
,
4220 OUT UINT8
**BinaryData
4224 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4230 UINT32 PackageListLength
;
4231 EFI_HII_PACKAGE_HEADER PackageHeader
;
4233 UINT8 NumberOfClassGuid
;
4234 BOOLEAN ClassGuidMatch
;
4235 EFI_GUID
*ClassGuid
;
4236 EFI_GUID
*ComparingGuid
;
4240 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4243 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4245 if (FormSetGuid
== NULL
) {
4246 ComparingGuid
= &gZeroGuid
;
4248 ComparingGuid
= FormSetGuid
;
4252 // Get HII PackageList
4255 HiiPackageList
= NULL
;
4256 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4257 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4258 HiiPackageList
= AllocatePool (BufferSize
);
4259 ASSERT (HiiPackageList
!= NULL
);
4261 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4263 if (EFI_ERROR (Status
)) {
4266 ASSERT (HiiPackageList
!= NULL
);
4269 // Get Form package from this HII package List
4271 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4273 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4275 ClassGuidMatch
= FALSE
;
4276 while (Offset
< PackageListLength
) {
4277 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4278 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4280 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4282 // Search FormSet in this Form Package
4284 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4285 while (Offset2
< PackageHeader
.Length
) {
4286 OpCodeData
= Package
+ Offset2
;
4288 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4290 // Try to compare against formset GUID
4292 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4293 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4297 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4299 // Try to compare against formset class GUID
4301 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4302 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4303 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4304 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4305 ClassGuidMatch
= TRUE
;
4309 if (ClassGuidMatch
) {
4312 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4313 ClassGuidMatch
= TRUE
;
4318 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4321 if (Offset2
< PackageHeader
.Length
) {
4323 // Target formset found
4329 Offset
+= PackageHeader
.Length
;
4332 if (Offset
>= PackageListLength
) {
4334 // Form package not found in this Package List
4336 FreePool (HiiPackageList
);
4337 return EFI_NOT_FOUND
;
4340 if (FormSetGuid
!= NULL
) {
4342 // Return the FormSet GUID
4344 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4348 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4349 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4350 // of the Form Package.
4352 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4353 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4355 FreePool (HiiPackageList
);
4357 if (*BinaryData
== NULL
) {
4358 return EFI_OUT_OF_RESOURCES
;
4366 Initialize the internal data structure of a FormSet.
4368 @param Handle PackageList Handle
4369 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4370 specified (NULL or zero GUID), take the first
4371 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4372 found in package list.
4373 On output, GUID of the formset found(if not NULL).
4374 @param FormSet FormSet data structure.
4376 @retval EFI_SUCCESS The function completed successfully.
4377 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4382 IN EFI_HII_HANDLE Handle
,
4383 IN OUT EFI_GUID
*FormSetGuid
,
4384 OUT FORM_BROWSER_FORMSET
*FormSet
4388 EFI_HANDLE DriverHandle
;
4390 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4391 if (EFI_ERROR (Status
)) {
4395 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4396 FormSet
->HiiHandle
= Handle
;
4397 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4398 FormSet
->QuestionInited
= FALSE
;
4401 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4403 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4404 if (EFI_ERROR (Status
)) {
4407 FormSet
->DriverHandle
= DriverHandle
;
4408 Status
= gBS
->HandleProtocol (
4410 &gEfiHiiConfigAccessProtocolGuid
,
4411 (VOID
**) &FormSet
->ConfigAccess
4413 if (EFI_ERROR (Status
)) {
4415 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4416 // list, then there will be no configuration action required
4418 FormSet
->ConfigAccess
= NULL
;
4422 // Parse the IFR binary OpCodes
4424 Status
= ParseOpCodes (FormSet
);
4431 Save globals used by previous call to SendForm(). SendForm() may be called from
4432 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4433 So, save globals of previous call to SendForm() and restore them upon exit.
4437 SaveBrowserContext (
4441 BROWSER_CONTEXT
*Context
;
4442 FORM_ENTRY_INFO
*MenuList
;
4444 gBrowserContextCount
++;
4445 if (gBrowserContextCount
== 1) {
4447 // This is not reentry of SendForm(), no context to save
4452 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4453 ASSERT (Context
!= NULL
);
4455 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4458 // Save FormBrowser context
4460 Context
->Selection
= gCurrentSelection
;
4461 Context
->ResetRequired
= gResetRequired
;
4462 Context
->ExitRequired
= gExitRequired
;
4463 Context
->HiiHandle
= mCurrentHiiHandle
;
4464 Context
->FormId
= mCurrentFormId
;
4465 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4468 // Save the menu history data.
4470 InitializeListHead(&Context
->FormHistoryList
);
4471 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4472 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4473 RemoveEntryList (&MenuList
->Link
);
4475 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4479 // Insert to FormBrowser context list
4481 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4486 Restore globals used by previous call to SendForm().
4490 RestoreBrowserContext (
4495 BROWSER_CONTEXT
*Context
;
4496 FORM_ENTRY_INFO
*MenuList
;
4498 ASSERT (gBrowserContextCount
!= 0);
4499 gBrowserContextCount
--;
4500 if (gBrowserContextCount
== 0) {
4502 // This is not reentry of SendForm(), no context to restore
4507 ASSERT (!IsListEmpty (&gBrowserContextList
));
4509 Link
= GetFirstNode (&gBrowserContextList
);
4510 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4513 // Restore FormBrowser context
4515 gCurrentSelection
= Context
->Selection
;
4516 gResetRequired
= Context
->ResetRequired
;
4517 gExitRequired
= Context
->ExitRequired
;
4518 mCurrentHiiHandle
= Context
->HiiHandle
;
4519 mCurrentFormId
= Context
->FormId
;
4520 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4523 // Restore the menu history data.
4525 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4526 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4527 RemoveEntryList (&MenuList
->Link
);
4529 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4533 // Remove from FormBrowser context list
4535 RemoveEntryList (&Context
->Link
);
4536 gBS
->FreePool (Context
);
4540 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4542 @param Handle The Hii Handle.
4544 @return the found FormSet context. If no found, NULL will return.
4547 FORM_BROWSER_FORMSET
*
4548 GetFormSetFromHiiHandle (
4549 EFI_HII_HANDLE Handle
4553 FORM_BROWSER_FORMSET
*FormSet
;
4555 Link
= GetFirstNode (&gBrowserFormSetList
);
4556 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4557 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4558 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4559 if (!ValidateFormSet(FormSet
)) {
4562 if (FormSet
->HiiHandle
== Handle
) {
4571 Check whether the input HII handle is the FormSet that is being used.
4573 @param Handle The Hii Handle.
4575 @retval TRUE HII handle is being used.
4576 @retval FALSE HII handle is not being used.
4580 IsHiiHandleInBrowserContext (
4581 EFI_HII_HANDLE Handle
4585 BROWSER_CONTEXT
*Context
;
4588 // HiiHandle is Current FormSet.
4590 if (mCurrentHiiHandle
== Handle
) {
4595 // Check whether HiiHandle is in BrowserContext.
4597 Link
= GetFirstNode (&gBrowserContextList
);
4598 while (!IsNull (&gBrowserContextList
, Link
)) {
4599 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4600 if (Context
->HiiHandle
== Handle
) {
4602 // HiiHandle is in BrowserContext
4606 Link
= GetNextNode (&gBrowserContextList
, Link
);
4613 Perform Password check.
4614 Passwork may be encrypted by driver that requires the specific check.
4616 @param Form Form where Password Statement is in.
4617 @param Statement Password statement
4618 @param PasswordString Password string to be checked. It may be NULL.
4619 NULL means to restore password.
4620 "" string can be used to checked whether old password does exist.
4622 @return Status Status of Password check.
4627 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4628 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4629 IN EFI_STRING PasswordString OPTIONAL
4633 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4634 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4635 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4636 FORM_BROWSER_STATEMENT
*Question
;
4638 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4639 Question
= GetBrowserStatement(Statement
);
4640 ASSERT (Question
!= NULL
);
4642 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4643 if (ConfigAccess
== NULL
) {
4644 return EFI_UNSUPPORTED
;
4647 if (PasswordString
== NULL
) {
4651 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4654 return EFI_NOT_READY
;
4659 // Prepare password string in HII database
4661 if (PasswordString
!= NULL
) {
4662 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4664 IfrTypeValue
.string
= 0;
4668 // Send password to Configuration Driver for validation
4670 Status
= ConfigAccess
->Callback (
4672 EFI_BROWSER_ACTION_CHANGING
,
4673 Question
->QuestionId
,
4674 Question
->HiiValue
.Type
,
4680 // Remove password string from HII database
4682 if (PasswordString
!= NULL
) {
4683 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4690 Find the registered HotKey based on KeyData.
4692 @param[in] KeyData A pointer to a buffer that describes the keystroke
4693 information for the hot key.
4695 @return The registered HotKey context. If no found, NULL will return.
4698 GetHotKeyFromRegisterList (
4699 IN EFI_INPUT_KEY
*KeyData
4703 BROWSER_HOT_KEY
*HotKey
;
4705 Link
= GetFirstNode (&gBrowserHotKeyList
);
4706 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4707 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4708 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4711 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4718 Configure what scope the hot key will impact.
4719 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4720 If no scope is set, the default scope will be FormSet level.
4721 After all registered hot keys are removed, previous Scope can reset to another level.
4723 @param[in] Scope Scope level to be set.
4725 @retval EFI_SUCCESS Scope is set correctly.
4726 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4727 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4733 IN BROWSER_SETTING_SCOPE Scope
4736 if (Scope
>= MaxLevel
) {
4737 return EFI_INVALID_PARAMETER
;
4741 // When no hot key registered in system or on the first setting,
4742 // Scope can be set.
4744 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4745 gBrowserSettingScope
= Scope
;
4746 mBrowserScopeFirstSet
= FALSE
;
4747 } else if (Scope
!= gBrowserSettingScope
) {
4748 return EFI_UNSUPPORTED
;
4755 Register the hot key with its browser action, or unregistered the hot key.
4756 Only support hot key that is not printable character (control key, function key, etc.).
4757 If the action value is zero, the hot key will be unregistered if it has been registered.
4758 If the same hot key has been registered, the new action and help string will override the previous ones.
4760 @param[in] KeyData A pointer to a buffer that describes the keystroke
4761 information for the hot key. Its type is EFI_INPUT_KEY to
4762 be supported by all ConsoleIn devices.
4763 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4764 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4765 @param[in] HelpString Help string that describes the hot key information.
4766 Its value may be NULL for the unregistered hot key.
4768 @retval EFI_SUCCESS Hot key is registered or unregistered.
4769 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4770 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4771 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4776 IN EFI_INPUT_KEY
*KeyData
,
4778 IN UINT16 DefaultId
,
4779 IN EFI_STRING HelpString OPTIONAL
4782 BROWSER_HOT_KEY
*HotKey
;
4785 // Check input parameters.
4787 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4788 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4789 return EFI_INVALID_PARAMETER
;
4793 // Check whether the input KeyData is in BrowserHotKeyList.
4795 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4798 // Unregister HotKey
4800 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4801 if (HotKey
!= NULL
) {
4803 // The registered HotKey is found.
4804 // Remove it from List, and free its resource.
4806 RemoveEntryList (&HotKey
->Link
);
4807 FreePool (HotKey
->KeyData
);
4808 FreePool (HotKey
->HelpString
);
4812 // The registered HotKey is not found.
4814 return EFI_NOT_FOUND
;
4819 // Register HotKey into List.
4821 if (HotKey
== NULL
) {
4823 // Create new Key, and add it into List.
4825 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4826 ASSERT (HotKey
!= NULL
);
4827 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4828 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4829 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4833 // Fill HotKey information.
4835 HotKey
->Action
= Action
;
4836 HotKey
->DefaultId
= DefaultId
;
4837 if (HotKey
->HelpString
!= NULL
) {
4838 FreePool (HotKey
->HelpString
);
4840 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4846 Register Exit handler function.
4847 When more than one handler function is registered, the latter one will override the previous one.
4848 When NULL handler is specified, the previous Exit handler will be unregistered.
4850 @param[in] Handler Pointer to handler function.
4855 RegiserExitHandler (
4856 IN EXIT_HANDLER Handler
4859 ExitHandlerFunction
= Handler
;
4864 Check whether the browser data has been modified.
4866 @retval TRUE Browser data is modified.
4867 @retval FALSE No browser data is modified.
4872 IsBrowserDataModified (
4877 FORM_BROWSER_FORMSET
*FormSet
;
4879 if (gCurrentSelection
== NULL
) {
4883 switch (gBrowserSettingScope
) {
4885 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
4888 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
4891 Link
= GetFirstNode (&gBrowserFormSetList
);
4892 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4893 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4894 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
4897 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4907 Execute the action requested by the Action parameter.
4909 @param[in] Action Execute the request action.
4910 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
4912 @retval EFI_SUCCESS Execute the request action succss.
4913 @retval EFI_INVALID_PARAMETER The input action value is invalid.
4925 if (gCurrentSelection
== NULL
) {
4926 return EFI_NOT_READY
;
4929 Status
= EFI_SUCCESS
;
4932 // Executet the discard action.
4934 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
4935 Status
= DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
4936 if (EFI_ERROR (Status
)) {
4942 // Executet the difault action.
4944 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
4945 Status
= ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
4946 if (EFI_ERROR (Status
)) {
4952 // Executet the submit action.
4954 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
4955 Status
= SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
4956 if (EFI_ERROR (Status
)) {
4962 // Executet the reset action.
4964 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
4965 gResetRequired
= TRUE
;
4969 // Executet the exit action.
4971 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
4972 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
4973 if (gBrowserSettingScope
== SystemLevel
) {
4974 if (ExitHandlerFunction
!= NULL
) {
4975 ExitHandlerFunction ();
4979 gExitRequired
= TRUE
;
4986 Create reminder to let user to choose save or discard the changed browser data.
4987 Caller can use it to actively check the changed browser data.
4989 @retval BROWSER_NO_CHANGES No browser data is changed.
4990 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4991 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5001 FORM_BROWSER_FORMSET
*FormSet
;
5002 BOOLEAN IsDataChanged
;
5003 UINT32 DataSavedAction
;
5005 DataSavedAction
= BROWSER_NO_CHANGES
;
5006 IsDataChanged
= FALSE
;
5007 Link
= GetFirstNode (&gBrowserFormSetList
);
5008 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5009 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5010 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5011 if (!ValidateFormSet(FormSet
)) {
5014 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5015 IsDataChanged
= TRUE
;
5021 // No data is changed. No save is required.
5023 if (!IsDataChanged
) {
5024 return DataSavedAction
;
5028 // If data is changed, prompt user to save or discard it.
5031 DataSavedAction
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5033 if (DataSavedAction
== BROWSER_SAVE_CHANGES
) {
5034 SubmitForm (NULL
, NULL
, SystemLevel
);
5036 } else if (DataSavedAction
== BROWSER_DISCARD_CHANGES
) {
5037 DiscardForm (NULL
, NULL
, SystemLevel
);
5042 return DataSavedAction
;