2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2020 - 2022 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
13 SETUP_DRIVER_SIGNATURE
,
26 BROWSER_EXTENSION2_VERSION_1_1
,
30 IsBrowserDataModified
,
38 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
39 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
40 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
41 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
43 UINTN gBrowserContextCount
= 0;
44 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
45 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
46 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
47 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
48 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
50 BOOLEAN mSystemSubmit
= FALSE
;
51 BOOLEAN gResetRequiredFormLevel
;
52 BOOLEAN gResetRequiredSystemLevel
= FALSE
;
53 BOOLEAN gExitRequired
;
54 BOOLEAN gFlagReconnect
;
55 BOOLEAN gCallbackReconnect
;
56 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
57 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
58 EXIT_HANDLER ExitHandlerFunction
= NULL
;
59 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
62 // Browser Global Strings
65 CHAR16
*mUnknownString
= L
"!";
67 extern EFI_GUID mCurrentFormSetGuid
;
68 extern EFI_HII_HANDLE mCurrentHiiHandle
;
69 extern UINT16 mCurrentFormId
;
70 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
73 Create a menu with specified formset GUID and form ID, and add it as a child
74 of the given parent menu.
76 @param HiiHandle Hii handle related to this formset.
77 @param FormSetGuid The Formset Guid of menu to be added.
78 @param FormId The Form ID of menu to be added.
79 @param QuestionId The question id of this menu to be added.
81 @return A pointer to the newly added menu or NULL if memory is insufficient.
86 IN EFI_HII_HANDLE HiiHandle
,
87 IN EFI_GUID
*FormSetGuid
,
92 FORM_ENTRY_INFO
*MenuList
;
94 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
95 if (MenuList
== NULL
) {
99 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
101 MenuList
->HiiHandle
= HiiHandle
;
102 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
103 MenuList
->FormId
= FormId
;
104 MenuList
->QuestionId
= QuestionId
;
107 // If parent is not specified, it is the root Form of a Formset
109 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
115 Return the form id for the input hiihandle and formset.
117 @param HiiHandle HiiHandle for FormSet.
118 @param FormSetGuid The Formset GUID of the menu to search.
120 @return First form's id for this form set.
125 IN EFI_HII_HANDLE HiiHandle
,
126 IN EFI_GUID
*FormSetGuid
130 FORM_BROWSER_FORM
*Form
;
132 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
133 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
139 Search Menu with given FormSetGuid and FormId in all cached menu list.
141 @param HiiHandle HiiHandle for FormSet.
142 @param FormSetGuid The Formset GUID of the menu to search.
143 @param FormId The Form ID of menu to search.
145 @return A pointer to menu found or NULL if not found.
150 IN EFI_HII_HANDLE HiiHandle
,
151 IN EFI_GUID
*FormSetGuid
,
156 FORM_ENTRY_INFO
*MenuList
;
157 FORM_ENTRY_INFO
*RetMenu
;
158 EFI_FORM_ID FirstFormId
;
162 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
163 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
164 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
165 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
168 // If already find the menu, free the menus behind it.
170 if (RetMenu
!= NULL
) {
171 RemoveEntryList (&MenuList
->Link
);
177 // Find the same FromSet.
179 if (MenuList
->HiiHandle
== HiiHandle
) {
180 if (IsZeroGuid (&MenuList
->FormSetGuid
)) {
182 // FormSetGuid is not specified.
185 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
186 if (MenuList
->FormId
== FormId
) {
188 } else if ((FormId
== 0) || (MenuList
->FormId
== 0)) {
189 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
190 if (((FormId
== 0) && (FirstFormId
== MenuList
->FormId
)) || ((MenuList
->FormId
== 0) && (FirstFormId
== FormId
))) {
202 Find parent menu for current menu.
204 @param CurrentMenu Current Menu
205 @param SettingLevel Whether find parent menu in Form Level or Formset level.
206 In form level, just find the parent menu;
207 In formset level, find the parent menu which has different
210 @retval The parent menu for current menu.
214 IN FORM_ENTRY_INFO
*CurrentMenu
,
215 IN BROWSER_SETTING_SCOPE SettingLevel
218 FORM_ENTRY_INFO
*ParentMenu
;
221 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
223 if (CurrentMenu
== NULL
) {
228 Link
= &CurrentMenu
->Link
;
230 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
231 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
233 if (SettingLevel
== FormLevel
) {
235 // For FormLevel, just find the parent menu, return.
240 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
242 // For SystemLevel, must find the menu which has different formset.
247 Link
= Link
->BackLink
;
251 // Not find the parent menu, just return NULL.
253 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
261 Free Menu list linked list.
263 @param MenuListHead One Menu list point in the menu list.
268 LIST_ENTRY
*MenuListHead
271 FORM_ENTRY_INFO
*MenuList
;
273 while (!IsListEmpty (MenuListHead
)) {
274 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
275 RemoveEntryList (&MenuList
->Link
);
282 Copy current Menu list to the new menu list.
284 @param NewMenuListHead New create Menu list.
285 @param CurrentMenuListHead Current Menu list.
290 OUT LIST_ENTRY
*NewMenuListHead
,
291 IN LIST_ENTRY
*CurrentMenuListHead
295 FORM_ENTRY_INFO
*MenuList
;
296 FORM_ENTRY_INFO
*NewMenuEntry
;
299 // If new menu list not empty, free it first.
301 UiFreeMenuList (NewMenuListHead
);
303 Link
= GetFirstNode (CurrentMenuListHead
);
304 while (!IsNull (CurrentMenuListHead
, Link
)) {
305 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
306 Link
= GetNextNode (CurrentMenuListHead
, Link
);
308 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
309 ASSERT (NewMenuEntry
!= NULL
);
310 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
311 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
312 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
313 NewMenuEntry
->FormId
= MenuList
->FormId
;
314 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
316 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
321 Load all hii formset to the browser.
329 FORM_BROWSER_FORMSET
*LocalFormSet
;
330 EFI_HII_HANDLE
*HiiHandles
;
334 FORM_BROWSER_FORMSET
*OldFormset
;
336 OldFormset
= mSystemLevelFormSet
;
339 // Get all the Hii handles
341 HiiHandles
= HiiGetHiiHandles (NULL
);
342 ASSERT (HiiHandles
!= NULL
);
345 // Search for formset of each class type
347 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
349 // Check HiiHandles[Index] does exist in global maintain list.
351 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
356 // Initilize FormSet Setting
358 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
359 ASSERT (LocalFormSet
!= NULL
);
360 mSystemLevelFormSet
= LocalFormSet
;
362 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
363 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
364 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
365 DestroyFormSet (LocalFormSet
);
369 InitializeCurrentSetting (LocalFormSet
);
372 // Initilize Questions' Value
374 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
375 if (EFI_ERROR (Status
)) {
376 DestroyFormSet (LocalFormSet
);
382 // Free resources, and restore gOldFormSet and gClassOfVfr
384 FreePool (HiiHandles
);
386 mSystemLevelFormSet
= OldFormset
;
390 Pop up the error info.
392 @param BrowserStatus The input browser status.
393 @param HiiHandle The Hiihandle for this opcode.
394 @param OpCode The opcode use to get the erro info and timeout value.
395 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
400 IN UINT32 BrowserStatus
,
401 IN EFI_HII_HANDLE HiiHandle
,
402 IN EFI_IFR_OP_HEADER
*OpCode OPTIONAL
,
403 IN CHAR16
*ErrorString
406 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
407 USER_INPUT UserInputData
;
411 if (OpCode
!= NULL
) {
412 Statement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
413 ASSERT (Statement
!= NULL
);
414 Statement
->OpCode
= OpCode
;
415 gDisplayFormData
.HighLightedStatement
= Statement
;
419 // Used to compatible with old display engine.
420 // New display engine not use this field.
422 gDisplayFormData
.ErrorString
= ErrorString
;
423 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
425 if (HiiHandle
!= NULL
) {
426 gDisplayFormData
.HiiHandle
= HiiHandle
;
429 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
431 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
432 gDisplayFormData
.ErrorString
= NULL
;
434 if (OpCode
!= NULL
) {
435 FreePool (Statement
);
438 return UserInputData
.Action
;
442 This is the routine which an external caller uses to direct the browser
443 where to obtain it's information.
446 @param This The Form Browser protocol instanse.
447 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
448 display a list of the formsets for the handles specified.
449 @param HandleCount The number of Handles specified in Handle.
450 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
451 field in the EFI_IFR_FORM_SET op-code for the specified
452 forms-based package. If FormSetGuid is NULL, then this
453 function will display the first found forms package.
454 @param FormId This field specifies which EFI_IFR_FORM to render as the first
455 displayable page. If this field has a value of 0x0000, then
456 the forms browser will render the specified forms in their encoded order.
457 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
459 @param ActionRequest Points to the action recommended by the form.
461 @retval EFI_SUCCESS The function completed successfully.
462 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
463 @retval EFI_NOT_FOUND No valid forms could be found to display.
469 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
470 IN EFI_HII_HANDLE
*Handles
,
471 IN UINTN HandleCount
,
472 IN EFI_GUID
*FormSetGuid OPTIONAL
,
473 IN UINT16 FormId OPTIONAL
,
474 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions OPTIONAL
,
475 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
479 UI_MENU_SELECTION
*Selection
;
481 FORM_BROWSER_FORMSET
*FormSet
;
482 FORM_ENTRY_INFO
*MenuList
;
486 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
488 if (mFormDisplay
== NULL
) {
489 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
490 return EFI_UNSUPPORTED
;
494 // Save globals used by SendForm()
496 SaveBrowserContext ();
498 gFlagReconnect
= FALSE
;
499 gResetRequiredFormLevel
= FALSE
;
500 gExitRequired
= FALSE
;
501 gCallbackReconnect
= FALSE
;
502 Status
= EFI_SUCCESS
;
504 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*)ScreenDimensions
;
506 for (Index
= 0; Index
< HandleCount
; Index
++) {
507 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
508 ASSERT (Selection
!= NULL
);
510 Selection
->Handle
= Handles
[Index
];
511 if (FormSetGuid
!= NULL
) {
512 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
513 Selection
->FormId
= FormId
;
515 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
519 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
520 ASSERT (FormSet
!= NULL
);
523 // Validate the HiiHandle
524 // if validate failed, find the first validate parent HiiHandle.
526 if (!ValidateHiiHandle (Selection
->Handle
)) {
527 FindNextMenu (Selection
, FormSetLevel
);
531 // Initialize internal data structures of FormSet
533 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
534 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
535 DestroyFormSet (FormSet
);
539 Selection
->FormSet
= FormSet
;
540 mSystemLevelFormSet
= FormSet
;
543 // Display this formset
545 gCurrentSelection
= Selection
;
547 Status
= SetupBrowser (Selection
);
549 gCurrentSelection
= NULL
;
550 mSystemLevelFormSet
= NULL
;
553 // Check incoming formset whether is same with previous. If yes, that means action is not exiting of formset so do not reconnect controller.
555 if ((gFlagReconnect
|| gCallbackReconnect
) && !CompareGuid (&FormSet
->Guid
, &Selection
->FormSetGuid
)) {
556 RetVal
= ReconnectController (FormSet
->DriverHandle
);
558 PopupErrorMessage (BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
561 gFlagReconnect
= FALSE
;
562 gCallbackReconnect
= FALSE
;
566 // If no data is changed, don't need to save current FormSet into the maintain list.
568 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
569 CleanBrowserStorage (FormSet
);
570 RemoveEntryList (&FormSet
->Link
);
571 DestroyFormSet (FormSet
);
574 if (EFI_ERROR (Status
)) {
577 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
579 FreePool (Selection
);
582 if (ActionRequest
!= NULL
) {
583 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
584 if (gResetRequiredFormLevel
) {
585 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
589 mFormDisplay
->ExitDisplay ();
592 // Clear the menu history data.
594 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
595 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
596 RemoveEntryList (&MenuList
->Link
);
601 // Restore globals used by SendForm()
603 RestoreBrowserContext ();
609 Get or set data to the storage.
611 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
612 @param ResultsData A string returned from an IFR browser or
613 equivalent. The results string will have no
614 routing information in them.
615 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
616 (if RetrieveData = TRUE) data from the uncommitted
617 browser state information or set (if RetrieveData
618 = FALSE) data in the uncommitted browser state
620 @param Storage The pointer to the storage.
622 @retval EFI_SUCCESS The results have been distributed or are awaiting
628 IN OUT UINTN
*ResultsDataSize
,
629 IN OUT EFI_STRING
*ResultsData
,
630 IN BOOLEAN RetrieveData
,
631 IN BROWSER_STORAGE
*Storage
640 FORMSET_STORAGE
*BrowserStorage
;
644 // Generate <ConfigResp>
646 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
647 if (EFI_ERROR (Status
)) {
652 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
653 // Also need to consider add "\0" at first time.
655 StrPtr
= StrStr (ConfigResp
, L
"PATH");
656 ASSERT (StrPtr
!= NULL
);
657 StrPtr
= StrStr (StrPtr
, L
"&");
659 BufferSize
= StrSize (StrPtr
);
662 // Copy the data if the input buffer is bigger enough.
664 if (*ResultsDataSize
>= BufferSize
) {
665 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
668 *ResultsDataSize
= BufferSize
;
669 FreePool (ConfigResp
);
672 // Prepare <ConfigResp>
674 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
675 ASSERT (BrowserStorage
!= NULL
);
676 TmpSize
= StrLen (*ResultsData
);
677 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
678 MaxLen
= BufferSize
/ sizeof (CHAR16
);
679 ConfigResp
= AllocateZeroPool (BufferSize
);
680 ASSERT (ConfigResp
!= NULL
);
682 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
683 StrCatS (ConfigResp
, MaxLen
, L
"&");
684 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
687 // Update Browser uncommited data
689 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
690 FreePool (ConfigResp
);
691 if (EFI_ERROR (Status
)) {
700 This routine called this service in the browser to retrieve or set certain uncommitted
701 state information that resides in the open formsets.
703 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
705 @param ResultsDataSize A pointer to the size of the buffer associated
707 @param ResultsData A string returned from an IFR browser or
708 equivalent. The results string will have no
709 routing information in them.
710 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
711 (if RetrieveData = TRUE) data from the uncommitted
712 browser state information or set (if RetrieveData
713 = FALSE) data in the uncommitted browser state
715 @param VariableGuid An optional field to indicate the target variable
717 @param VariableName An optional field to indicate the target
718 human-readable variable name.
720 @retval EFI_SUCCESS The results have been distributed or are awaiting
722 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
723 contain the results data.
729 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
730 IN OUT UINTN
*ResultsDataSize
,
731 IN OUT EFI_STRING ResultsData
,
732 IN BOOLEAN RetrieveData
,
733 IN CONST EFI_GUID
*VariableGuid OPTIONAL
,
734 IN CONST CHAR16
*VariableName OPTIONAL
739 BROWSER_STORAGE
*Storage
;
740 FORMSET_STORAGE
*FormsetStorage
;
744 if ((ResultsDataSize
== NULL
) || (ResultsData
== NULL
)) {
745 return EFI_INVALID_PARAMETER
;
748 TotalSize
= *ResultsDataSize
;
751 Status
= EFI_SUCCESS
;
753 if (VariableGuid
!= NULL
) {
755 // Try to find target storage in the current formset.
757 Link
= GetFirstNode (&gBrowserStorageList
);
758 while (!IsNull (&gBrowserStorageList
, Link
)) {
759 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
760 Link
= GetNextNode (&gBrowserStorageList
, Link
);
762 // Check the current storage.
764 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*)VariableGuid
)) {
768 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
769 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
772 // Buffer storage require both GUID and Name
774 if (VariableName
== NULL
) {
775 return EFI_NOT_FOUND
;
778 if (StrCmp (Storage
->Name
, (CHAR16
*)VariableName
) != 0) {
783 if ((Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) ||
784 (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
))
786 if ((mSystemLevelFormSet
== NULL
) || (mSystemLevelFormSet
->HiiHandle
== NULL
)) {
787 return EFI_NOT_FOUND
;
790 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
795 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
796 if (EFI_ERROR (Status
)) {
800 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
801 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
805 // Different formsets may have same varstore, so here just set the flag
806 // not exit the circle.
813 return EFI_NOT_FOUND
;
817 // GUID/Name is not specified, take the first storage in FormSet
819 if (mSystemLevelFormSet
== NULL
) {
820 return EFI_NOT_READY
;
824 // Generate <ConfigResp>
826 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
827 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
828 return EFI_UNSUPPORTED
;
831 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
833 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
834 if (EFI_ERROR (Status
)) {
840 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
841 *ResultsDataSize
= TotalSize
;
848 Callback function for SimpleTextInEx protocol install events
850 @param Event the event that is signaled.
851 @param Context not used here.
856 FormDisplayCallback (
861 if (mFormDisplay
!= NULL
) {
865 gBS
->LocateProtocol (
866 &gEdkiiFormDisplayEngineProtocolGuid
,
868 (VOID
**)&mFormDisplay
873 Initialize Setup Browser driver.
875 @param ImageHandle The image handle.
876 @param SystemTable The system table.
878 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
879 @return Other value if failed to initialize the Setup Browser module.
885 IN EFI_HANDLE ImageHandle
,
886 IN EFI_SYSTEM_TABLE
*SystemTable
893 // Locate required Hii relative protocols
895 Status
= gBS
->LocateProtocol (
896 &gEfiHiiDatabaseProtocolGuid
,
898 (VOID
**)&mHiiDatabase
900 ASSERT_EFI_ERROR (Status
);
902 Status
= gBS
->LocateProtocol (
903 &gEfiHiiConfigRoutingProtocolGuid
,
905 (VOID
**)&mHiiConfigRouting
907 ASSERT_EFI_ERROR (Status
);
909 Status
= gBS
->LocateProtocol (
910 &gEfiDevicePathFromTextProtocolGuid
,
912 (VOID
**)&mPathFromText
916 // Install FormBrowser2 protocol
918 mPrivateData
.Handle
= NULL
;
919 Status
= gBS
->InstallProtocolInterface (
920 &mPrivateData
.Handle
,
921 &gEfiFormBrowser2ProtocolGuid
,
922 EFI_NATIVE_INTERFACE
,
923 &mPrivateData
.FormBrowser2
925 ASSERT_EFI_ERROR (Status
);
928 // Install FormBrowserEx2 protocol
930 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
931 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
932 mPrivateData
.Handle
= NULL
;
933 Status
= gBS
->InstallProtocolInterface (
934 &mPrivateData
.Handle
,
935 &gEdkiiFormBrowserEx2ProtocolGuid
,
936 EFI_NATIVE_INTERFACE
,
937 &mPrivateData
.FormBrowserEx2
939 ASSERT_EFI_ERROR (Status
);
941 Status
= gBS
->InstallProtocolInterface (
942 &mPrivateData
.Handle
,
943 &gEdkiiFormBrowserExProtocolGuid
,
944 EFI_NATIVE_INTERFACE
,
945 &mPrivateData
.FormBrowserEx
947 ASSERT_EFI_ERROR (Status
);
949 InitializeDisplayFormData ();
951 Status
= gBS
->LocateProtocol (
952 &gEdkiiFormDisplayEngineProtocolGuid
,
954 (VOID
**)&mFormDisplay
957 if (EFI_ERROR (Status
)) {
958 EfiCreateProtocolNotifyEvent (
959 &gEdkiiFormDisplayEngineProtocolGuid
,
971 Create a new string in HII Package List.
973 @param String The String to be added
974 @param HiiHandle The package list in the HII database to insert the
977 @return The output string.
983 IN EFI_HII_HANDLE HiiHandle
986 EFI_STRING_ID StringId
;
988 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
989 ASSERT (StringId
!= 0);
995 Delete a string from HII Package List.
997 @param StringId Id of the string in HII database.
998 @param HiiHandle The HII package list handle.
1000 @retval EFI_SUCCESS The string was deleted successfully.
1005 IN EFI_STRING_ID StringId
,
1006 IN EFI_HII_HANDLE HiiHandle
1011 NullChar
= CHAR_NULL
;
1012 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1017 Get the string based on the StringId and HII Package List Handle.
1019 @param Token The String's ID.
1020 @param HiiHandle The package list in the HII database to search for
1021 the specified string.
1023 @return The output string.
1028 IN EFI_STRING_ID Token
,
1029 IN EFI_HII_HANDLE HiiHandle
1034 if (HiiHandle
== NULL
) {
1038 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1039 if (String
== NULL
) {
1040 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1041 ASSERT (String
!= NULL
);
1044 return (CHAR16
*)String
;
1048 Allocate new memory and then copy the Unicode string Source to Destination.
1050 @param Dest Location to copy string
1051 @param Src String to copy
1056 IN OUT CHAR16
**Dest
,
1060 if (*Dest
!= NULL
) {
1064 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1065 ASSERT (*Dest
!= NULL
);
1069 Allocate new memory and concatinate Source on the end of Destination.
1071 @param Dest String to added to the end of.
1072 @param Src String to concatinate.
1077 IN OUT CHAR16
**Dest
,
1084 if (*Dest
== NULL
) {
1085 NewStringCpy (Dest
, Src
);
1089 MaxLen
= (StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1090 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1091 ASSERT (NewString
!= NULL
);
1093 StrCpyS (NewString
, MaxLen
, *Dest
);
1094 StrCatS (NewString
, MaxLen
, Src
);
1101 Get Value for given Name from a NameValue Storage.
1103 @param Storage The NameValue Storage.
1104 @param Name The Name.
1105 @param Value The retured Value.
1106 @param GetValueFrom Where to get source value, from EditValue or Value.
1108 @retval EFI_SUCCESS Value found for given Name.
1109 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1114 IN BROWSER_STORAGE
*Storage
,
1116 IN OUT CHAR16
**Value
,
1117 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1121 NAME_VALUE_NODE
*Node
;
1123 if ((GetValueFrom
!= GetSetValueWithEditBuffer
) && (GetValueFrom
!= GetSetValueWithBuffer
)) {
1124 return EFI_INVALID_PARAMETER
;
1129 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1130 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1131 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1133 if (StrCmp (Name
, Node
->Name
) == 0) {
1134 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1135 NewStringCpy (Value
, Node
->EditValue
);
1137 NewStringCpy (Value
, Node
->Value
);
1143 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1146 return EFI_NOT_FOUND
;
1150 Set Value of given Name in a NameValue Storage.
1152 @param Storage The NameValue Storage.
1153 @param Name The Name.
1154 @param Value The Value to set.
1155 @param SetValueTo Whether update editValue or Value.
1156 @param ReturnNode The node use the input name.
1158 @retval EFI_SUCCESS Value found for given Name.
1159 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1164 IN BROWSER_STORAGE
*Storage
,
1167 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1168 OUT NAME_VALUE_NODE
**ReturnNode
1172 NAME_VALUE_NODE
*Node
;
1175 if ((SetValueTo
!= GetSetValueWithEditBuffer
) && (SetValueTo
!= GetSetValueWithBuffer
)) {
1176 return EFI_INVALID_PARAMETER
;
1179 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1180 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1181 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1183 if (StrCmp (Name
, Node
->Name
) == 0) {
1184 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1185 Buffer
= Node
->EditValue
;
1187 Buffer
= Node
->Value
;
1190 if (Buffer
!= NULL
) {
1194 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1195 ASSERT (Buffer
!= NULL
);
1196 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1197 Node
->EditValue
= Buffer
;
1199 Node
->Value
= Buffer
;
1202 if (ReturnNode
!= NULL
) {
1209 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1212 return EFI_NOT_FOUND
;
1216 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1218 @param Storage The Storage to be conveted.
1219 @param ConfigResp The returned <ConfigResp>.
1220 @param ConfigRequest The ConfigRequest string.
1221 @param GetEditBuf Get the data from editbuffer or buffer.
1223 @retval EFI_SUCCESS Convert success.
1224 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1228 StorageToConfigResp (
1229 IN BROWSER_STORAGE
*Storage
,
1230 IN CHAR16
**ConfigResp
,
1231 IN CHAR16
*ConfigRequest
,
1232 IN BOOLEAN GetEditBuf
1236 EFI_STRING Progress
;
1238 NAME_VALUE_NODE
*Node
;
1240 FORMSET_STORAGE
*FormsetStorage
;
1242 Status
= EFI_SUCCESS
;
1244 switch (Storage
->Type
) {
1245 case EFI_HII_VARSTORE_BUFFER
:
1246 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1247 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1248 Status
= mHiiConfigRouting
->BlockToConfig (
1258 case EFI_HII_VARSTORE_NAME_VALUE
:
1260 FormsetStorage
= GetFstStgFromBrsStg (Storage
);
1261 ASSERT (FormsetStorage
!= NULL
);
1262 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1264 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1265 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1266 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1268 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1269 NewStringCat (ConfigResp
, L
"&");
1270 NewStringCat (ConfigResp
, Node
->Name
);
1271 NewStringCat (ConfigResp
, L
"=");
1273 NewStringCat (ConfigResp
, Node
->EditValue
);
1275 NewStringCat (ConfigResp
, Node
->Value
);
1279 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1284 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1286 Status
= EFI_INVALID_PARAMETER
;
1294 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1296 @param Storage The Storage to receive the settings.
1297 @param ConfigResp The <ConfigResp> to be converted.
1299 @retval EFI_SUCCESS Convert success.
1300 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1304 ConfigRespToStorage (
1305 IN BROWSER_STORAGE
*Storage
,
1306 IN CHAR16
*ConfigResp
1310 EFI_STRING Progress
;
1316 Status
= EFI_SUCCESS
;
1318 switch (Storage
->Type
) {
1319 case EFI_HII_VARSTORE_BUFFER
:
1320 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1321 BufferSize
= Storage
->Size
;
1322 Status
= mHiiConfigRouting
->ConfigToBlock (
1325 Storage
->EditBuffer
,
1331 case EFI_HII_VARSTORE_NAME_VALUE
:
1332 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1333 if (StrPtr
== NULL
) {
1337 StrPtr
= StrStr (ConfigResp
, L
"&");
1338 while (StrPtr
!= NULL
) {
1342 StrPtr
= StrPtr
+ 1;
1344 StrPtr
= StrStr (StrPtr
, L
"=");
1345 if (StrPtr
== NULL
) {
1354 StrPtr
= StrPtr
+ 1;
1356 StrPtr
= StrStr (StrPtr
, L
"&");
1357 if (StrPtr
!= NULL
) {
1361 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1366 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1368 Status
= EFI_INVALID_PARAMETER
;
1376 Get bit field value from the buffer and then set the value for the question.
1377 Note: Data type UINT32 can cover all the bit field value.
1379 @param Question The question refer to bit field.
1380 @param Buffer Point to the buffer which the question value get from.
1384 GetBitsQuestionValue (
1385 IN FORM_BROWSER_STATEMENT
*Question
,
1394 StartBit
= Question
->BitVarOffset
% 8;
1395 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1397 CopyMem ((UINT8
*)&BufferValue
, Buffer
, Question
->StorageWidth
);
1399 RetVal
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1402 // Set question value.
1403 // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
1404 // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.
1406 CopyMem ((UINT8
*)&Question
->HiiValue
.Value
, (UINT8
*)&RetVal
, Question
->StorageWidth
);
1410 Set bit field value to the buffer.
1411 Note: Data type UINT32 can cover all the bit field value.
1413 @param Question The question refer to bit field.
1414 @param Buffer Point to the buffer which the question value set to.
1415 @param Value The bit field value need to set.
1419 SetBitsQuestionValue (
1420 IN FORM_BROWSER_STATEMENT
*Question
,
1421 IN OUT UINT8
*Buffer
,
1430 StartBit
= Question
->BitVarOffset
% 8;
1431 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1433 CopyMem ((UINT8
*)&Operand
, Buffer
, Question
->StorageWidth
);
1435 RetVal
= BitFieldWrite32 (Operand
, StartBit
, EndBit
, Value
);
1437 CopyMem (Buffer
, (UINT8
*)&RetVal
, Question
->StorageWidth
);
1441 Convert the buffer value to HiiValue.
1443 @param Question The question.
1444 @param Value Unicode buffer save the question value.
1446 @retval Status whether convert the value success.
1451 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1456 BOOLEAN IsBufferStorage
;
1471 IsString
= (BOOLEAN
)((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1472 if ((Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
1473 (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
1475 IsBufferStorage
= TRUE
;
1477 IsBufferStorage
= FALSE
;
1481 // Question Value is provided by Buffer Storage or NameValue Storage
1483 if (Question
->BufferValue
!= NULL
) {
1485 // This Question is password or orderedlist
1487 Dst
= Question
->BufferValue
;
1490 // Other type of Questions
1492 if (Question
->QuestionReferToBitField
) {
1493 Buffer
= (UINT8
*)AllocateZeroPool (Question
->StorageWidth
);
1494 if (Buffer
== NULL
) {
1495 return EFI_OUT_OF_RESOURCES
;
1500 Dst
= (UINT8
*)&Question
->HiiValue
.Value
;
1505 // Temp cut at the end of this section, end with '\0' or '&'.
1508 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1512 TempChar
= *StringPtr
;
1515 LengthStr
= StrLen (Value
);
1518 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1519 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1520 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1521 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1523 if (LengthStr
> (UINTN
)Question
->StorageWidth
* 2) {
1524 Length
= (UINTN
)Question
->StorageWidth
* 2;
1529 Status
= EFI_SUCCESS
;
1530 if (!IsBufferStorage
&& IsString
) {
1532 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1533 // Add string tail char L'\0' into Length
1535 DstBuf
= (CHAR16
*)Dst
;
1536 ZeroMem (TemStr
, sizeof (TemStr
));
1537 for (Index
= 0; Index
< Length
; Index
+= 4) {
1538 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1539 DstBuf
[Index
/4] = (CHAR16
)StrHexToUint64 (TemStr
);
1543 // Add tailing L'\0' character
1545 DstBuf
[Index
/4] = L
'\0';
1547 ZeroMem (TemStr
, sizeof (TemStr
));
1548 for (Index
= 0; Index
< Length
; Index
++) {
1549 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1550 DigitUint8
= (UINT8
)StrHexToUint64 (TemStr
);
1551 if ((Index
& 1) == 0) {
1552 Dst
[Index
/2] = DigitUint8
;
1554 Dst
[Index
/2] = (UINT8
)((DigitUint8
<< 4) + Dst
[Index
/2]);
1559 *StringPtr
= TempChar
;
1561 if ((Buffer
!= NULL
) && Question
->QuestionReferToBitField
) {
1562 GetBitsQuestionValue (Question
, Buffer
);
1570 Get Question's current Value.
1572 @param FormSet FormSet data structure.
1573 @param Form Form data structure.
1574 @param Question Question to be initialized.
1575 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1577 @retval EFI_SUCCESS The function completed successfully.
1582 IN FORM_BROWSER_FORMSET
*FormSet
,
1583 IN FORM_BROWSER_FORM
*Form
,
1584 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1585 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1594 BROWSER_STORAGE
*Storage
;
1595 FORMSET_STORAGE
*FormsetStorage
;
1596 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1597 CHAR16
*ConfigRequest
;
1602 BOOLEAN IsBufferStorage
;
1605 Status
= EFI_SUCCESS
;
1609 if (GetValueFrom
>= GetSetValueWithMax
) {
1610 return EFI_INVALID_PARAMETER
;
1614 // Question value is provided by an Expression, evaluate it
1616 if (Question
->ValueExpression
!= NULL
) {
1617 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1618 if (!EFI_ERROR (Status
)) {
1619 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1620 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1621 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1622 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1623 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1625 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1626 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1629 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1632 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1633 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1640 // Get question value by read expression.
1642 if ((Question
->ReadExpression
!= NULL
) && (Form
->FormType
== STANDARD_MAP_FORM_TYPE
)) {
1643 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1644 if (!EFI_ERROR (Status
) &&
1645 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
)))
1648 // Only update question value to the valid result.
1650 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1651 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1652 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1653 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1654 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1656 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1657 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1660 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1663 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1664 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1670 // Question value is provided by RTC
1672 Storage
= Question
->Storage
;
1673 QuestionValue
= &Question
->HiiValue
.Value
;
1674 if (Storage
== NULL
) {
1676 // It's a Question without storage, or RTC date/time
1678 if ((Question
->Operand
== EFI_IFR_DATE_OP
) || (Question
->Operand
== EFI_IFR_TIME_OP
)) {
1680 // Date and time define the same Flags bit
1682 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1683 case QF_DATE_STORAGE_TIME
:
1684 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1687 case QF_DATE_STORAGE_WAKEUP
:
1688 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1691 case QF_DATE_STORAGE_NORMAL
:
1694 // For date/time without storage
1699 if (EFI_ERROR (Status
)) {
1700 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1701 QuestionValue
->date
.Year
= 0xff;
1702 QuestionValue
->date
.Month
= 0xff;
1703 QuestionValue
->date
.Day
= 0xff;
1705 QuestionValue
->time
.Hour
= 0xff;
1706 QuestionValue
->time
.Minute
= 0xff;
1707 QuestionValue
->time
.Second
= 0xff;
1713 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1714 QuestionValue
->date
.Year
= EfiTime
.Year
;
1715 QuestionValue
->date
.Month
= EfiTime
.Month
;
1716 QuestionValue
->date
.Day
= EfiTime
.Day
;
1718 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1719 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1720 QuestionValue
->time
.Second
= EfiTime
.Second
;
1728 // Question value is provided by EFI variable
1730 StorageWidth
= Question
->StorageWidth
;
1731 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1732 if (Question
->BufferValue
!= NULL
) {
1733 Dst
= Question
->BufferValue
;
1735 Dst
= (UINT8
*)QuestionValue
;
1738 Status
= gRT
->GetVariable (
1739 Question
->VariableName
,
1746 // Always return success, even this EFI variable doesn't exist
1752 // Question Value is provided by Buffer Storage or NameValue Storage
1754 if (Question
->BufferValue
!= NULL
) {
1756 // This Question is password or orderedlist
1758 Dst
= Question
->BufferValue
;
1761 // Other type of Questions
1763 Dst
= (UINT8
*)&Question
->HiiValue
.Value
;
1766 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
1767 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
1769 IsBufferStorage
= TRUE
;
1771 IsBufferStorage
= FALSE
;
1774 if ((GetValueFrom
== GetSetValueWithEditBuffer
) || (GetValueFrom
== GetSetValueWithBuffer
)) {
1775 if (IsBufferStorage
) {
1776 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1778 // Copy from storage Edit buffer
1779 // If the Question refer to bit filed, get the value in the related bit filed.
1781 if (Question
->QuestionReferToBitField
) {
1782 GetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
);
1784 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1788 // Copy from storage Edit buffer
1789 // If the Question refer to bit filed, get the value in the related bit filed.
1791 if (Question
->QuestionReferToBitField
) {
1792 GetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
);
1794 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1799 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1800 if (EFI_ERROR (Status
)) {
1804 ASSERT (Value
!= NULL
);
1805 Status
= BufferToValue (Question
, Value
);
1809 FormsetStorage
= GetFstStgFromVarId (FormSet
, Question
->VarStoreId
);
1810 ASSERT (FormsetStorage
!= NULL
);
1812 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1813 // <ConfigHdr> + "&" + <VariableName>
1815 if (IsBufferStorage
) {
1816 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1817 Length
+= StrLen (Question
->BlockName
);
1819 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1820 Length
+= StrLen (Question
->VariableName
) + 1;
1823 // Allocate buffer include '\0'
1824 MaxLen
= Length
+ 1;
1825 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1826 ASSERT (ConfigRequest
!= NULL
);
1828 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1829 if (IsBufferStorage
) {
1830 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1832 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1833 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1837 // Request current settings from Configuration Driver
1839 Status
= mHiiConfigRouting
->ExtractConfig (
1845 FreePool (ConfigRequest
);
1846 if (EFI_ERROR (Status
)) {
1851 // Skip <ConfigRequest>
1853 if (IsBufferStorage
) {
1854 Value
= StrStr (Result
, L
"&VALUE");
1855 if (Value
== NULL
) {
1857 return EFI_NOT_FOUND
;
1865 Value
= Result
+ Length
;
1868 if (*Value
!= '=') {
1870 return EFI_NOT_FOUND
;
1874 // Skip '=', point to value
1878 Status
= BufferToValue (Question
, Value
);
1879 if (EFI_ERROR (Status
)) {
1885 // Synchronize Edit Buffer
1887 if (IsBufferStorage
) {
1888 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1890 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1893 if (Result
!= NULL
) {
1902 Save Question Value to edit copy(cached) or Storage(uncached).
1904 @param FormSet FormSet data structure.
1905 @param Form Form data structure.
1906 @param Question Pointer to the Question.
1907 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1909 @retval EFI_SUCCESS The function completed successfully.
1914 IN FORM_BROWSER_FORMSET
*FormSet
,
1915 IN FORM_BROWSER_FORM
*Form
,
1916 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1917 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1927 BROWSER_STORAGE
*Storage
;
1928 FORMSET_STORAGE
*FormsetStorage
;
1929 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1934 BOOLEAN IsBufferStorage
;
1940 NAME_VALUE_NODE
*Node
;
1943 Status
= EFI_SUCCESS
;
1946 if (SetValueTo
>= GetSetValueWithMax
) {
1947 return EFI_INVALID_PARAMETER
;
1951 // If Question value is provided by an Expression, then it is read only
1953 if (Question
->ValueExpression
!= NULL
) {
1958 // Before set question value, evaluate its write expression.
1960 if ((Question
->WriteExpression
!= NULL
) && (Form
->FormType
== STANDARD_MAP_FORM_TYPE
)) {
1961 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1962 if (EFI_ERROR (Status
)) {
1968 // Question value is provided by RTC
1970 Storage
= Question
->Storage
;
1971 QuestionValue
= &Question
->HiiValue
.Value
;
1972 if (Storage
== NULL
) {
1974 // It's a Question without storage, or RTC date/time
1976 if ((Question
->Operand
== EFI_IFR_DATE_OP
) || (Question
->Operand
== EFI_IFR_TIME_OP
)) {
1978 // Date and time define the same Flags bit
1980 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1981 case QF_DATE_STORAGE_TIME
:
1982 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1985 case QF_DATE_STORAGE_WAKEUP
:
1986 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1989 case QF_DATE_STORAGE_NORMAL
:
1992 // For date/time without storage
1997 if (EFI_ERROR (Status
)) {
2001 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
2002 EfiTime
.Year
= QuestionValue
->date
.Year
;
2003 EfiTime
.Month
= QuestionValue
->date
.Month
;
2004 EfiTime
.Day
= QuestionValue
->date
.Day
;
2006 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
2007 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
2008 EfiTime
.Second
= QuestionValue
->time
.Second
;
2011 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
2012 Status
= gRT
->SetTime (&EfiTime
);
2014 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
2022 // Question value is provided by EFI variable
2024 StorageWidth
= Question
->StorageWidth
;
2025 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2026 if (Question
->BufferValue
!= NULL
) {
2027 Src
= Question
->BufferValue
;
2029 Src
= (UINT8
*)QuestionValue
;
2032 Status
= gRT
->SetVariable (
2033 Question
->VariableName
,
2035 Storage
->Attributes
,
2043 // Question Value is provided by Buffer Storage or NameValue Storage
2045 if (Question
->BufferValue
!= NULL
) {
2046 Src
= Question
->BufferValue
;
2048 Src
= (UINT8
*)&Question
->HiiValue
.Value
;
2051 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
2052 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
2054 IsBufferStorage
= TRUE
;
2056 IsBufferStorage
= FALSE
;
2059 IsString
= (BOOLEAN
)((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2061 if ((SetValueTo
== GetSetValueWithEditBuffer
) || (SetValueTo
== GetSetValueWithBuffer
)) {
2062 if (IsBufferStorage
) {
2063 if (SetValueTo
== GetSetValueWithEditBuffer
) {
2065 // Copy to storage edit buffer
2066 // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
2068 if (Question
->QuestionReferToBitField
) {
2069 SetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2071 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2073 } else if (SetValueTo
== GetSetValueWithBuffer
) {
2075 // Copy to storage buffer
2076 // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.
2078 if (Question
->QuestionReferToBitField
) {
2079 SetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2081 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2087 // Allocate enough string buffer.
2090 BufferLen
= ((StrLen ((CHAR16
*)Src
) * 4) + 1) * sizeof (CHAR16
);
2091 Value
= AllocateZeroPool (BufferLen
);
2092 ASSERT (Value
!= NULL
);
2094 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2096 TemName
= (CHAR16
*)Src
;
2098 for ( ; *TemName
!= L
'\0'; TemName
++) {
2099 UnicodeValueToStringS (
2101 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
2102 PREFIX_ZERO
| RADIX_HEX
,
2106 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
2109 BufferLen
= StorageWidth
* 2 + 1;
2110 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
2111 ASSERT (Value
!= NULL
);
2113 // Convert Buffer to Hex String
2115 TemBuffer
= Src
+ StorageWidth
- 1;
2117 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2118 UnicodeValueToStringS (
2120 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
2121 PREFIX_ZERO
| RADIX_HEX
,
2125 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2129 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2131 if (EFI_ERROR (Status
)) {
2135 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2137 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2138 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2140 if (IsBufferStorage
) {
2141 Length
= StrLen (Question
->BlockName
) + 7;
2143 Length
= StrLen (Question
->VariableName
) + 2;
2146 if (!IsBufferStorage
&& IsString
) {
2147 Length
+= (StrLen ((CHAR16
*)Src
) * 4);
2149 Length
+= (StorageWidth
* 2);
2152 FormsetStorage
= GetFstStgFromVarId (FormSet
, Question
->VarStoreId
);
2153 ASSERT (FormsetStorage
!= NULL
);
2154 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2155 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2156 ASSERT (ConfigResp
!= NULL
);
2158 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2159 if (IsBufferStorage
) {
2160 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2161 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2163 StrCatS (ConfigResp
, MaxLen
, L
"&");
2164 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2165 StrCatS (ConfigResp
, MaxLen
, L
"=");
2168 Value
= ConfigResp
+ StrLen (ConfigResp
);
2170 if (!IsBufferStorage
&& IsString
) {
2172 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2174 TemName
= (CHAR16
*)Src
;
2176 for ( ; *TemName
!= L
'\0'; TemName
++) {
2177 UnicodeValueToStringS (
2179 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2180 PREFIX_ZERO
| RADIX_HEX
,
2184 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2188 // Convert Buffer to Hex String
2190 TemBuffer
= Src
+ StorageWidth
- 1;
2192 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2193 UnicodeValueToStringS (
2195 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2196 PREFIX_ZERO
| RADIX_HEX
,
2200 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2205 // Convert to lower char.
2207 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2208 if ((*Value
>= L
'A') && (*Value
<= L
'Z')) {
2209 *Value
= (CHAR16
)(*Value
- L
'A' + L
'a');
2214 // Submit Question Value to Configuration Driver
2216 Status
= mHiiConfigRouting
->RouteConfig (
2221 if (EFI_ERROR (Status
)) {
2222 FreePool (ConfigResp
);
2226 FreePool (ConfigResp
);
2229 // Sync storage, from editbuffer to buffer.
2231 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2238 Perform nosubmitif check for a Form.
2240 @param FormSet FormSet data structure.
2241 @param Form Form data structure.
2242 @param Question The Question to be validated.
2243 @param Type Validation type: NoSubmit
2245 @retval EFI_SUCCESS Form validation pass.
2246 @retval other Form validation failed.
2251 IN FORM_BROWSER_FORMSET
*FormSet
,
2252 IN FORM_BROWSER_FORM
*Form
,
2253 IN FORM_BROWSER_STATEMENT
*Question
,
2259 LIST_ENTRY
*ListHead
;
2260 FORM_EXPRESSION
*Expression
;
2261 UINT32 BrowserStatus
;
2264 BrowserStatus
= BROWSER_SUCCESS
;
2268 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2269 ListHead
= &Question
->InconsistentListHead
;
2272 case EFI_HII_EXPRESSION_WARNING_IF
:
2273 ListHead
= &Question
->WarningListHead
;
2276 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2277 ListHead
= &Question
->NoSubmitListHead
;
2282 return EFI_UNSUPPORTED
;
2285 Link
= GetFirstNode (ListHead
);
2286 while (!IsNull (ListHead
, Link
)) {
2287 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2290 // Evaluate the expression
2292 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2293 if (EFI_ERROR (Status
)) {
2297 if (IsTrue (&Expression
->Result
)) {
2299 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2300 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2303 case EFI_HII_EXPRESSION_WARNING_IF
:
2304 BrowserStatus
= BROWSER_WARNING_IF
;
2307 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2308 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2310 // This code only used to compatible with old display engine,
2311 // New display engine will not use this field.
2313 if (Expression
->Error
!= 0) {
2314 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2324 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2326 // If in system submit process and for no_submit_if check, not popup this error message.
2327 // Will process this fail again later in not system submit process.
2329 PopupErrorMessage (BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2332 if (ErrorStr
!= NULL
) {
2333 FreePool (ErrorStr
);
2336 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2339 return EFI_NOT_READY
;
2343 Link
= GetNextNode (ListHead
, Link
);
2350 Perform question check.
2352 If one question has more than one check, process form high priority to low.
2353 Only one error info will be popup.
2355 @param FormSet FormSet data structure.
2356 @param Form Form data structure.
2357 @param Question The Question to be validated.
2359 @retval EFI_SUCCESS Form validation pass.
2360 @retval other Form validation failed.
2364 ValueChangedValidation (
2365 IN FORM_BROWSER_FORMSET
*FormSet
,
2366 IN FORM_BROWSER_FORM
*Form
,
2367 IN FORM_BROWSER_STATEMENT
*Question
2372 Status
= EFI_SUCCESS
;
2375 // Do the inconsistentif check.
2377 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2378 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2379 if (EFI_ERROR (Status
)) {
2385 // Do the warningif check.
2387 if (!IsListEmpty (&Question
->WarningListHead
)) {
2388 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2395 Perform NoSubmit check for each Form in FormSet.
2397 @param FormSet FormSet data structure.
2398 @param CurrentForm Current input form data structure.
2399 @param Statement The statement for this check.
2401 @retval EFI_SUCCESS Form validation pass.
2402 @retval other Form validation failed.
2407 IN FORM_BROWSER_FORMSET
*FormSet
,
2408 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2409 OUT FORM_BROWSER_STATEMENT
**Statement
2414 FORM_BROWSER_STATEMENT
*Question
;
2415 FORM_BROWSER_FORM
*Form
;
2416 LIST_ENTRY
*LinkForm
;
2418 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2419 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2420 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2421 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2423 if ((*CurrentForm
!= NULL
) && (*CurrentForm
!= Form
)) {
2427 Link
= GetFirstNode (&Form
->StatementListHead
);
2428 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2429 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2430 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2431 if (EFI_ERROR (Status
)) {
2432 if (*CurrentForm
== NULL
) {
2433 *CurrentForm
= Form
;
2436 if (Statement
!= NULL
) {
2437 *Statement
= Question
;
2443 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2451 Fill storage's edit copy with settings requested from Configuration Driver.
2453 @param Storage The storage which need to sync.
2454 @param ConfigRequest The config request string which used to sync storage.
2455 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2456 editbuffer to buffer
2457 if TRUE, copy the editbuffer to the buffer.
2458 if FALSE, copy the buffer to the editbuffer.
2460 @retval EFI_SUCCESS The function completed successfully.
2464 SynchronizeStorage (
2465 OUT BROWSER_STORAGE
*Storage
,
2466 IN CHAR16
*ConfigRequest
,
2467 IN BOOLEAN SyncOrRestore
2471 EFI_STRING Progress
;
2475 NAME_VALUE_NODE
*Node
;
2479 Status
= EFI_SUCCESS
;
2482 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
2483 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
2485 BufferSize
= Storage
->Size
;
2487 if (SyncOrRestore
) {
2488 Src
= Storage
->EditBuffer
;
2489 Dst
= Storage
->Buffer
;
2491 Src
= Storage
->Buffer
;
2492 Dst
= Storage
->EditBuffer
;
2495 if (ConfigRequest
!= NULL
) {
2496 Status
= mHiiConfigRouting
->BlockToConfig (
2504 if (EFI_ERROR (Status
)) {
2508 Status
= mHiiConfigRouting
->ConfigToBlock (
2515 if (Result
!= NULL
) {
2519 CopyMem (Dst
, Src
, BufferSize
);
2521 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2522 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2523 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2524 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2526 if (((ConfigRequest
!= NULL
) && (StrStr (ConfigRequest
, Node
->Name
) != NULL
)) ||
2527 (ConfigRequest
== NULL
))
2529 if (SyncOrRestore
) {
2530 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2532 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2536 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2544 When discard the question value, call the callback function with Changed type
2545 to inform the hii driver.
2547 @param FormSet FormSet data structure.
2548 @param Form Form data structure.
2552 SendDiscardInfoToDriver (
2553 IN FORM_BROWSER_FORMSET
*FormSet
,
2554 IN FORM_BROWSER_FORM
*Form
2558 FORM_BROWSER_STATEMENT
*Question
;
2559 EFI_IFR_TYPE_VALUE
*TypeValue
;
2560 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2562 if (FormSet
->ConfigAccess
== NULL
) {
2566 Link
= GetFirstNode (&Form
->StatementListHead
);
2567 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2568 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2569 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2571 if ((Question
->Storage
== NULL
) || (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2575 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2579 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2583 if (!Question
->ValueChanged
) {
2588 // Restore the question value before call the CHANGED callback type.
2590 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2592 if (Question
->Operand
== EFI_IFR_STRING_OP
) {
2593 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2596 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2597 TypeValue
= (EFI_IFR_TYPE_VALUE
*)Question
->BufferValue
;
2599 TypeValue
= &Question
->HiiValue
.Value
;
2602 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2603 FormSet
->ConfigAccess
->Callback (
2604 FormSet
->ConfigAccess
,
2605 EFI_BROWSER_ACTION_CHANGED
,
2606 Question
->QuestionId
,
2607 Question
->HiiValue
.Type
,
2615 When submit the question value, call the callback function with Submitted type
2616 to inform the hii driver.
2618 @param FormSet FormSet data structure.
2619 @param Form Form data structure.
2623 SubmitCallbackForForm (
2624 IN FORM_BROWSER_FORMSET
*FormSet
,
2625 IN FORM_BROWSER_FORM
*Form
2629 FORM_BROWSER_STATEMENT
*Question
;
2630 EFI_IFR_TYPE_VALUE
*TypeValue
;
2631 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2633 if (FormSet
->ConfigAccess
== NULL
) {
2637 Link
= GetFirstNode (&Form
->StatementListHead
);
2638 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2639 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2640 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2642 if ((Question
->Storage
== NULL
) || (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2646 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2650 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2654 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2655 TypeValue
= (EFI_IFR_TYPE_VALUE
*)Question
->BufferValue
;
2657 TypeValue
= &Question
->HiiValue
.Value
;
2660 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2661 FormSet
->ConfigAccess
->Callback (
2662 FormSet
->ConfigAccess
,
2663 EFI_BROWSER_ACTION_SUBMITTED
,
2664 Question
->QuestionId
,
2665 Question
->HiiValue
.Type
,
2673 When value set Success, call the submit callback function.
2675 @param FormSet FormSet data structure.
2676 @param Form Form data structure.
2681 IN FORM_BROWSER_FORMSET
*FormSet
,
2682 IN FORM_BROWSER_FORM
*Form
2685 FORM_BROWSER_FORM
*CurrentForm
;
2689 SubmitCallbackForForm (FormSet
, Form
);
2693 Link
= GetFirstNode (&FormSet
->FormListHead
);
2694 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2695 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2696 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2698 SubmitCallbackForForm (FormSet
, CurrentForm
);
2703 Validate the HiiHandle.
2705 @param HiiHandle The input HiiHandle which need to validate.
2707 @retval TRUE The handle is validate.
2708 @retval FALSE The handle is invalidate.
2713 EFI_HII_HANDLE HiiHandle
2716 EFI_HII_HANDLE
*HiiHandles
;
2720 if (HiiHandle
== NULL
) {
2726 HiiHandles
= HiiGetHiiHandles (NULL
);
2727 ASSERT (HiiHandles
!= NULL
);
2729 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2730 if (HiiHandles
[Index
] == HiiHandle
) {
2736 FreePool (HiiHandles
);
2742 Validate the FormSet. If the formset is not validate, remove it from the list.
2744 @param FormSet The input FormSet which need to validate.
2746 @retval TRUE The handle is validate.
2747 @retval FALSE The handle is invalidate.
2752 FORM_BROWSER_FORMSET
*FormSet
2757 ASSERT (FormSet
!= NULL
);
2759 Find
= ValidateHiiHandle (FormSet
->HiiHandle
);
2761 // Should not remove the formset which is being used.
2763 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2764 CleanBrowserStorage (FormSet
);
2765 RemoveEntryList (&FormSet
->Link
);
2766 DestroyFormSet (FormSet
);
2773 Check whether need to enable the reset flag in form level.
2774 Also clean all ValueChanged flag in question.
2776 @param SetFlag Whether need to set the Reset Flag.
2777 @param FormSet FormSet data structure.
2778 @param Form Form data structure.
2784 IN FORM_BROWSER_FORMSET
*FormSet
,
2785 IN FORM_BROWSER_FORM
*Form
2789 FORM_BROWSER_STATEMENT
*Question
;
2792 Link
= GetFirstNode (&Form
->StatementListHead
);
2793 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2794 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2795 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2797 if (!Question
->ValueChanged
) {
2801 OldValue
= Question
->ValueChanged
;
2804 // Compare the buffer and editbuffer data to see whether the data has been saved.
2806 Question
->ValueChanged
= IsQuestionValueChanged (FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2809 // Only the changed data has been saved, then need to set the reset flag.
2811 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2812 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2813 gResetRequiredFormLevel
= TRUE
;
2814 gResetRequiredSystemLevel
= TRUE
;
2817 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2818 gFlagReconnect
= TRUE
;
2825 Check whether need to enable the reset flag.
2826 Also clean ValueChanged flag for all statements.
2828 Form level or formset level, only one.
2830 @param SetFlag Whether need to set the Reset Flag.
2831 @param FormSet FormSet data structure.
2832 @param Form Form data structure.
2836 ValueChangeResetFlagUpdate (
2838 IN FORM_BROWSER_FORMSET
*FormSet
,
2839 IN FORM_BROWSER_FORM
*Form
2842 FORM_BROWSER_FORM
*CurrentForm
;
2846 UpdateFlagForForm (SetFlag
, FormSet
, Form
);
2850 Link
= GetFirstNode (&FormSet
->FormListHead
);
2851 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2852 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2853 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2855 UpdateFlagForForm (SetFlag
, FormSet
, CurrentForm
);
2860 Base on the return Progress string to find the form.
2862 Base on the first return Offset/Width (Name) string to find the form
2863 which keep this string.
2865 @param FormSet FormSet data structure.
2866 @param Storage Storage which has this Progress string.
2867 @param Progress The Progress string which has the first fail string.
2868 @param RetForm The return form for this progress string.
2869 @param RetQuestion The return question for the error progress string.
2871 @retval TRUE Find the error form and statement for this error progress string.
2872 @retval FALSE Not find the error form.
2876 FindQuestionFromProgress (
2877 IN FORM_BROWSER_FORMSET
*FormSet
,
2878 IN BROWSER_STORAGE
*Storage
,
2879 IN EFI_STRING Progress
,
2880 OUT FORM_BROWSER_FORM
**RetForm
,
2881 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2885 LIST_ENTRY
*LinkStorage
;
2886 LIST_ENTRY
*LinkStatement
;
2887 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2888 FORM_BROWSER_FORM
*Form
;
2890 FORM_BROWSER_STATEMENT
*Statement
;
2892 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2896 *RetQuestion
= NULL
;
2899 // Skip the first "&" or the ConfigHdr part.
2901 if (*Progress
== '&') {
2905 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2907 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2909 // For Name/Value type, Skip the ConfigHdr part.
2911 EndStr
= StrStr (Progress
, L
"PATH=");
2912 ASSERT (EndStr
!= NULL
);
2913 while (*EndStr
!= '&') {
2920 // For Buffer type, Skip the ConfigHdr part.
2922 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2923 ASSERT (EndStr
!= NULL
);
2927 Progress
= EndStr
+ 1;
2931 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2933 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2935 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2936 // here, just keep the "Fred" string.
2938 EndStr
= StrStr (Progress
, L
"=");
2939 ASSERT (EndStr
!= NULL
);
2943 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2944 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2946 EndStr
= StrStr (Progress
, L
"&VALUE=");
2947 ASSERT (EndStr
!= NULL
);
2952 // Search in the form list.
2954 Link
= GetFirstNode (&FormSet
->FormListHead
);
2955 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2956 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2957 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2960 // Search in the ConfigReqeust list in this form.
2962 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2963 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2964 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2965 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2967 if (Storage
!= ConfigInfo
->Storage
) {
2971 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2973 // Find the OffsetWidth string in this form.
2980 if (*RetForm
!= NULL
) {
2981 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2982 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2983 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2984 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2986 if ((Statement
->BlockName
!= NULL
) && (StrStr (Statement
->BlockName
, Progress
) != NULL
)) {
2987 *RetQuestion
= Statement
;
2991 if ((Statement
->VariableName
!= NULL
) && (StrStr (Statement
->VariableName
, Progress
) != NULL
)) {
2992 *RetQuestion
= Statement
;
2998 if (*RetForm
!= NULL
) {
3004 // restore the OffsetWidth string to the original format.
3006 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3012 return (BOOLEAN
)(*RetForm
!= NULL
);
3016 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
3017 for form and formset.
3019 @param Storage Storage which has this Progress string.
3020 @param ConfigRequest The ConfigRequest string.
3021 @param Progress The Progress string which has the first fail string.
3022 @param RestoreConfigRequest Return the RestoreConfigRequest string.
3023 @param SyncConfigRequest Return the SyncConfigRequest string.
3027 GetSyncRestoreConfigRequest (
3028 IN BROWSER_STORAGE
*Storage
,
3029 IN EFI_STRING ConfigRequest
,
3030 IN EFI_STRING Progress
,
3031 OUT EFI_STRING
*RestoreConfigRequest
,
3032 OUT EFI_STRING
*SyncConfigRequest
3036 EFI_STRING ConfigHdrEndStr
;
3037 EFI_STRING ElementStr
;
3039 UINTN RestoreEleSize
;
3042 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
3044 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
3045 // Need to restore all the fields in the ConfigRequest.
3047 if (*Progress
== L
'G') {
3048 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3049 ASSERT (*RestoreConfigRequest
!= NULL
);
3054 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
3056 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3058 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
3059 // here, just keep the "Fred" string.
3061 EndStr
= StrStr (Progress
, L
"=");
3062 ASSERT (EndStr
!= NULL
);
3065 // Find the ConfigHdr in ConfigRequest.
3067 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
3068 ASSERT (ConfigHdrEndStr
!= NULL
);
3069 while (*ConfigHdrEndStr
!= L
'&') {
3074 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
3075 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
3077 EndStr
= StrStr (Progress
, L
"&VALUE=");
3078 ASSERT (EndStr
!= NULL
);
3081 // Find the ConfigHdr in ConfigRequest.
3083 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
3087 // Find the first fail pair in the ConfigRequest.
3089 ElementStr
= StrStr (ConfigRequest
, Progress
);
3090 ASSERT (ElementStr
!= NULL
);
3092 // To get the RestoreConfigRequest.
3094 RestoreEleSize
= StrSize (ElementStr
);
3095 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
3096 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
3097 ASSERT (*RestoreConfigRequest
!= NULL
);
3098 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
3099 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
3101 // To get the SyncConfigRequest.
3103 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
3104 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
3105 ASSERT (*SyncConfigRequest
!= NULL
);
3106 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
3109 // restore the Progress string to the original format.
3111 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3119 Popup an save error info and get user input.
3121 @param TitleId The form title id.
3122 @param HiiHandle The hii handle for this package.
3124 @retval UINT32 The user select option for the save fail.
3125 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3129 IN EFI_STRING_ID TitleId
,
3130 IN EFI_HII_HANDLE HiiHandle
3134 CHAR16
*StringBuffer
;
3137 FormTitle
= GetToken (TitleId
, HiiHandle
);
3139 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3140 ASSERT (StringBuffer
!= NULL
);
3144 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3145 L
"Submit Fail For Form: %s.",
3149 RetVal
= PopupErrorMessage (BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3151 FreePool (StringBuffer
);
3152 FreePool (FormTitle
);
3158 Popup an NO_SUBMIT_IF error info and get user input.
3160 @param TitleId The form title id.
3161 @param HiiHandle The hii handle for this package.
3163 @retval UINT32 The user select option for the save fail.
3164 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3167 ConfirmNoSubmitFail (
3168 IN EFI_STRING_ID TitleId
,
3169 IN EFI_HII_HANDLE HiiHandle
3173 CHAR16
*StringBuffer
;
3176 FormTitle
= GetToken (TitleId
, HiiHandle
);
3178 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3179 ASSERT (StringBuffer
!= NULL
);
3183 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3184 L
"NO_SUBMIT_IF error For Form: %s.",
3188 RetVal
= PopupErrorMessage (BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3190 FreePool (StringBuffer
);
3191 FreePool (FormTitle
);
3197 Discard data based on the input setting scope (Form, FormSet or System).
3199 @param FormSet FormSet data structure.
3200 @param Form Form data structure.
3201 @param SettingScope Setting Scope for Discard action.
3203 @retval EFI_SUCCESS The function completed successfully.
3204 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3209 IN FORM_BROWSER_FORMSET
*FormSet
,
3210 IN FORM_BROWSER_FORM
*Form
,
3211 IN BROWSER_SETTING_SCOPE SettingScope
3215 FORMSET_STORAGE
*Storage
;
3216 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3217 FORM_BROWSER_FORMSET
*LocalFormSet
;
3218 FORM_BROWSER_FORMSET
*OldFormSet
;
3221 // Check the supported setting level.
3223 if (SettingScope
>= MaxLevel
) {
3224 return EFI_UNSUPPORTED
;
3227 if ((SettingScope
== FormLevel
) && IsNvUpdateRequiredForForm (Form
)) {
3229 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3230 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3231 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3232 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3234 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3239 // Skip if there is no RequestElement
3241 if (ConfigInfo
->ElementCount
== 0) {
3246 // Prepare <ConfigResp>
3248 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3251 // Call callback with Changed type to inform the driver.
3253 SendDiscardInfoToDriver (FormSet
, Form
);
3256 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3257 } else if ((SettingScope
== FormSetLevel
) && IsNvUpdateRequiredForFormSet (FormSet
)) {
3259 // Discard Buffer storage or Name/Value storage
3261 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3262 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3263 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3264 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3266 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3271 // Skip if there is no RequestElement
3273 if (Storage
->ElementCount
== 0) {
3277 SynchronizeStorage (Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3280 Link
= GetFirstNode (&FormSet
->FormListHead
);
3281 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3282 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3283 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3286 // Call callback with Changed type to inform the driver.
3288 SendDiscardInfoToDriver (FormSet
, Form
);
3291 ValueChangeResetFlagUpdate (FALSE
, FormSet
, NULL
);
3292 } else if (SettingScope
== SystemLevel
) {
3294 // System Level Discard.
3296 OldFormSet
= mSystemLevelFormSet
;
3299 // Discard changed value for each FormSet in the maintain list.
3301 Link
= GetFirstNode (&gBrowserFormSetList
);
3302 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3303 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3304 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3305 if (!ValidateFormSet (LocalFormSet
)) {
3309 mSystemLevelFormSet
= LocalFormSet
;
3311 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3312 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3314 // Remove maintain backup list after discard except for the current using FormSet.
3316 CleanBrowserStorage (LocalFormSet
);
3317 RemoveEntryList (&LocalFormSet
->Link
);
3318 DestroyFormSet (LocalFormSet
);
3322 mSystemLevelFormSet
= OldFormSet
;
3329 Submit data for a form.
3331 @param FormSet FormSet data structure.
3332 @param Form Form data structure.
3334 @retval EFI_SUCCESS The function completed successfully.
3335 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3340 IN FORM_BROWSER_FORMSET
*FormSet
,
3341 IN FORM_BROWSER_FORM
*Form
3346 EFI_STRING ConfigResp
;
3347 EFI_STRING Progress
;
3348 BROWSER_STORAGE
*Storage
;
3349 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3350 BOOLEAN SubmitFormFail
;
3352 SubmitFormFail
= FALSE
;
3354 if (!IsNvUpdateRequiredForForm (Form
)) {
3358 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3359 if (EFI_ERROR (Status
)) {
3363 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3364 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3365 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3366 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3368 Storage
= ConfigInfo
->Storage
;
3369 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3374 // Skip if there is no RequestElement
3376 if (ConfigInfo
->ElementCount
== 0) {
3381 // 1. Prepare <ConfigResp>
3383 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3384 if (EFI_ERROR (Status
)) {
3389 // 2. Set value to hii config routine protocol.
3391 Status
= mHiiConfigRouting
->RouteConfig (
3397 if (EFI_ERROR (Status
)) {
3399 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3401 SubmitFormFail
= TRUE
;
3402 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3403 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3404 FreePool (ConfigResp
);
3408 FreePool (ConfigResp
);
3410 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3412 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3416 // 4. Process the save failed storage.
3418 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3419 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3420 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3421 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3422 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3423 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3425 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3426 // base on the SyncConfigRequest to Sync the buffer.
3428 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3429 FreePool (ConfigInfo
->RestoreConfigRequest
);
3430 ConfigInfo
->RestoreConfigRequest
= NULL
;
3431 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3432 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3433 FreePool (ConfigInfo
->SyncConfigRequest
);
3434 ConfigInfo
->SyncConfigRequest
= NULL
;
3437 Status
= EFI_SUCCESS
;
3440 SendDiscardInfoToDriver (FormSet
, Form
);
3442 Status
= EFI_UNSUPPORTED
;
3446 // Free Form save fail list.
3448 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3449 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3450 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3451 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3456 // 5. Update the NV flag.
3458 ValueChangeResetFlagUpdate (TRUE
, FormSet
, Form
);
3461 // 6 Call callback with Submitted type to inform the driver.
3463 if (!SubmitFormFail
) {
3464 SubmitCallback (FormSet
, Form
);
3471 Submit data for a formset.
3473 @param FormSet FormSet data structure.
3474 @param SkipProcessFail Whether skip to process the save failed storage.
3475 If submit formset is called when do system level save,
3476 set this value to true and process the failed formset
3478 if submit formset is called when do formset level save,
3479 set the value to false and process the failed storage
3480 right after process all storages for this formset.
3482 @retval EFI_SUCCESS The function completed successfully.
3483 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3488 IN FORM_BROWSER_FORMSET
*FormSet
,
3489 IN BOOLEAN SkipProcessFail
3494 EFI_STRING ConfigResp
;
3495 EFI_STRING Progress
;
3496 BROWSER_STORAGE
*Storage
;
3497 FORMSET_STORAGE
*FormSetStorage
;
3498 FORM_BROWSER_FORM
*Form
;
3499 BOOLEAN HasInserted
;
3500 FORM_BROWSER_STATEMENT
*Question
;
3501 BOOLEAN SubmitFormSetFail
;
3502 BOOLEAN DiscardChange
;
3504 HasInserted
= FALSE
;
3505 SubmitFormSetFail
= FALSE
;
3506 DiscardChange
= FALSE
;
3508 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3513 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3514 if (EFI_ERROR (Status
)) {
3515 if (SkipProcessFail
) {
3517 // Process NO_SUBMIT check first, so insert it at head.
3519 FormSet
->SaveFailForm
= Form
;
3520 FormSet
->SaveFailStatement
= Question
;
3521 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3530 // Submit Buffer storage or Name/Value storage
3532 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3533 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3534 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3535 Storage
= FormSetStorage
->BrowserStorage
;
3536 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3538 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3543 // Skip if there is no RequestElement
3545 if (FormSetStorage
->ElementCount
== 0) {
3550 // 1. Prepare <ConfigResp>
3552 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3553 if (EFI_ERROR (Status
)) {
3558 // 2. Send <ConfigResp> to Routine config Protocol.
3560 Status
= mHiiConfigRouting
->RouteConfig (
3565 if (EFI_ERROR (Status
)) {
3567 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3569 SubmitFormSetFail
= TRUE
;
3570 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3571 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3574 // Call submit formset for system level, save the formset info
3575 // and process later.
3577 FindQuestionFromProgress (FormSet
, Storage
, Progress
, &Form
, &Question
);
3578 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3579 FormSet
->SaveFailForm
= Form
;
3580 FormSet
->SaveFailStatement
= Question
;
3581 if (SkipProcessFail
) {
3582 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3588 FreePool (ConfigResp
);
3592 FreePool (ConfigResp
);
3594 // 3. Config success, update storage shadow Buffer
3596 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3600 // 4. Has save fail storage need to handle.
3603 if (!SkipProcessFail
) {
3605 // If not in system level, just handl the save failed storage here.
3607 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3608 DiscardChange
= TRUE
;
3609 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3610 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3611 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3612 Storage
= FormSetStorage
->BrowserStorage
;
3613 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3615 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3616 // base on the SyncConfigRequest to Sync the buffer.
3618 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3619 FreePool (FormSetStorage
->RestoreConfigRequest
);
3620 FormSetStorage
->RestoreConfigRequest
= NULL
;
3621 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3622 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3623 FreePool (FormSetStorage
->SyncConfigRequest
);
3624 FormSetStorage
->SyncConfigRequest
= NULL
;
3627 Status
= EFI_SUCCESS
;
3630 UiCopyMenuList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3632 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3633 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3634 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3635 gCurrentSelection
->FormId
= Form
->FormId
;
3636 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3638 Status
= EFI_UNSUPPORTED
;
3642 // Free FormSet save fail list.
3644 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3645 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3646 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3647 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3651 // If in system level, just return error and handle the failed formset later.
3653 Status
= EFI_UNSUPPORTED
;
3658 // If user discard the change, send the discard info to driver.
3660 if (DiscardChange
) {
3661 Link
= GetFirstNode (&FormSet
->FormListHead
);
3662 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3663 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3664 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3666 // Call callback with Changed type to inform the driver.
3668 SendDiscardInfoToDriver (FormSet
, Form
);
3673 // 5. Update the NV flag.
3675 ValueChangeResetFlagUpdate (TRUE
, FormSet
, NULL
);
3678 // 6. Call callback with Submitted type to inform the driver.
3680 if (!SubmitFormSetFail
) {
3681 SubmitCallback (FormSet
, NULL
);
3688 Submit data for all formsets.
3690 @retval EFI_SUCCESS The function completed successfully.
3691 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3701 LIST_ENTRY
*FormLink
;
3702 LIST_ENTRY
*StorageLink
;
3703 FORMSET_STORAGE
*FormSetStorage
;
3704 FORM_BROWSER_FORM
*Form
;
3705 FORM_BROWSER_FORMSET
*LocalFormSet
;
3706 UINT32 UserSelection
;
3707 FORM_BROWSER_STATEMENT
*Question
;
3709 mSystemSubmit
= TRUE
;
3710 Link
= GetFirstNode (&gBrowserFormSetList
);
3711 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3712 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3713 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3714 if (!ValidateFormSet (LocalFormSet
)) {
3718 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3719 if (EFI_ERROR (Status
)) {
3724 // Remove maintain backup list after save except for the current using FormSet.
3726 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3727 CleanBrowserStorage (LocalFormSet
);
3728 RemoveEntryList (&LocalFormSet
->Link
);
3729 DestroyFormSet (LocalFormSet
);
3733 mSystemSubmit
= FALSE
;
3735 Status
= EFI_SUCCESS
;
3738 // Process the save failed formsets.
3740 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3741 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3742 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3743 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3745 if (!ValidateFormSet (LocalFormSet
)) {
3749 Form
= LocalFormSet
->SaveFailForm
;
3750 Question
= LocalFormSet
->SaveFailStatement
;
3753 // Confirm with user, get user input.
3755 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3757 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3759 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3761 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3764 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3765 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3766 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3767 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3768 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3769 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3771 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3774 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3775 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3776 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3777 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3779 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3780 // base on the SyncConfigRequest to Sync the buffer.
3782 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3783 FreePool (FormSetStorage
->RestoreConfigRequest
);
3784 FormSetStorage
->RestoreConfigRequest
= NULL
;
3785 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3786 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3787 FreePool (FormSetStorage
->SyncConfigRequest
);
3788 FormSetStorage
->SyncConfigRequest
= NULL
;
3793 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3794 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3795 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3796 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3798 // Call callback with Changed type to inform the driver.
3800 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3803 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3804 CleanBrowserStorage (LocalFormSet
);
3805 RemoveEntryList (&LocalFormSet
->Link
);
3806 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3807 DestroyFormSet (LocalFormSet
);
3809 ValueChangeResetFlagUpdate (FALSE
, LocalFormSet
, NULL
);
3812 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3813 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3816 UiCopyMenuList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3818 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3819 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3820 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3821 gCurrentSelection
->FormId
= Form
->FormId
;
3822 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3824 Status
= EFI_UNSUPPORTED
;
3830 // Clean the list which will not process.
3832 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3833 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3834 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3835 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3837 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3838 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3839 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3840 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3848 Submit data based on the input Setting level (Form, FormSet or System).
3850 @param FormSet FormSet data structure.
3851 @param Form Form data structure.
3852 @param SettingScope Setting Scope for Submit action.
3854 @retval EFI_SUCCESS The function completed successfully.
3855 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3860 IN FORM_BROWSER_FORMSET
*FormSet
,
3861 IN FORM_BROWSER_FORM
*Form
,
3862 IN BROWSER_SETTING_SCOPE SettingScope
3867 switch (SettingScope
) {
3869 Status
= SubmitForForm (FormSet
, Form
);
3873 Status
= SubmitForFormSet (FormSet
, FALSE
);
3877 Status
= SubmitForSystem ();
3881 Status
= EFI_UNSUPPORTED
;
3889 Converts the unicode character of the string from uppercase to lowercase.
3890 This is a internal function.
3892 @param ConfigString String to be converted
3898 IN EFI_STRING ConfigString
3904 ASSERT (ConfigString
!= NULL
);
3907 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3909 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3910 if (*String
== L
'=') {
3912 } else if (*String
== L
'&') {
3914 } else if (Lower
&& (*String
>= L
'A') && (*String
<= L
'F')) {
3915 *String
= (CHAR16
)(*String
- L
'A' + L
'a');
3921 Find the point in the ConfigResp string for this question.
3923 @param Question The question.
3924 @param ConfigResp Get ConfigResp string.
3926 @retval point to the offset where is for this question.
3930 GetOffsetFromConfigResp (
3931 IN FORM_BROWSER_STATEMENT
*Question
,
3932 IN CHAR16
*ConfigResp
3935 CHAR16
*RequestElement
;
3939 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3941 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3942 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3943 if (RequestElement
!= NULL
) {
3945 // Skip the "VariableName=" field.
3947 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3950 return RequestElement
;
3954 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3958 // Convert all hex digits in ConfigResp to lower case before searching.
3960 HiiToLower (ConfigResp
);
3963 // 1. Directly use Question->BlockName to find.
3965 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3966 if (RequestElement
!= NULL
) {
3968 // Skip the "Question->BlockName&VALUE=" field.
3970 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3971 return RequestElement
;
3975 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3977 BlockData
= AllocateCopyPool (StrSize (Question
->BlockName
), Question
->BlockName
);
3978 ASSERT (BlockData
!= NULL
);
3979 HiiToLower (BlockData
);
3980 RequestElement
= StrStr (ConfigResp
, BlockData
);
3981 FreePool (BlockData
);
3983 if (RequestElement
!= NULL
) {
3985 // Skip the "Question->BlockName&VALUE=" field.
3987 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3990 return RequestElement
;
3994 Get Question default value from AltCfg string.
3996 @param FormSet The form set.
3997 @param Form The form
3998 @param Question The question.
4000 @retval EFI_SUCCESS Question is reset to default value.
4004 GetDefaultValueFromAltCfg (
4005 IN FORM_BROWSER_FORMSET
*FormSet
,
4006 IN FORM_BROWSER_FORM
*Form
,
4007 IN OUT FORM_BROWSER_STATEMENT
*Question
4010 BROWSER_STORAGE
*Storage
;
4011 FORMSET_STORAGE
*FormSetStorage
;
4015 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4017 Storage
= Question
->Storage
;
4018 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4019 return EFI_NOT_FOUND
;
4023 // Try to get AltCfg string from form. If not found it, then
4024 // try to get it from formset.
4027 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4028 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4029 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4030 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4032 if (Storage
== ConfigInfo
->Storage
) {
4033 ConfigResp
= ConfigInfo
->ConfigAltResp
;
4038 if (ConfigResp
== NULL
) {
4039 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4040 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4041 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4042 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4044 if (Storage
== FormSetStorage
->BrowserStorage
) {
4045 ConfigResp
= FormSetStorage
->ConfigAltResp
;
4051 if (ConfigResp
== NULL
) {
4052 return EFI_NOT_FOUND
;
4055 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
4056 if (Value
== NULL
) {
4057 return EFI_NOT_FOUND
;
4060 return BufferToValue (Question
, Value
);
4064 Get default Id value used for browser.
4066 @param DefaultId The default id value used by hii.
4068 @retval Browser used default value.
4072 GetDefaultIdForCallBack (
4076 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
4077 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
4078 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4079 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
4080 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
4081 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
4082 } else if ((DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
) && (DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000)) {
4083 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
4084 } else if ((DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
) && (DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000)) {
4085 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
4086 } else if ((DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
) && (DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000)) {
4087 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
4094 Return data element in an Array by its Index.
4096 @param Array The data array.
4097 @param Type Type of the data in this array.
4098 @param Index Zero based index for data in this array.
4100 @retval Value The data to be returned
4112 ASSERT (Array
!= NULL
);
4116 case EFI_IFR_TYPE_NUM_SIZE_8
:
4117 Data
= (UINT64
)*(((UINT8
*)Array
) + Index
);
4120 case EFI_IFR_TYPE_NUM_SIZE_16
:
4121 Data
= (UINT64
)*(((UINT16
*)Array
) + Index
);
4124 case EFI_IFR_TYPE_NUM_SIZE_32
:
4125 Data
= (UINT64
)*(((UINT32
*)Array
) + Index
);
4128 case EFI_IFR_TYPE_NUM_SIZE_64
:
4129 Data
= (UINT64
)*(((UINT64
*)Array
) + Index
);
4140 Set value of a data element in an Array by its Index.
4142 @param Array The data array.
4143 @param Type Type of the data in this array.
4144 @param Index Zero based index for data in this array.
4145 @param Value The value to be set.
4156 ASSERT (Array
!= NULL
);
4159 case EFI_IFR_TYPE_NUM_SIZE_8
:
4160 *(((UINT8
*)Array
) + Index
) = (UINT8
)Value
;
4163 case EFI_IFR_TYPE_NUM_SIZE_16
:
4164 *(((UINT16
*)Array
) + Index
) = (UINT16
)Value
;
4167 case EFI_IFR_TYPE_NUM_SIZE_32
:
4168 *(((UINT32
*)Array
) + Index
) = (UINT32
)Value
;
4171 case EFI_IFR_TYPE_NUM_SIZE_64
:
4172 *(((UINT64
*)Array
) + Index
) = (UINT64
)Value
;
4181 Search an Option of a Question by its value.
4183 @param Question The Question
4184 @param OptionValue Value for Option to be searched.
4186 @retval Pointer Pointer to the found Option.
4187 @retval NULL Option not found.
4192 IN FORM_BROWSER_STATEMENT
*Question
,
4193 IN EFI_HII_VALUE
*OptionValue
4197 QUESTION_OPTION
*Option
;
4200 Link
= GetFirstNode (&Question
->OptionListHead
);
4201 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4202 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4204 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4206 // Check the suppressif condition, only a valid option can be return.
4208 if ((Option
->SuppressExpression
== NULL
) ||
4209 ((EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
)))
4215 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4222 Reset Question to its default value.
4224 @param FormSet The form set.
4225 @param Form The form.
4226 @param Question The question.
4227 @param DefaultId The Class of the default.
4229 @retval EFI_SUCCESS Question is reset to default value.
4233 GetQuestionDefault (
4234 IN FORM_BROWSER_FORMSET
*FormSet
,
4235 IN FORM_BROWSER_FORM
*Form
,
4236 IN FORM_BROWSER_STATEMENT
*Question
,
4242 QUESTION_DEFAULT
*Default
;
4243 QUESTION_OPTION
*Option
;
4244 EFI_HII_VALUE
*HiiValue
;
4246 EFI_STRING StrValue
;
4247 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4248 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4251 EFI_IFR_TYPE_VALUE
*TypeValue
;
4252 UINT16 OriginalDefaultId
;
4253 FORMSET_DEFAULTSTORE
*DefaultStore
;
4254 LIST_ENTRY
*DefaultLink
;
4256 Status
= EFI_NOT_FOUND
;
4258 OriginalDefaultId
= DefaultId
;
4259 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4262 // Statement don't have storage, skip them
4264 if (Question
->QuestionId
== 0) {
4269 // There are Five ways to specify default value for a Question:
4270 // 1, use call back function (highest priority)
4271 // 2, use ExtractConfig function
4272 // 3, use nested EFI_IFR_DEFAULT
4273 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4274 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4277 HiiValue
= &Question
->HiiValue
;
4278 TypeValue
= &HiiValue
->Value
;
4279 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4281 // For orderedlist, need to pass the BufferValue to Callback function.
4283 TypeValue
= (EFI_IFR_TYPE_VALUE
*)Question
->BufferValue
;
4287 // Get Question defaut value from call back function.
4289 ConfigAccess
= FormSet
->ConfigAccess
;
4290 Action
= GetDefaultIdForCallBack (DefaultId
);
4291 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4292 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4293 Status
= ConfigAccess
->Callback (
4296 Question
->QuestionId
,
4301 if (!EFI_ERROR (Status
)) {
4302 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4303 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4304 ASSERT (NewString
!= NULL
);
4306 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4307 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4308 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4309 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4311 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4314 FreePool (NewString
);
4322 // Get default value from altcfg string.
4324 if (ConfigAccess
!= NULL
) {
4325 Status
= GetDefaultValueFromAltCfg (FormSet
, Form
, Question
);
4326 if (!EFI_ERROR (Status
)) {
4332 // EFI_IFR_DEFAULT has highest priority
4334 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4335 Link
= GetFirstNode (&Question
->DefaultListHead
);
4336 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4337 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4339 if (Default
->DefaultId
== DefaultId
) {
4340 if (Default
->ValueExpression
!= NULL
) {
4342 // Default is provided by an Expression, evaluate it
4344 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4345 if (EFI_ERROR (Status
)) {
4349 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4350 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4351 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4352 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4353 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4355 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4356 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4359 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4362 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4363 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4366 // Default value is embedded in EFI_IFR_DEFAULT
4368 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4369 ASSERT (HiiValue
->Buffer
!= NULL
);
4370 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4372 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4376 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4377 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4378 if (StrValue
== NULL
) {
4379 return EFI_NOT_FOUND
;
4382 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4383 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4384 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4386 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4393 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4398 // EFI_ONE_OF_OPTION
4400 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4401 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4403 // OneOfOption could only provide Standard and Manufacturing default
4405 Link
= GetFirstNode (&Question
->OptionListHead
);
4406 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4407 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4408 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4410 if ((Option
->SuppressExpression
!= NULL
) &&
4411 (EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
))
4416 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4417 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4420 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4429 // EFI_IFR_CHECKBOX - lowest priority
4431 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4432 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4434 // Checkbox could only provide Standard and Manufacturing default
4436 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4437 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4440 HiiValue
->Value
.b
= TRUE
;
4448 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4449 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4450 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4452 while (!IsNull (&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4453 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink
);
4454 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
, DefaultLink
);
4455 DefaultId
= DefaultStore
->DefaultId
;
4456 if (DefaultId
== OriginalDefaultId
) {
4464 // For Questions without default value for all the default id in the DefaultStoreList.
4466 Status
= EFI_NOT_FOUND
;
4467 switch (Question
->Operand
) {
4468 case EFI_IFR_CHECKBOX_OP
:
4469 HiiValue
->Value
.b
= FALSE
;
4470 Status
= EFI_SUCCESS
;
4473 case EFI_IFR_NUMERIC_OP
:
4475 // Take minimum value as numeric default value
4477 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4479 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4481 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4482 case EFI_IFR_NUMERIC_SIZE_1
:
4483 if (((INT8
)HiiValue
->Value
.u8
< (INT8
)Question
->Minimum
) || ((INT8
)HiiValue
->Value
.u8
> (INT8
)Question
->Maximum
)) {
4484 HiiValue
->Value
.u8
= (UINT8
)Question
->Minimum
;
4485 Status
= EFI_SUCCESS
;
4489 case EFI_IFR_NUMERIC_SIZE_2
:
4490 if (((INT16
)HiiValue
->Value
.u16
< (INT16
)Question
->Minimum
) || ((INT16
)HiiValue
->Value
.u16
> (INT16
)Question
->Maximum
)) {
4491 HiiValue
->Value
.u16
= (UINT16
)Question
->Minimum
;
4492 Status
= EFI_SUCCESS
;
4496 case EFI_IFR_NUMERIC_SIZE_4
:
4497 if (((INT32
)HiiValue
->Value
.u32
< (INT32
)Question
->Minimum
) || ((INT32
)HiiValue
->Value
.u32
> (INT32
)Question
->Maximum
)) {
4498 HiiValue
->Value
.u32
= (UINT32
)Question
->Minimum
;
4499 Status
= EFI_SUCCESS
;
4503 case EFI_IFR_NUMERIC_SIZE_8
:
4504 if (((INT64
)HiiValue
->Value
.u64
< (INT64
)Question
->Minimum
) || ((INT64
)HiiValue
->Value
.u64
> (INT64
)Question
->Maximum
)) {
4505 HiiValue
->Value
.u64
= Question
->Minimum
;
4506 Status
= EFI_SUCCESS
;
4514 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4515 HiiValue
->Value
.u64
= Question
->Minimum
;
4516 Status
= EFI_SUCCESS
;
4522 case EFI_IFR_ONE_OF_OP
:
4524 // Take first oneof option as oneof's default value
4526 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4527 Link
= GetFirstNode (&Question
->OptionListHead
);
4528 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4529 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4530 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4532 if ((Option
->SuppressExpression
!= NULL
) &&
4533 (EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
))
4538 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4539 Status
= EFI_SUCCESS
;
4546 case EFI_IFR_ORDERED_LIST_OP
:
4548 // Take option sequence in IFR as ordered list's default value
4551 Link
= GetFirstNode (&Question
->OptionListHead
);
4552 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4553 Status
= EFI_SUCCESS
;
4554 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4555 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4557 if ((Option
->SuppressExpression
!= NULL
) &&
4558 (EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
))
4563 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4566 if (Index
>= Question
->MaxContainers
) {
4581 Get AltCfg string for current form.
4583 @param FormSet Form data structure.
4584 @param Form Form data structure.
4585 @param DefaultId The Class of the default.
4586 @param BrowserStorage The input request storage for the questions.
4590 ExtractAltCfgForForm (
4591 IN FORM_BROWSER_FORMSET
*FormSet
,
4592 IN FORM_BROWSER_FORM
*Form
,
4593 IN UINT16 DefaultId
,
4594 IN BROWSER_STORAGE
*BrowserStorage
4602 BROWSER_STORAGE
*Storage
;
4603 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4604 FORMSET_STORAGE
*FormSetStorage
;
4607 // Check whether has get AltCfg string for this formset.
4608 // If yes, no need to get AltCfg for form.
4610 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4611 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4612 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4613 Storage
= FormSetStorage
->BrowserStorage
;
4614 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4615 if ((BrowserStorage
!= NULL
) && (BrowserStorage
!= Storage
)) {
4619 if ((Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
) &&
4620 (FormSetStorage
->ElementCount
!= 0) &&
4621 FormSetStorage
->HasCallAltCfg
)
4628 // Get AltCfg string for each form.
4630 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4631 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4632 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4633 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4635 Storage
= ConfigInfo
->Storage
;
4636 if ((BrowserStorage
!= NULL
) && (BrowserStorage
!= Storage
)) {
4640 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4645 // 1. Skip if there is no RequestElement
4647 if (ConfigInfo
->ElementCount
== 0) {
4652 // 2. Get value through hii config routine protocol.
4654 Status
= mHiiConfigRouting
->ExtractConfig (
4656 ConfigInfo
->ConfigRequest
,
4660 if (EFI_ERROR (Status
)) {
4665 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4666 // Get the default configuration string according to the default ID.
4668 Status
= mHiiConfigRouting
->GetAltConfig (
4674 &DefaultId
, // it can be NULL to get the current setting.
4678 if (EFI_ERROR (Status
)) {
4682 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4687 Clean AltCfg string for current form.
4689 @param Form Form data structure.
4693 CleanAltCfgForForm (
4694 IN FORM_BROWSER_FORM
*Form
4698 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4700 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4701 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4702 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4703 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4705 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4706 FreePool (ConfigInfo
->ConfigAltResp
);
4707 ConfigInfo
->ConfigAltResp
= NULL
;
4713 Get AltCfg string for current formset.
4715 @param FormSet Form data structure.
4716 @param DefaultId The Class of the default.
4717 @param BrowserStorage The input request storage for the questions.
4721 ExtractAltCfgForFormSet (
4722 IN FORM_BROWSER_FORMSET
*FormSet
,
4723 IN UINT16 DefaultId
,
4724 IN BROWSER_STORAGE
*BrowserStorage
4732 BROWSER_STORAGE
*Storage
;
4733 FORMSET_STORAGE
*FormSetStorage
;
4735 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4736 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4737 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4738 Storage
= FormSetStorage
->BrowserStorage
;
4739 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4741 if ((BrowserStorage
!= NULL
) && (BrowserStorage
!= Storage
)) {
4745 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4750 // 1. Skip if there is no RequestElement
4752 if (FormSetStorage
->ElementCount
== 0) {
4756 FormSetStorage
->HasCallAltCfg
= TRUE
;
4759 // 2. Get value through hii config routine protocol.
4761 Status
= mHiiConfigRouting
->ExtractConfig (
4763 FormSetStorage
->ConfigRequest
,
4767 if (EFI_ERROR (Status
)) {
4772 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4773 // Get the default configuration string according to the default ID.
4775 Status
= mHiiConfigRouting
->GetAltConfig (
4781 &DefaultId
, // it can be NULL to get the current setting.
4786 if (EFI_ERROR (Status
)) {
4790 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4795 Clean AltCfg string for current formset.
4797 @param FormSet Form data structure.
4801 CleanAltCfgForFormSet (
4802 IN FORM_BROWSER_FORMSET
*FormSet
4806 FORMSET_STORAGE
*FormSetStorage
;
4808 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4809 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4810 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4811 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4813 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4814 FreePool (FormSetStorage
->ConfigAltResp
);
4815 FormSetStorage
->ConfigAltResp
= NULL
;
4818 FormSetStorage
->HasCallAltCfg
= FALSE
;
4823 Reset Questions to their initial value or default value in a Form, Formset or System.
4825 GetDefaultValueScope parameter decides which questions will reset
4826 to its default value.
4828 @param FormSet FormSet data structure.
4829 @param Form Form data structure.
4830 @param DefaultId The Class of the default.
4831 @param SettingScope Setting Scope for Default action.
4832 @param GetDefaultValueScope Get default value scope.
4833 @param Storage Get default value only for this storage.
4834 @param RetrieveValueFirst Whether call the retrieve call back to
4835 get the initial value before get default
4837 @param SkipGetAltCfg Whether skip the get altcfg string process.
4839 @retval EFI_SUCCESS The function completed successfully.
4840 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4845 IN FORM_BROWSER_FORMSET
*FormSet
,
4846 IN FORM_BROWSER_FORM
*Form
,
4847 IN UINT16 DefaultId
,
4848 IN BROWSER_SETTING_SCOPE SettingScope
,
4849 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4850 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4851 IN BOOLEAN RetrieveValueFirst
,
4852 IN BOOLEAN SkipGetAltCfg
4856 LIST_ENTRY
*FormLink
;
4858 FORM_BROWSER_STATEMENT
*Question
;
4859 FORM_BROWSER_FORMSET
*LocalFormSet
;
4860 FORM_BROWSER_FORMSET
*OldFormSet
;
4862 Status
= EFI_SUCCESS
;
4865 // Check the supported setting level.
4867 if ((SettingScope
>= MaxLevel
) || (GetDefaultValueScope
>= GetDefaultForMax
)) {
4868 return EFI_UNSUPPORTED
;
4871 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Storage
== NULL
)) {
4872 return EFI_UNSUPPORTED
;
4875 if (SettingScope
== FormLevel
) {
4877 // Prepare the AltCfg String for form.
4879 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4880 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4884 // Extract Form default
4886 Link
= GetFirstNode (&Form
->StatementListHead
);
4887 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4888 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4889 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4892 // If get default value only for this storage, check the storage first.
4894 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4899 // If get default value only for no storage question, just skip the question which has storage.
4901 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4906 // If Question is disabled, don't reset it to default
4908 if (Question
->Expression
!= NULL
) {
4909 if (EvaluateExpressionList (Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4914 if (RetrieveValueFirst
) {
4916 // Call the Retrieve call back to get the initial question value.
4918 Status
= ProcessRetrieveForQuestion (FormSet
->ConfigAccess
, Question
, FormSet
);
4922 // If not request to get the initial value or get initial value fail, then get default value.
4924 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4925 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4926 if (EFI_ERROR (Status
)) {
4932 // Synchronize Buffer storage's Edit buffer
4934 if ((Question
->Storage
!= NULL
) &&
4935 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
))
4937 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4942 // Clean the AltCfg String.
4944 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4945 CleanAltCfgForForm (Form
);
4947 } else if (SettingScope
== FormSetLevel
) {
4949 // Prepare the AltCfg String for formset.
4951 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4952 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4955 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4956 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4957 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4958 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4959 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4963 // Clean the AltCfg String.
4965 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4966 CleanAltCfgForFormSet (FormSet
);
4968 } else if (SettingScope
== SystemLevel
) {
4970 // Preload all Hii formset.
4972 LoadAllHiiFormset ();
4974 OldFormSet
= mSystemLevelFormSet
;
4977 // Set Default Value for each FormSet in the maintain list.
4979 Link
= GetFirstNode (&gBrowserFormSetList
);
4980 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4981 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4982 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4983 if (!ValidateFormSet (LocalFormSet
)) {
4987 mSystemLevelFormSet
= LocalFormSet
;
4989 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4992 mSystemLevelFormSet
= OldFormSet
;
4999 Validate whether this question's value has changed.
5001 @param FormSet FormSet data structure.
5002 @param Form Form data structure.
5003 @param Question Question to be initialized.
5004 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
5006 @retval TRUE Question's value has changed.
5007 @retval FALSE Question's value has not changed
5011 IsQuestionValueChanged (
5012 IN FORM_BROWSER_FORMSET
*FormSet
,
5013 IN FORM_BROWSER_FORM
*Form
,
5014 IN OUT FORM_BROWSER_STATEMENT
*Question
,
5015 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
5018 EFI_HII_VALUE BackUpValue
;
5019 CHAR8
*BackUpBuffer
;
5020 EFI_HII_VALUE BackUpValue2
;
5021 CHAR8
*BackUpBuffer2
;
5023 BOOLEAN ValueChanged
;
5027 // For quetion without storage, always mark it as data not changed.
5029 if ((Question
->Storage
== NULL
) && (Question
->Operand
!= EFI_IFR_TIME_OP
) && (Question
->Operand
!= EFI_IFR_DATE_OP
)) {
5033 BackUpBuffer
= NULL
;
5034 BackUpBuffer2
= NULL
;
5035 ValueChanged
= FALSE
;
5037 switch (Question
->Operand
) {
5038 case EFI_IFR_ORDERED_LIST_OP
:
5039 BufferWidth
= Question
->StorageWidth
;
5040 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5041 ASSERT (BackUpBuffer
!= NULL
);
5044 case EFI_IFR_STRING_OP
:
5045 case EFI_IFR_PASSWORD_OP
:
5046 BufferWidth
= (UINTN
)Question
->Maximum
* sizeof (CHAR16
);
5047 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5048 ASSERT (BackUpBuffer
!= NULL
);
5056 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5058 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
5059 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5060 ASSERT_EFI_ERROR (Status
);
5062 switch (Question
->Operand
) {
5063 case EFI_IFR_ORDERED_LIST_OP
:
5064 BufferWidth
= Question
->StorageWidth
;
5065 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5066 ASSERT (BackUpBuffer2
!= NULL
);
5069 case EFI_IFR_STRING_OP
:
5070 case EFI_IFR_PASSWORD_OP
:
5071 BufferWidth
= (UINTN
)Question
->Maximum
* sizeof (CHAR16
);
5072 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5073 ASSERT (BackUpBuffer2
!= NULL
);
5081 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5083 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
5084 ASSERT_EFI_ERROR (Status
);
5086 if ((CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0) ||
5087 (CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0))
5089 ValueChanged
= TRUE
;
5092 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
5093 ASSERT_EFI_ERROR (Status
);
5095 if ((CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0) ||
5096 (CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0))
5098 ValueChanged
= TRUE
;
5102 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
5103 if (BackUpBuffer
!= NULL
) {
5104 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
5105 FreePool (BackUpBuffer
);
5108 if (BackUpBuffer2
!= NULL
) {
5109 FreePool (BackUpBuffer2
);
5112 Question
->ValueChanged
= ValueChanged
;
5114 return ValueChanged
;
5118 Initialize Question's Edit copy from Storage.
5120 @param Selection Selection contains the information about
5121 the Selection, form and formset to be displayed.
5122 Selection action may be updated in retrieve callback.
5123 If Selection is NULL, only initialize Question value.
5124 @param FormSet FormSet data structure.
5125 @param Form Form data structure.
5127 @retval EFI_SUCCESS The function completed successfully.
5132 IN OUT UI_MENU_SELECTION
*Selection
,
5133 IN FORM_BROWSER_FORMSET
*FormSet
,
5134 IN FORM_BROWSER_FORM
*Form
5139 FORM_BROWSER_STATEMENT
*Question
;
5141 Link
= GetFirstNode (&Form
->StatementListHead
);
5142 while (!IsNull (&Form
->StatementListHead
, Link
)) {
5143 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
5146 // Initialize local copy of Value for each Question
5148 if ((Question
->Operand
== EFI_IFR_PASSWORD_OP
) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == 0)) {
5149 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
5151 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5154 if (EFI_ERROR (Status
)) {
5158 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5159 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5162 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5169 Initialize Question's Edit copy from Storage for the whole Formset.
5171 @param Selection Selection contains the information about
5172 the Selection, form and formset to be displayed.
5173 Selection action may be updated in retrieve callback.
5174 If Selection is NULL, only initialize Question value.
5175 @param FormSet FormSet data structure.
5177 @retval EFI_SUCCESS The function completed successfully.
5182 IN OUT UI_MENU_SELECTION
*Selection
,
5183 IN FORM_BROWSER_FORMSET
*FormSet
5188 FORM_BROWSER_FORM
*Form
;
5190 Link
= GetFirstNode (&FormSet
->FormListHead
);
5191 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5192 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5195 // Initialize local copy of Value for each Form
5197 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5198 if (EFI_ERROR (Status
)) {
5202 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5206 // Finished question initialization.
5208 FormSet
->QuestionInited
= TRUE
;
5214 Remove the Request element from the Config Request.
5216 @param Storage Pointer to the browser storage.
5217 @param RequestElement The pointer to the Request element.
5222 IN OUT BROWSER_STORAGE
*Storage
,
5223 IN CHAR16
*RequestElement
5229 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5231 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5233 if (NewStr
== NULL
) {
5238 // Remove this element from this ConfigRequest.
5241 NewStr
+= StrLen (RequestElement
);
5242 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5244 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5248 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5250 @param Storage Pointer to the formset storage.
5251 @param ConfigRequest The pointer to the Request element.
5255 RemoveConfigRequest (
5256 FORMSET_STORAGE
*Storage
,
5257 CHAR16
*ConfigRequest
5260 CHAR16
*RequestElement
;
5261 CHAR16
*NextRequestElement
;
5265 // No request element in it, just return.
5267 if (ConfigRequest
== NULL
) {
5271 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5273 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5278 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5280 SearchKey
= L
"&OFFSET";
5284 // Find SearchKey storage
5286 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5287 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5288 ASSERT (RequestElement
!= NULL
);
5289 RequestElement
= StrStr (RequestElement
, SearchKey
);
5291 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5294 while (RequestElement
!= NULL
) {
5296 // +1 to avoid find header itself.
5298 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5301 // The last Request element in configRequest string.
5303 if (NextRequestElement
!= NULL
) {
5305 // Replace "&" with '\0'.
5307 *NextRequestElement
= L
'\0';
5310 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5312 if (NextRequestElement
!= NULL
) {
5314 // Restore '&' with '\0' for later used.
5316 *NextRequestElement
= L
'&';
5319 RequestElement
= NextRequestElement
;
5323 // If no request element remain, just remove the ConfigRequest string.
5325 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5326 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5327 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5328 Storage
->BrowserStorage
->SpareStrLen
= 0;
5333 Base on the current formset info, clean the ConfigRequest string in browser storage.
5335 @param FormSet Pointer of the FormSet
5339 CleanBrowserStorage (
5340 IN OUT FORM_BROWSER_FORMSET
*FormSet
5344 FORMSET_STORAGE
*Storage
;
5346 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5347 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5348 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5349 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5351 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5352 if ((Storage
->ConfigRequest
== NULL
) || (Storage
->BrowserStorage
->ConfigRequest
== NULL
)) {
5356 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5357 } else if ((Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
5358 (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
))
5360 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5361 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5362 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5365 Storage
->BrowserStorage
->Initialized
= FALSE
;
5371 Check whether current element in the ConfigReqeust string.
5373 @param BrowserStorage Storage which includes ConfigReqeust.
5374 @param RequestElement New element need to check.
5376 @retval TRUE The Element is in the ConfigReqeust string.
5377 @retval FALSE The Element not in the configReqeust String.
5382 BROWSER_STORAGE
*BrowserStorage
,
5383 CHAR16
*RequestElement
5386 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5390 Append the Request element to the Config Request.
5392 @param ConfigRequest Current ConfigRequest info.
5393 @param SpareStrLen Current remain free buffer for config reqeust.
5394 @param RequestElement New Request element.
5398 AppendConfigRequest (
5399 IN OUT CHAR16
**ConfigRequest
,
5400 IN OUT UINTN
*SpareStrLen
,
5401 IN CHAR16
*RequestElement
5409 StrLength
= StrLen (RequestElement
);
5410 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5411 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5414 // Append <RequestElement> to <ConfigRequest>
5416 if (StrLength
> *SpareStrLen
) {
5418 // Old String buffer is not sufficient for RequestElement, allocate a new one
5420 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5421 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5422 ASSERT (NewStr
!= NULL
);
5424 if (*ConfigRequest
!= NULL
) {
5425 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5426 FreePool (*ConfigRequest
);
5429 *ConfigRequest
= NewStr
;
5430 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5433 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5434 *SpareStrLen
-= StrLength
;
5438 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5440 @param Storage Form set Storage.
5441 @param Request The input request string.
5442 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5444 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5445 @retval FALSE All elements covered by current used elements.
5449 ConfigRequestAdjust (
5450 IN BROWSER_STORAGE
*Storage
,
5452 IN BOOLEAN RespString
5455 CHAR16
*RequestElement
;
5456 CHAR16
*NextRequestElement
;
5457 CHAR16
*NextElementBakup
;
5461 CHAR16
*ConfigRequest
;
5464 NextElementBakup
= NULL
;
5467 if (Request
!= NULL
) {
5468 ConfigRequest
= Request
;
5470 ConfigRequest
= Storage
->ConfigRequest
;
5473 if (Storage
->ConfigRequest
== NULL
) {
5474 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5478 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5480 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5485 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5487 SearchKey
= L
"&OFFSET";
5488 ValueKey
= L
"&VALUE";
5492 // Find SearchKey storage
5494 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5495 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5496 ASSERT (RequestElement
!= NULL
);
5497 RequestElement
= StrStr (RequestElement
, SearchKey
);
5499 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5502 while (RequestElement
!= NULL
) {
5504 // +1 to avoid find header itself.
5506 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5509 // The last Request element in configRequest string.
5511 if (NextRequestElement
!= NULL
) {
5512 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5513 NextElementBakup
= NextRequestElement
;
5514 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5515 ASSERT (NextRequestElement
!= NULL
);
5519 // Replace "&" with '\0'.
5521 *NextRequestElement
= L
'\0';
5523 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5524 NextElementBakup
= NextRequestElement
;
5525 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5526 ASSERT (NextRequestElement
!= NULL
);
5528 // Replace "&" with '\0'.
5530 *NextRequestElement
= L
'\0';
5534 if (!ElementValidation (Storage
, RequestElement
)) {
5536 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5538 AppendConfigRequest (&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5542 if (NextRequestElement
!= NULL
) {
5544 // Restore '&' with '\0' for later used.
5546 *NextRequestElement
= L
'&';
5549 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5550 RequestElement
= NextElementBakup
;
5552 RequestElement
= NextRequestElement
;
5560 Fill storage's edit copy with settings requested from Configuration Driver.
5562 @param FormSet FormSet data structure.
5563 @param Storage Buffer Storage.
5568 IN FORM_BROWSER_FORMSET
*FormSet
,
5569 IN FORMSET_STORAGE
*Storage
5573 EFI_STRING Progress
;
5576 EFI_STRING ConfigRequest
;
5579 ConfigRequest
= NULL
;
5581 switch (Storage
->BrowserStorage
->Type
) {
5582 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5585 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5586 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5587 ConfigRequestAdjust (Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5593 case EFI_HII_VARSTORE_BUFFER
:
5594 case EFI_HII_VARSTORE_NAME_VALUE
:
5596 // Skip if there is no RequestElement.
5598 if (Storage
->ElementCount
== 0) {
5603 // Just update the ConfigRequest, if storage already initialized.
5605 if (Storage
->BrowserStorage
->Initialized
) {
5606 ConfigRequestAdjust (Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5610 Storage
->BrowserStorage
->Initialized
= TRUE
;
5617 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5619 // Create the config request string to get all fields for this storage.
5620 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5621 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5623 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5624 ConfigRequest
= AllocateZeroPool (StrLen
);
5625 ASSERT (ConfigRequest
!= NULL
);
5629 L
"%s&OFFSET=0&WIDTH=%04x",
5631 Storage
->BrowserStorage
->Size
5634 ConfigRequest
= Storage
->ConfigRequest
;
5638 // Request current settings from Configuration Driver
5640 Status
= mHiiConfigRouting
->ExtractConfig (
5648 // If get value fail, extract default from IFR binary
5650 if (EFI_ERROR (Status
)) {
5651 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5654 // Convert Result from <ConfigAltResp> to <ConfigResp>
5656 StrPtr
= StrStr (Result
, L
"&GUID=");
5657 if (StrPtr
!= NULL
) {
5661 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5665 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5668 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5670 SynchronizeStorage (Storage
->BrowserStorage
, NULL
, TRUE
);
5672 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5673 if (ConfigRequest
!= NULL
) {
5674 FreePool (ConfigRequest
);
5680 Get Value changed status from old question.
5682 @param NewFormSet FormSet data structure.
5683 @param OldQuestion Old question which has value changed.
5687 SyncStatusForQuestion (
5688 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5689 IN FORM_BROWSER_STATEMENT
*OldQuestion
5693 LIST_ENTRY
*QuestionLink
;
5694 FORM_BROWSER_FORM
*Form
;
5695 FORM_BROWSER_STATEMENT
*Question
;
5698 // For each form in one formset.
5700 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5701 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5702 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5703 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5706 // for each question in one form.
5708 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5709 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5710 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5711 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5713 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5714 Question
->ValueChanged
= TRUE
;
5722 Get Value changed status from old formset.
5724 @param NewFormSet FormSet data structure.
5725 @param OldFormSet FormSet data structure.
5729 SyncStatusForFormSet (
5730 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5731 IN FORM_BROWSER_FORMSET
*OldFormSet
5735 LIST_ENTRY
*QuestionLink
;
5736 FORM_BROWSER_FORM
*Form
;
5737 FORM_BROWSER_STATEMENT
*Question
;
5740 // For each form in one formset.
5742 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5743 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5744 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5745 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5748 // for each question in one form.
5750 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5751 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5752 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5753 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5755 if (!Question
->ValueChanged
) {
5760 // Find the same question in new formset and update the value changed flag.
5762 SyncStatusForQuestion (NewFormSet
, Question
);
5768 Get current setting of Questions.
5770 @param FormSet FormSet data structure.
5774 InitializeCurrentSetting (
5775 IN OUT FORM_BROWSER_FORMSET
*FormSet
5779 FORMSET_STORAGE
*Storage
;
5780 FORM_BROWSER_FORMSET
*OldFormSet
;
5783 // Try to find pre FormSet in the maintain backup list.
5784 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5786 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5787 if (OldFormSet
!= NULL
) {
5788 SyncStatusForFormSet (FormSet
, OldFormSet
);
5789 RemoveEntryList (&OldFormSet
->Link
);
5790 DestroyFormSet (OldFormSet
);
5793 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5796 // Extract default from IFR binary for no storage questions.
5798 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5801 // Request current settings from Configuration Driver
5803 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5804 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5805 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5807 LoadStorage (FormSet
, Storage
);
5809 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5814 Fetch the Ifr binary data of a FormSet.
5816 @param Handle PackageList Handle
5817 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5818 specified (NULL or zero GUID), take the first
5819 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5820 found in package list.
5821 On output, GUID of the formset found(if not NULL).
5822 @param BinaryLength The length of the FormSet IFR binary.
5823 @param BinaryData The buffer designed to receive the FormSet.
5825 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5826 BufferLength was updated.
5827 @retval EFI_INVALID_PARAMETER The handle is unknown.
5828 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5829 be found with the requested FormId.
5834 IN EFI_HII_HANDLE Handle
,
5835 IN OUT EFI_GUID
*FormSetGuid
,
5836 OUT UINTN
*BinaryLength
,
5837 OUT UINT8
**BinaryData
5841 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5847 UINT32 PackageListLength
;
5848 EFI_HII_PACKAGE_HEADER PackageHeader
;
5850 UINT8 NumberOfClassGuid
;
5851 BOOLEAN ClassGuidMatch
;
5852 EFI_GUID
*ClassGuid
;
5853 EFI_GUID
*ComparingGuid
;
5857 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5860 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5862 if (FormSetGuid
== NULL
) {
5863 ComparingGuid
= &gZeroGuid
;
5865 ComparingGuid
= FormSetGuid
;
5869 // Get HII PackageList
5872 HiiPackageList
= NULL
;
5873 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5874 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5875 HiiPackageList
= AllocatePool (BufferSize
);
5876 ASSERT (HiiPackageList
!= NULL
);
5878 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5881 if (EFI_ERROR (Status
)) {
5885 ASSERT (HiiPackageList
!= NULL
);
5888 // Get Form package from this HII package List
5890 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5892 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5894 ClassGuidMatch
= FALSE
;
5895 while (Offset
< PackageListLength
) {
5896 Package
= ((UINT8
*)HiiPackageList
) + Offset
;
5897 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5899 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5901 // Search FormSet in this Form Package
5903 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5904 while (Offset2
< PackageHeader
.Length
) {
5905 OpCodeData
= Package
+ Offset2
;
5907 if (((EFI_IFR_OP_HEADER
*)OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5909 // Try to compare against formset GUID
5911 if (IsZeroGuid (ComparingGuid
) ||
5912 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
))))
5917 if (((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5919 // Try to compare against formset class GUID
5921 NumberOfClassGuid
= (UINT8
)(((EFI_IFR_FORM_SET
*)OpCodeData
)->Flags
& 0x3);
5922 ClassGuid
= (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5923 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5924 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5925 ClassGuidMatch
= TRUE
;
5930 if (ClassGuidMatch
) {
5933 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5934 ClassGuidMatch
= TRUE
;
5939 Offset2
+= ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
;
5942 if (Offset2
< PackageHeader
.Length
) {
5944 // Target formset found
5950 Offset
+= PackageHeader
.Length
;
5953 if (Offset
>= PackageListLength
) {
5955 // Form package not found in this Package List
5957 FreePool (HiiPackageList
);
5958 return EFI_NOT_FOUND
;
5961 if (FormSetGuid
!= NULL
) {
5963 // Return the FormSet GUID
5965 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*)OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5969 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5970 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5971 // of the Form Package.
5973 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5974 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5976 FreePool (HiiPackageList
);
5978 if (*BinaryData
== NULL
) {
5979 return EFI_OUT_OF_RESOURCES
;
5986 Initialize the internal data structure of a FormSet.
5988 @param Handle PackageList Handle
5989 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5990 specified (NULL or zero GUID), take the first
5991 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5992 found in package list.
5993 On output, GUID of the formset found(if not NULL).
5994 @param FormSet FormSet data structure.
5996 @retval EFI_SUCCESS The function completed successfully.
5997 @retval EFI_NOT_FOUND The specified FormSet could not be found.
6002 IN EFI_HII_HANDLE Handle
,
6003 IN OUT EFI_GUID
*FormSetGuid
,
6004 OUT FORM_BROWSER_FORMSET
*FormSet
6008 EFI_HANDLE DriverHandle
;
6010 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
6011 if (EFI_ERROR (Status
)) {
6015 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
6016 FormSet
->HiiHandle
= Handle
;
6017 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
6018 FormSet
->QuestionInited
= FALSE
;
6021 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
6023 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
6024 if (EFI_ERROR (Status
)) {
6028 FormSet
->DriverHandle
= DriverHandle
;
6029 Status
= gBS
->HandleProtocol (
6031 &gEfiHiiConfigAccessProtocolGuid
,
6032 (VOID
**)&FormSet
->ConfigAccess
6034 if (EFI_ERROR (Status
)) {
6036 // Configuration Driver don't attach ConfigAccess protocol to its HII package
6037 // list, then there will be no configuration action required
6039 FormSet
->ConfigAccess
= NULL
;
6043 // Parse the IFR binary OpCodes
6045 Status
= ParseOpCodes (FormSet
);
6051 Save globals used by previous call to SendForm(). SendForm() may be called from
6052 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
6053 So, save globals of previous call to SendForm() and restore them upon exit.
6057 SaveBrowserContext (
6061 BROWSER_CONTEXT
*Context
;
6062 FORM_ENTRY_INFO
*MenuList
;
6063 FORM_BROWSER_FORMSET
*FormSet
;
6065 gBrowserContextCount
++;
6066 if (gBrowserContextCount
== 1) {
6068 // This is not reentry of SendForm(), no context to save
6073 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
6074 ASSERT (Context
!= NULL
);
6076 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
6079 // Save FormBrowser context
6081 Context
->Selection
= gCurrentSelection
;
6082 Context
->ResetRequired
= gResetRequiredFormLevel
;
6083 Context
->FlagReconnect
= gFlagReconnect
;
6084 Context
->CallbackReconnect
= gCallbackReconnect
;
6085 Context
->ExitRequired
= gExitRequired
;
6086 Context
->HiiHandle
= mCurrentHiiHandle
;
6087 Context
->FormId
= mCurrentFormId
;
6088 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
6089 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
6090 Context
->CurFakeQestId
= mCurFakeQestId
;
6091 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
6092 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
6095 // Save the menu history data.
6097 InitializeListHead (&Context
->FormHistoryList
);
6098 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
6099 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
6100 RemoveEntryList (&MenuList
->Link
);
6102 InsertTailList (&Context
->FormHistoryList
, &MenuList
->Link
);
6106 // Save formset list.
6108 InitializeListHead (&Context
->FormSetList
);
6109 while (!IsListEmpty (&gBrowserFormSetList
)) {
6110 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
6111 RemoveEntryList (&FormSet
->Link
);
6113 InsertTailList (&Context
->FormSetList
, &FormSet
->Link
);
6117 // Insert to FormBrowser context list
6119 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
6123 Restore globals used by previous call to SendForm().
6127 RestoreBrowserContext (
6132 BROWSER_CONTEXT
*Context
;
6133 FORM_ENTRY_INFO
*MenuList
;
6134 FORM_BROWSER_FORMSET
*FormSet
;
6136 ASSERT (gBrowserContextCount
!= 0);
6137 gBrowserContextCount
--;
6138 if (gBrowserContextCount
== 0) {
6140 // This is not reentry of SendForm(), no context to restore
6145 ASSERT (!IsListEmpty (&gBrowserContextList
));
6147 Link
= GetFirstNode (&gBrowserContextList
);
6148 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6151 // Restore FormBrowser context
6153 gCurrentSelection
= Context
->Selection
;
6154 gResetRequiredFormLevel
= Context
->ResetRequired
;
6155 gFlagReconnect
= Context
->FlagReconnect
;
6156 gCallbackReconnect
= Context
->CallbackReconnect
;
6157 gExitRequired
= Context
->ExitRequired
;
6158 mCurrentHiiHandle
= Context
->HiiHandle
;
6159 mCurrentFormId
= Context
->FormId
;
6160 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6161 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6162 mCurFakeQestId
= Context
->CurFakeQestId
;
6163 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6164 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6167 // Restore the menu history data.
6169 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6170 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6171 RemoveEntryList (&MenuList
->Link
);
6173 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6177 // Restore the Formset data.
6179 while (!IsListEmpty (&Context
->FormSetList
)) {
6180 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6181 RemoveEntryList (&FormSet
->Link
);
6183 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
6187 // Remove from FormBrowser context list
6189 RemoveEntryList (&Context
->Link
);
6190 gBS
->FreePool (Context
);
6194 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6196 @param Handle The Hii Handle.
6198 @return the found FormSet context. If no found, NULL will return.
6201 FORM_BROWSER_FORMSET
*
6202 GetFormSetFromHiiHandle (
6203 EFI_HII_HANDLE Handle
6207 FORM_BROWSER_FORMSET
*FormSet
;
6209 Link
= GetFirstNode (&gBrowserFormSetList
);
6210 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6211 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6212 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6213 if (!ValidateFormSet (FormSet
)) {
6217 if (FormSet
->HiiHandle
== Handle
) {
6226 Check whether the input HII handle is the FormSet that is being used.
6228 @param Handle The Hii Handle.
6230 @retval TRUE HII handle is being used.
6231 @retval FALSE HII handle is not being used.
6235 IsHiiHandleInBrowserContext (
6236 EFI_HII_HANDLE Handle
6240 BROWSER_CONTEXT
*Context
;
6243 // HiiHandle is Current FormSet.
6245 if (mCurrentHiiHandle
== Handle
) {
6250 // Check whether HiiHandle is in BrowserContext.
6252 Link
= GetFirstNode (&gBrowserContextList
);
6253 while (!IsNull (&gBrowserContextList
, Link
)) {
6254 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6255 if (Context
->HiiHandle
== Handle
) {
6257 // HiiHandle is in BrowserContext
6262 Link
= GetNextNode (&gBrowserContextList
, Link
);
6269 Perform Password check.
6270 Passwork may be encrypted by driver that requires the specific check.
6272 @param Form Form where Password Statement is in.
6273 @param Statement Password statement
6274 @param PasswordString Password string to be checked. It may be NULL.
6275 NULL means to restore password.
6276 "" string can be used to checked whether old password does exist.
6278 @return Status Status of Password check.
6283 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6284 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6285 IN EFI_STRING PasswordString OPTIONAL
6289 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6290 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6291 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6292 FORM_BROWSER_STATEMENT
*Question
;
6294 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6295 Question
= GetBrowserStatement (Statement
);
6296 ASSERT (Question
!= NULL
);
6298 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6299 if (ConfigAccess
== NULL
) {
6300 return EFI_UNSUPPORTED
;
6304 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6306 return EFI_UNSUPPORTED
;
6310 // Prepare password string in HII database
6312 if (PasswordString
!= NULL
) {
6313 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6315 IfrTypeValue
.string
= 0;
6319 // Send password to Configuration Driver for validation
6321 Status
= ConfigAccess
->Callback (
6323 EFI_BROWSER_ACTION_CHANGING
,
6324 Question
->QuestionId
,
6325 Question
->HiiValue
.Type
,
6331 // Remove password string from HII database
6333 if (PasswordString
!= NULL
) {
6334 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6341 Find the registered HotKey based on KeyData.
6343 @param[in] KeyData A pointer to a buffer that describes the keystroke
6344 information for the hot key.
6346 @return The registered HotKey context. If no found, NULL will return.
6349 GetHotKeyFromRegisterList (
6350 IN EFI_INPUT_KEY
*KeyData
6354 BROWSER_HOT_KEY
*HotKey
;
6356 Link
= GetFirstNode (&gBrowserHotKeyList
);
6357 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6358 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6359 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6363 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6370 Configure what scope the hot key will impact.
6371 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6372 If no scope is set, the default scope will be FormSet level.
6373 After all registered hot keys are removed, previous Scope can reset to another level.
6375 @param[in] Scope Scope level to be set.
6377 @retval EFI_SUCCESS Scope is set correctly.
6378 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6379 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6385 IN BROWSER_SETTING_SCOPE Scope
6388 if (Scope
>= MaxLevel
) {
6389 return EFI_INVALID_PARAMETER
;
6393 // When no hot key registered in system or on the first setting,
6394 // Scope can be set.
6396 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6397 gBrowserSettingScope
= Scope
;
6398 mBrowserScopeFirstSet
= FALSE
;
6399 } else if (Scope
!= gBrowserSettingScope
) {
6400 return EFI_UNSUPPORTED
;
6407 Register the hot key with its browser action, or unregistered the hot key.
6408 Only support hot key that is not printable character (control key, function key, etc.).
6409 If the action value is zero, the hot key will be unregistered if it has been registered.
6410 If the same hot key has been registered, the new action and help string will override the previous ones.
6412 @param[in] KeyData A pointer to a buffer that describes the keystroke
6413 information for the hot key. Its type is EFI_INPUT_KEY to
6414 be supported by all ConsoleIn devices.
6415 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6416 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6417 @param[in] HelpString Help string that describes the hot key information.
6418 Its value may be NULL for the unregistered hot key.
6420 @retval EFI_SUCCESS Hot key is registered or unregistered.
6421 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6422 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6423 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6424 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6429 IN EFI_INPUT_KEY
*KeyData
,
6431 IN UINT16 DefaultId
,
6432 IN EFI_STRING HelpString OPTIONAL
6435 BROWSER_HOT_KEY
*HotKey
;
6438 // Check input parameters.
6440 if ((KeyData
== NULL
) || (KeyData
->UnicodeChar
!= CHAR_NULL
) ||
6441 ((Action
!= BROWSER_ACTION_UNREGISTER
) && (HelpString
== NULL
)))
6443 return EFI_INVALID_PARAMETER
;
6447 // Check whether the input KeyData is in BrowserHotKeyList.
6449 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6452 // Unregister HotKey
6454 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6455 if (HotKey
!= NULL
) {
6457 // The registered HotKey is found.
6458 // Remove it from List, and free its resource.
6460 RemoveEntryList (&HotKey
->Link
);
6461 FreePool (HotKey
->KeyData
);
6462 FreePool (HotKey
->HelpString
);
6466 // The registered HotKey is not found.
6468 return EFI_NOT_FOUND
;
6472 if (HotKey
!= NULL
) {
6473 return EFI_ALREADY_STARTED
;
6477 // Create new Key, and add it into List.
6479 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6480 ASSERT (HotKey
!= NULL
);
6481 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6482 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6483 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6486 // Fill HotKey information.
6488 HotKey
->Action
= Action
;
6489 HotKey
->DefaultId
= DefaultId
;
6490 if (HotKey
->HelpString
!= NULL
) {
6491 FreePool (HotKey
->HelpString
);
6494 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6500 Register Exit handler function.
6501 When more than one handler function is registered, the latter one will override the previous one.
6502 When NULL handler is specified, the previous Exit handler will be unregistered.
6504 @param[in] Handler Pointer to handler function.
6509 RegiserExitHandler (
6510 IN EXIT_HANDLER Handler
6513 ExitHandlerFunction
= Handler
;
6518 Check whether the browser data has been modified.
6520 @retval TRUE Browser data is modified.
6521 @retval FALSE No browser data is modified.
6526 IsBrowserDataModified (
6531 FORM_BROWSER_FORMSET
*FormSet
;
6533 switch (gBrowserSettingScope
) {
6535 if (gCurrentSelection
== NULL
) {
6539 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6542 if (gCurrentSelection
== NULL
) {
6546 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6549 Link
= GetFirstNode (&gBrowserFormSetList
);
6550 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6551 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6552 if (!ValidateFormSet (FormSet
)) {
6556 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6560 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6571 Execute the action requested by the Action parameter.
6573 @param[in] Action Execute the request action.
6574 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6576 @retval EFI_SUCCESS Execute the request action succss.
6577 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6588 FORM_BROWSER_FORMSET
*FormSet
;
6589 FORM_BROWSER_FORM
*Form
;
6591 if ((gBrowserSettingScope
< SystemLevel
) && (gCurrentSelection
== NULL
)) {
6592 return EFI_NOT_READY
;
6595 Status
= EFI_SUCCESS
;
6598 if (gBrowserSettingScope
< SystemLevel
) {
6599 FormSet
= gCurrentSelection
->FormSet
;
6600 Form
= gCurrentSelection
->Form
;
6604 // Executet the discard action.
6606 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6607 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6608 if (EFI_ERROR (Status
)) {
6614 // Executet the difault action.
6616 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6617 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6618 if (EFI_ERROR (Status
)) {
6622 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6626 // Executet the submit action.
6628 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6629 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6630 if (EFI_ERROR (Status
)) {
6636 // Executet the reset action.
6638 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6639 gResetRequiredFormLevel
= TRUE
;
6640 gResetRequiredSystemLevel
= TRUE
;
6644 // Executet the exit action.
6646 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6647 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6648 if (gBrowserSettingScope
== SystemLevel
) {
6649 if (ExitHandlerFunction
!= NULL
) {
6650 ExitHandlerFunction ();
6654 gExitRequired
= TRUE
;
6661 Create reminder to let user to choose save or discard the changed browser data.
6662 Caller can use it to actively check the changed browser data.
6664 @retval BROWSER_NO_CHANGES No browser data is changed.
6665 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6666 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6667 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6677 FORM_BROWSER_FORMSET
*FormSet
;
6678 BOOLEAN IsDataChanged
;
6679 UINT32 DataSavedAction
;
6682 DataSavedAction
= BROWSER_NO_CHANGES
;
6683 IsDataChanged
= FALSE
;
6684 Link
= GetFirstNode (&gBrowserFormSetList
);
6685 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6686 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6687 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6688 if (!ValidateFormSet (FormSet
)) {
6692 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6693 IsDataChanged
= TRUE
;
6699 // No data is changed. No save is required.
6701 if (!IsDataChanged
) {
6702 return DataSavedAction
;
6706 // If data is changed, prompt user to save or discard it.
6709 ConfirmRet
= (UINT32
)mFormDisplay
->ConfirmDataChange ();
6711 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6712 SubmitForm (NULL
, NULL
, SystemLevel
);
6713 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6715 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6716 DiscardForm (NULL
, NULL
, SystemLevel
);
6717 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6719 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6720 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6725 return DataSavedAction
;
6729 Check whether the Reset Required for the browser
6731 @retval TRUE Browser required to reset after exit.
6732 @retval FALSE Browser not need to reset after exit.
6741 return gResetRequiredSystemLevel
;