2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2020 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
);
368 InitializeCurrentSetting (LocalFormSet
);
371 // Initilize Questions' Value
373 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
374 if (EFI_ERROR (Status
)) {
375 DestroyFormSet (LocalFormSet
);
381 // Free resources, and restore gOldFormSet and gClassOfVfr
383 FreePool (HiiHandles
);
385 mSystemLevelFormSet
= OldFormset
;
389 Pop up the error info.
391 @param BrowserStatus The input browser status.
392 @param HiiHandle The Hiihandle for this opcode.
393 @param OpCode The opcode use to get the erro info and timeout value.
394 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
399 IN UINT32 BrowserStatus
,
400 IN EFI_HII_HANDLE HiiHandle
,
401 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
402 IN CHAR16
*ErrorString
405 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
406 USER_INPUT UserInputData
;
410 if (OpCode
!= NULL
) {
411 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
412 ASSERT (Statement
!= NULL
);
413 Statement
->OpCode
= OpCode
;
414 gDisplayFormData
.HighLightedStatement
= Statement
;
418 // Used to compatible with old display engine.
419 // New display engine not use this field.
421 gDisplayFormData
.ErrorString
= ErrorString
;
422 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
424 if (HiiHandle
!= NULL
) {
425 gDisplayFormData
.HiiHandle
= HiiHandle
;
428 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
430 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
431 gDisplayFormData
.ErrorString
= NULL
;
433 if (OpCode
!= NULL
) {
434 FreePool (Statement
);
437 return UserInputData
.Action
;
441 This is the routine which an external caller uses to direct the browser
442 where to obtain it's information.
445 @param This The Form Browser protocol instanse.
446 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
447 display a list of the formsets for the handles specified.
448 @param HandleCount The number of Handles specified in Handle.
449 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
450 field in the EFI_IFR_FORM_SET op-code for the specified
451 forms-based package. If FormSetGuid is NULL, then this
452 function will display the first found forms package.
453 @param FormId This field specifies which EFI_IFR_FORM to render as the first
454 displayable page. If this field has a value of 0x0000, then
455 the forms browser will render the specified forms in their encoded order.
456 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
458 @param ActionRequest Points to the action recommended by the form.
460 @retval EFI_SUCCESS The function completed successfully.
461 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
462 @retval EFI_NOT_FOUND No valid forms could be found to display.
468 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
469 IN EFI_HII_HANDLE
*Handles
,
470 IN UINTN HandleCount
,
471 IN EFI_GUID
*FormSetGuid
, OPTIONAL
472 IN UINT16 FormId
, OPTIONAL
473 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
474 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
478 UI_MENU_SELECTION
*Selection
;
480 FORM_BROWSER_FORMSET
*FormSet
;
481 FORM_ENTRY_INFO
*MenuList
;
485 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
487 if (mFormDisplay
== NULL
) {
488 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
489 return EFI_UNSUPPORTED
;
493 // Save globals used by SendForm()
495 SaveBrowserContext ();
497 gFlagReconnect
= FALSE
;
498 gResetRequiredFormLevel
= FALSE
;
499 gExitRequired
= FALSE
;
500 gCallbackReconnect
= FALSE
;
501 Status
= EFI_SUCCESS
;
503 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
505 for (Index
= 0; Index
< HandleCount
; Index
++) {
506 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
507 ASSERT (Selection
!= NULL
);
509 Selection
->Handle
= Handles
[Index
];
510 if (FormSetGuid
!= NULL
) {
511 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
512 Selection
->FormId
= FormId
;
514 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
518 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
519 ASSERT (FormSet
!= NULL
);
522 // Validate the HiiHandle
523 // if validate failed, find the first validate parent HiiHandle.
525 if (!ValidateHiiHandle(Selection
->Handle
)) {
526 FindNextMenu (Selection
, FormSetLevel
);
530 // Initialize internal data structures of FormSet
532 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
533 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
534 DestroyFormSet (FormSet
);
537 Selection
->FormSet
= FormSet
;
538 mSystemLevelFormSet
= FormSet
;
541 // Display this formset
543 gCurrentSelection
= Selection
;
545 Status
= SetupBrowser (Selection
);
547 gCurrentSelection
= NULL
;
548 mSystemLevelFormSet
= NULL
;
550 if (gFlagReconnect
|| gCallbackReconnect
) {
551 RetVal
= ReconnectController (FormSet
->DriverHandle
);
553 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
555 gFlagReconnect
= FALSE
;
556 gCallbackReconnect
= FALSE
;
560 // If no data is changed, don't need to save current FormSet into the maintain list.
562 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
563 CleanBrowserStorage(FormSet
);
564 RemoveEntryList (&FormSet
->Link
);
565 DestroyFormSet (FormSet
);
568 if (EFI_ERROR (Status
)) {
571 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
573 FreePool (Selection
);
576 if (ActionRequest
!= NULL
) {
577 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
578 if (gResetRequiredFormLevel
) {
579 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
583 mFormDisplay
->ExitDisplay();
586 // Clear the menu history data.
588 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
589 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
590 RemoveEntryList (&MenuList
->Link
);
595 // Restore globals used by SendForm()
597 RestoreBrowserContext ();
603 Get or set data to the storage.
605 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
606 @param ResultsData A string returned from an IFR browser or
607 equivalent. The results string will have no
608 routing information in them.
609 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
610 (if RetrieveData = TRUE) data from the uncommitted
611 browser state information or set (if RetrieveData
612 = FALSE) data in the uncommitted browser state
614 @param Storage The pointer to the storage.
616 @retval EFI_SUCCESS The results have been distributed or are awaiting
622 IN OUT UINTN
*ResultsDataSize
,
623 IN OUT EFI_STRING
*ResultsData
,
624 IN BOOLEAN RetrieveData
,
625 IN BROWSER_STORAGE
*Storage
634 FORMSET_STORAGE
*BrowserStorage
;
638 // Generate <ConfigResp>
640 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
641 if (EFI_ERROR (Status
)) {
646 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
647 // Also need to consider add "\0" at first time.
649 StrPtr
= StrStr (ConfigResp
, L
"PATH");
650 ASSERT (StrPtr
!= NULL
);
651 StrPtr
= StrStr (StrPtr
, L
"&");
653 BufferSize
= StrSize (StrPtr
);
656 // Copy the data if the input buffer is bigger enough.
658 if (*ResultsDataSize
>= BufferSize
) {
659 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
662 *ResultsDataSize
= BufferSize
;
663 FreePool (ConfigResp
);
666 // Prepare <ConfigResp>
668 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
669 ASSERT (BrowserStorage
!= NULL
);
670 TmpSize
= StrLen (*ResultsData
);
671 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
672 MaxLen
= BufferSize
/ sizeof (CHAR16
);
673 ConfigResp
= AllocateZeroPool (BufferSize
);
674 ASSERT (ConfigResp
!= NULL
);
676 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
677 StrCatS (ConfigResp
, MaxLen
, L
"&");
678 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
681 // Update Browser uncommited data
683 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
684 FreePool (ConfigResp
);
685 if (EFI_ERROR (Status
)) {
694 This routine called this service in the browser to retrieve or set certain uncommitted
695 state information that resides in the open formsets.
697 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
699 @param ResultsDataSize A pointer to the size of the buffer associated
701 @param ResultsData A string returned from an IFR browser or
702 equivalent. The results string will have no
703 routing information in them.
704 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
705 (if RetrieveData = TRUE) data from the uncommitted
706 browser state information or set (if RetrieveData
707 = FALSE) data in the uncommitted browser state
709 @param VariableGuid An optional field to indicate the target variable
711 @param VariableName An optional field to indicate the target
712 human-readable variable name.
714 @retval EFI_SUCCESS The results have been distributed or are awaiting
716 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
717 contain the results data.
723 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
724 IN OUT UINTN
*ResultsDataSize
,
725 IN OUT EFI_STRING ResultsData
,
726 IN BOOLEAN RetrieveData
,
727 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
728 IN CONST CHAR16
*VariableName OPTIONAL
733 BROWSER_STORAGE
*Storage
;
734 FORMSET_STORAGE
*FormsetStorage
;
738 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
739 return EFI_INVALID_PARAMETER
;
742 TotalSize
= *ResultsDataSize
;
745 Status
= EFI_SUCCESS
;
747 if (VariableGuid
!= NULL
) {
749 // Try to find target storage in the current formset.
751 Link
= GetFirstNode (&gBrowserStorageList
);
752 while (!IsNull (&gBrowserStorageList
, Link
)) {
753 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
754 Link
= GetNextNode (&gBrowserStorageList
, Link
);
756 // Check the current storage.
758 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
762 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
763 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
765 // Buffer storage require both GUID and Name
767 if (VariableName
== NULL
) {
768 return EFI_NOT_FOUND
;
771 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
776 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
777 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
778 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
779 return EFI_NOT_FOUND
;
782 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
787 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
788 if (EFI_ERROR (Status
)) {
792 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
793 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
797 // Different formsets may have same varstore, so here just set the flag
798 // not exit the circle.
805 return EFI_NOT_FOUND
;
809 // GUID/Name is not specified, take the first storage in FormSet
811 if (mSystemLevelFormSet
== NULL
) {
812 return EFI_NOT_READY
;
816 // Generate <ConfigResp>
818 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
819 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
820 return EFI_UNSUPPORTED
;
823 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
825 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
826 if (EFI_ERROR (Status
)) {
832 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
833 *ResultsDataSize
= TotalSize
;
842 Callback function for SimpleTextInEx protocol install events
844 @param Event the event that is signaled.
845 @param Context not used here.
850 FormDisplayCallback (
855 if (mFormDisplay
!= NULL
) {
859 gBS
->LocateProtocol (
860 &gEdkiiFormDisplayEngineProtocolGuid
,
862 (VOID
**) &mFormDisplay
867 Initialize Setup Browser driver.
869 @param ImageHandle The image handle.
870 @param SystemTable The system table.
872 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
873 @return Other value if failed to initialize the Setup Browser module.
879 IN EFI_HANDLE ImageHandle
,
880 IN EFI_SYSTEM_TABLE
*SystemTable
887 // Locate required Hii relative protocols
889 Status
= gBS
->LocateProtocol (
890 &gEfiHiiDatabaseProtocolGuid
,
892 (VOID
**) &mHiiDatabase
894 ASSERT_EFI_ERROR (Status
);
896 Status
= gBS
->LocateProtocol (
897 &gEfiHiiConfigRoutingProtocolGuid
,
899 (VOID
**) &mHiiConfigRouting
901 ASSERT_EFI_ERROR (Status
);
903 Status
= gBS
->LocateProtocol (
904 &gEfiDevicePathFromTextProtocolGuid
,
906 (VOID
**) &mPathFromText
910 // Install FormBrowser2 protocol
912 mPrivateData
.Handle
= NULL
;
913 Status
= gBS
->InstallProtocolInterface (
914 &mPrivateData
.Handle
,
915 &gEfiFormBrowser2ProtocolGuid
,
916 EFI_NATIVE_INTERFACE
,
917 &mPrivateData
.FormBrowser2
919 ASSERT_EFI_ERROR (Status
);
922 // Install FormBrowserEx2 protocol
924 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
925 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
926 mPrivateData
.Handle
= NULL
;
927 Status
= gBS
->InstallProtocolInterface (
928 &mPrivateData
.Handle
,
929 &gEdkiiFormBrowserEx2ProtocolGuid
,
930 EFI_NATIVE_INTERFACE
,
931 &mPrivateData
.FormBrowserEx2
933 ASSERT_EFI_ERROR (Status
);
935 Status
= gBS
->InstallProtocolInterface (
936 &mPrivateData
.Handle
,
937 &gEdkiiFormBrowserExProtocolGuid
,
938 EFI_NATIVE_INTERFACE
,
939 &mPrivateData
.FormBrowserEx
941 ASSERT_EFI_ERROR (Status
);
943 InitializeDisplayFormData ();
945 Status
= gBS
->LocateProtocol (
946 &gEdkiiFormDisplayEngineProtocolGuid
,
948 (VOID
**) &mFormDisplay
951 if (EFI_ERROR (Status
)) {
952 EfiCreateProtocolNotifyEvent (
953 &gEdkiiFormDisplayEngineProtocolGuid
,
966 Create a new string in HII Package List.
968 @param String The String to be added
969 @param HiiHandle The package list in the HII database to insert the
972 @return The output string.
978 IN EFI_HII_HANDLE HiiHandle
981 EFI_STRING_ID StringId
;
983 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
984 ASSERT (StringId
!= 0);
991 Delete a string from HII Package List.
993 @param StringId Id of the string in HII database.
994 @param HiiHandle The HII package list handle.
996 @retval EFI_SUCCESS The string was deleted successfully.
1001 IN EFI_STRING_ID StringId
,
1002 IN EFI_HII_HANDLE HiiHandle
1007 NullChar
= CHAR_NULL
;
1008 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1014 Get the string based on the StringId and HII Package List Handle.
1016 @param Token The String's ID.
1017 @param HiiHandle The package list in the HII database to search for
1018 the specified string.
1020 @return The output string.
1025 IN EFI_STRING_ID Token
,
1026 IN EFI_HII_HANDLE HiiHandle
1031 if (HiiHandle
== NULL
) {
1035 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1036 if (String
== NULL
) {
1037 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1038 ASSERT (String
!= NULL
);
1040 return (CHAR16
*) String
;
1045 Allocate new memory and then copy the Unicode string Source to Destination.
1047 @param Dest Location to copy string
1048 @param Src String to copy
1053 IN OUT CHAR16
**Dest
,
1057 if (*Dest
!= NULL
) {
1060 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1061 ASSERT (*Dest
!= NULL
);
1066 Allocate new memory and concatinate Source on the end of Destination.
1068 @param Dest String to added to the end of.
1069 @param Src String to concatinate.
1074 IN OUT CHAR16
**Dest
,
1081 if (*Dest
== NULL
) {
1082 NewStringCpy (Dest
, Src
);
1086 MaxLen
= ( StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1087 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1088 ASSERT (NewString
!= NULL
);
1090 StrCpyS (NewString
, MaxLen
, *Dest
);
1091 StrCatS (NewString
, MaxLen
, Src
);
1098 Get Value for given Name from a NameValue Storage.
1100 @param Storage The NameValue Storage.
1101 @param Name The Name.
1102 @param Value The retured Value.
1103 @param GetValueFrom Where to get source value, from EditValue or Value.
1105 @retval EFI_SUCCESS Value found for given Name.
1106 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1111 IN BROWSER_STORAGE
*Storage
,
1113 IN OUT CHAR16
**Value
,
1114 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1118 NAME_VALUE_NODE
*Node
;
1120 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1121 return EFI_INVALID_PARAMETER
;
1126 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1127 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1128 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1130 if (StrCmp (Name
, Node
->Name
) == 0) {
1131 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1132 NewStringCpy (Value
, Node
->EditValue
);
1134 NewStringCpy (Value
, Node
->Value
);
1139 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1142 return EFI_NOT_FOUND
;
1147 Set Value of given Name in a NameValue Storage.
1149 @param Storage The NameValue Storage.
1150 @param Name The Name.
1151 @param Value The Value to set.
1152 @param SetValueTo Whether update editValue or Value.
1153 @param ReturnNode The node use the input name.
1155 @retval EFI_SUCCESS Value found for given Name.
1156 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1161 IN BROWSER_STORAGE
*Storage
,
1164 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1165 OUT NAME_VALUE_NODE
**ReturnNode
1169 NAME_VALUE_NODE
*Node
;
1172 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1173 return EFI_INVALID_PARAMETER
;
1176 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1177 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1178 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1180 if (StrCmp (Name
, Node
->Name
) == 0) {
1181 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1182 Buffer
= Node
->EditValue
;
1184 Buffer
= Node
->Value
;
1186 if (Buffer
!= NULL
) {
1189 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1190 ASSERT (Buffer
!= NULL
);
1191 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1192 Node
->EditValue
= Buffer
;
1194 Node
->Value
= Buffer
;
1197 if (ReturnNode
!= NULL
) {
1204 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1207 return EFI_NOT_FOUND
;
1212 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1214 @param Storage The Storage to be conveted.
1215 @param ConfigResp The returned <ConfigResp>.
1216 @param ConfigRequest The ConfigRequest string.
1217 @param GetEditBuf Get the data from editbuffer or buffer.
1219 @retval EFI_SUCCESS Convert success.
1220 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1224 StorageToConfigResp (
1225 IN BROWSER_STORAGE
*Storage
,
1226 IN CHAR16
**ConfigResp
,
1227 IN CHAR16
*ConfigRequest
,
1228 IN BOOLEAN GetEditBuf
1232 EFI_STRING Progress
;
1234 NAME_VALUE_NODE
*Node
;
1236 FORMSET_STORAGE
*FormsetStorage
;
1238 Status
= EFI_SUCCESS
;
1240 switch (Storage
->Type
) {
1241 case EFI_HII_VARSTORE_BUFFER
:
1242 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1243 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1244 Status
= mHiiConfigRouting
->BlockToConfig (
1254 case EFI_HII_VARSTORE_NAME_VALUE
:
1256 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1257 ASSERT (FormsetStorage
!= NULL
);
1258 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1260 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1261 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1262 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1264 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1265 NewStringCat (ConfigResp
, L
"&");
1266 NewStringCat (ConfigResp
, Node
->Name
);
1267 NewStringCat (ConfigResp
, L
"=");
1269 NewStringCat (ConfigResp
, Node
->EditValue
);
1271 NewStringCat (ConfigResp
, Node
->Value
);
1274 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1278 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1280 Status
= EFI_INVALID_PARAMETER
;
1289 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1291 @param Storage The Storage to receive the settings.
1292 @param ConfigResp The <ConfigResp> to be converted.
1294 @retval EFI_SUCCESS Convert success.
1295 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1299 ConfigRespToStorage (
1300 IN BROWSER_STORAGE
*Storage
,
1301 IN CHAR16
*ConfigResp
1305 EFI_STRING Progress
;
1311 Status
= EFI_SUCCESS
;
1313 switch (Storage
->Type
) {
1314 case EFI_HII_VARSTORE_BUFFER
:
1315 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1316 BufferSize
= Storage
->Size
;
1317 Status
= mHiiConfigRouting
->ConfigToBlock (
1320 Storage
->EditBuffer
,
1326 case EFI_HII_VARSTORE_NAME_VALUE
:
1327 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1328 if (StrPtr
== NULL
) {
1331 StrPtr
= StrStr (ConfigResp
, L
"&");
1332 while (StrPtr
!= NULL
) {
1336 StrPtr
= StrPtr
+ 1;
1338 StrPtr
= StrStr (StrPtr
, L
"=");
1339 if (StrPtr
== NULL
) {
1347 StrPtr
= StrPtr
+ 1;
1349 StrPtr
= StrStr (StrPtr
, L
"&");
1350 if (StrPtr
!= NULL
) {
1353 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1357 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1359 Status
= EFI_INVALID_PARAMETER
;
1367 Get bit field value from the buffer and then set the value for the question.
1368 Note: Data type UINT32 can cover all the bit field value.
1370 @param Question The question refer to bit field.
1371 @param Buffer Point to the buffer which the question value get from.
1375 GetBitsQuestionValue (
1376 IN FORM_BROWSER_STATEMENT
*Question
,
1385 StartBit
= Question
->BitVarOffset
% 8;
1386 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1388 CopyMem ((UINT8
*) &BufferValue
, Buffer
, Question
->StorageWidth
);
1390 RetVal
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1393 // Set question value.
1394 // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
1395 // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.
1397 CopyMem ((UINT8
*) &Question
->HiiValue
.Value
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1401 Set bit field value to the buffer.
1402 Note: Data type UINT32 can cover all the bit field value.
1404 @param Question The question refer to bit field.
1405 @param Buffer Point to the buffer which the question value set to.
1406 @param Value The bit field value need to set.
1410 SetBitsQuestionValue (
1411 IN FORM_BROWSER_STATEMENT
*Question
,
1412 IN OUT UINT8
*Buffer
,
1421 StartBit
= Question
->BitVarOffset
% 8;
1422 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1424 CopyMem ((UINT8
*) &Operand
, Buffer
, Question
->StorageWidth
);
1426 RetVal
= BitFieldWrite32 (Operand
, StartBit
, EndBit
, Value
);
1428 CopyMem (Buffer
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1432 Convert the buffer value to HiiValue.
1434 @param Question The question.
1435 @param Value Unicode buffer save the question value.
1437 @retval Status whether convert the value success.
1442 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1447 BOOLEAN IsBufferStorage
;
1462 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1463 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1464 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1465 IsBufferStorage
= TRUE
;
1467 IsBufferStorage
= FALSE
;
1471 // Question Value is provided by Buffer Storage or NameValue Storage
1473 if (Question
->BufferValue
!= NULL
) {
1475 // This Question is password or orderedlist
1477 Dst
= Question
->BufferValue
;
1480 // Other type of Questions
1482 if (Question
->QuestionReferToBitField
) {
1483 Buffer
= (UINT8
*)AllocateZeroPool (Question
->StorageWidth
);
1484 if (Buffer
== NULL
) {
1485 return EFI_OUT_OF_RESOURCES
;
1489 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1494 // Temp cut at the end of this section, end with '\0' or '&'.
1497 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1500 TempChar
= *StringPtr
;
1503 LengthStr
= StrLen (Value
);
1506 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1507 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1508 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1509 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1511 if (LengthStr
> (UINTN
) Question
->StorageWidth
* 2) {
1512 Length
= (UINTN
) Question
->StorageWidth
* 2;
1517 Status
= EFI_SUCCESS
;
1518 if (!IsBufferStorage
&& IsString
) {
1520 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1521 // Add string tail char L'\0' into Length
1523 DstBuf
= (CHAR16
*) Dst
;
1524 ZeroMem (TemStr
, sizeof (TemStr
));
1525 for (Index
= 0; Index
< Length
; Index
+= 4) {
1526 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1527 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1530 // Add tailing L'\0' character
1532 DstBuf
[Index
/4] = L
'\0';
1534 ZeroMem (TemStr
, sizeof (TemStr
));
1535 for (Index
= 0; Index
< Length
; Index
++) {
1536 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1537 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1538 if ((Index
& 1) == 0) {
1539 Dst
[Index
/2] = DigitUint8
;
1541 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1546 *StringPtr
= TempChar
;
1548 if (Buffer
!= NULL
&& Question
->QuestionReferToBitField
) {
1549 GetBitsQuestionValue (Question
, Buffer
);
1557 Get Question's current Value.
1559 @param FormSet FormSet data structure.
1560 @param Form Form data structure.
1561 @param Question Question to be initialized.
1562 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1564 @retval EFI_SUCCESS The function completed successfully.
1569 IN FORM_BROWSER_FORMSET
*FormSet
,
1570 IN FORM_BROWSER_FORM
*Form
,
1571 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1572 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1581 BROWSER_STORAGE
*Storage
;
1582 FORMSET_STORAGE
*FormsetStorage
;
1583 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1584 CHAR16
*ConfigRequest
;
1589 BOOLEAN IsBufferStorage
;
1592 Status
= EFI_SUCCESS
;
1596 if (GetValueFrom
>= GetSetValueWithMax
) {
1597 return EFI_INVALID_PARAMETER
;
1601 // Question value is provided by an Expression, evaluate it
1603 if (Question
->ValueExpression
!= NULL
) {
1604 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1605 if (!EFI_ERROR (Status
)) {
1606 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1607 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1608 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1609 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1610 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1612 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1613 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1615 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1617 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1618 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1624 // Get question value by read expression.
1626 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1627 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1628 if (!EFI_ERROR (Status
) &&
1629 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1631 // Only update question value to the valid result.
1633 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1634 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1635 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1636 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1637 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1639 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1640 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1642 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1644 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1645 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1651 // Question value is provided by RTC
1653 Storage
= Question
->Storage
;
1654 QuestionValue
= &Question
->HiiValue
.Value
;
1655 if (Storage
== NULL
) {
1657 // It's a Question without storage, or RTC date/time
1659 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1661 // Date and time define the same Flags bit
1663 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1664 case QF_DATE_STORAGE_TIME
:
1665 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1668 case QF_DATE_STORAGE_WAKEUP
:
1669 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1672 case QF_DATE_STORAGE_NORMAL
:
1675 // For date/time without storage
1680 if (EFI_ERROR (Status
)) {
1681 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1682 QuestionValue
->date
.Year
= 0xff;
1683 QuestionValue
->date
.Month
= 0xff;
1684 QuestionValue
->date
.Day
= 0xff;
1686 QuestionValue
->time
.Hour
= 0xff;
1687 QuestionValue
->time
.Minute
= 0xff;
1688 QuestionValue
->time
.Second
= 0xff;
1693 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1694 QuestionValue
->date
.Year
= EfiTime
.Year
;
1695 QuestionValue
->date
.Month
= EfiTime
.Month
;
1696 QuestionValue
->date
.Day
= EfiTime
.Day
;
1698 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1699 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1700 QuestionValue
->time
.Second
= EfiTime
.Second
;
1708 // Question value is provided by EFI variable
1710 StorageWidth
= Question
->StorageWidth
;
1711 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1712 if (Question
->BufferValue
!= NULL
) {
1713 Dst
= Question
->BufferValue
;
1715 Dst
= (UINT8
*) QuestionValue
;
1718 Status
= gRT
->GetVariable (
1719 Question
->VariableName
,
1726 // Always return success, even this EFI variable doesn't exist
1732 // Question Value is provided by Buffer Storage or NameValue Storage
1734 if (Question
->BufferValue
!= NULL
) {
1736 // This Question is password or orderedlist
1738 Dst
= Question
->BufferValue
;
1741 // Other type of Questions
1743 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1746 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1747 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1748 IsBufferStorage
= TRUE
;
1750 IsBufferStorage
= FALSE
;
1752 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1753 if (IsBufferStorage
) {
1754 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1756 // Copy from storage Edit buffer
1757 // If the Question refer to bit filed, get the value in the related bit filed.
1759 if (Question
->QuestionReferToBitField
) {
1760 GetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
);
1762 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1766 // Copy from storage Edit buffer
1767 // If the Question refer to bit filed, get the value in the related bit filed.
1769 if (Question
->QuestionReferToBitField
) {
1770 GetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
);
1772 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1777 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1778 if (EFI_ERROR (Status
)) {
1782 ASSERT (Value
!= NULL
);
1783 Status
= BufferToValue (Question
, Value
);
1787 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1788 ASSERT (FormsetStorage
!= NULL
);
1790 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1791 // <ConfigHdr> + "&" + <VariableName>
1793 if (IsBufferStorage
) {
1794 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1795 Length
+= StrLen (Question
->BlockName
);
1797 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1798 Length
+= StrLen (Question
->VariableName
) + 1;
1800 // Allocate buffer include '\0'
1801 MaxLen
= Length
+ 1;
1802 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1803 ASSERT (ConfigRequest
!= NULL
);
1805 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1806 if (IsBufferStorage
) {
1807 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1809 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1810 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1814 // Request current settings from Configuration Driver
1816 Status
= mHiiConfigRouting
->ExtractConfig (
1822 FreePool (ConfigRequest
);
1823 if (EFI_ERROR (Status
)) {
1828 // Skip <ConfigRequest>
1830 if (IsBufferStorage
) {
1831 Value
= StrStr (Result
, L
"&VALUE");
1832 if (Value
== NULL
) {
1834 return EFI_NOT_FOUND
;
1841 Value
= Result
+ Length
;
1843 if (*Value
!= '=') {
1845 return EFI_NOT_FOUND
;
1848 // Skip '=', point to value
1852 Status
= BufferToValue (Question
, Value
);
1853 if (EFI_ERROR (Status
)) {
1859 // Synchronize Edit Buffer
1861 if (IsBufferStorage
) {
1862 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1864 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1867 if (Result
!= NULL
) {
1877 Save Question Value to edit copy(cached) or Storage(uncached).
1879 @param FormSet FormSet data structure.
1880 @param Form Form data structure.
1881 @param Question Pointer to the Question.
1882 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1884 @retval EFI_SUCCESS The function completed successfully.
1889 IN FORM_BROWSER_FORMSET
*FormSet
,
1890 IN FORM_BROWSER_FORM
*Form
,
1891 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1892 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1902 BROWSER_STORAGE
*Storage
;
1903 FORMSET_STORAGE
*FormsetStorage
;
1904 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1909 BOOLEAN IsBufferStorage
;
1915 NAME_VALUE_NODE
*Node
;
1918 Status
= EFI_SUCCESS
;
1921 if (SetValueTo
>= GetSetValueWithMax
) {
1922 return EFI_INVALID_PARAMETER
;
1926 // If Question value is provided by an Expression, then it is read only
1928 if (Question
->ValueExpression
!= NULL
) {
1933 // Before set question value, evaluate its write expression.
1935 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1936 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1937 if (EFI_ERROR (Status
)) {
1943 // Question value is provided by RTC
1945 Storage
= Question
->Storage
;
1946 QuestionValue
= &Question
->HiiValue
.Value
;
1947 if (Storage
== NULL
) {
1949 // It's a Question without storage, or RTC date/time
1951 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1953 // Date and time define the same Flags bit
1955 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1956 case QF_DATE_STORAGE_TIME
:
1957 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1960 case QF_DATE_STORAGE_WAKEUP
:
1961 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1964 case QF_DATE_STORAGE_NORMAL
:
1967 // For date/time without storage
1972 if (EFI_ERROR (Status
)) {
1976 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1977 EfiTime
.Year
= QuestionValue
->date
.Year
;
1978 EfiTime
.Month
= QuestionValue
->date
.Month
;
1979 EfiTime
.Day
= QuestionValue
->date
.Day
;
1981 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1982 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1983 EfiTime
.Second
= QuestionValue
->time
.Second
;
1986 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1987 Status
= gRT
->SetTime (&EfiTime
);
1989 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1997 // Question value is provided by EFI variable
1999 StorageWidth
= Question
->StorageWidth
;
2000 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2001 if (Question
->BufferValue
!= NULL
) {
2002 Src
= Question
->BufferValue
;
2004 Src
= (UINT8
*) QuestionValue
;
2007 Status
= gRT
->SetVariable (
2008 Question
->VariableName
,
2010 Storage
->Attributes
,
2018 // Question Value is provided by Buffer Storage or NameValue Storage
2020 if (Question
->BufferValue
!= NULL
) {
2021 Src
= Question
->BufferValue
;
2023 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
2026 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2027 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2028 IsBufferStorage
= TRUE
;
2030 IsBufferStorage
= FALSE
;
2032 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2034 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
2035 if (IsBufferStorage
) {
2036 if (SetValueTo
== GetSetValueWithEditBuffer
) {
2038 // Copy to storage edit buffer
2039 // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
2041 if (Question
->QuestionReferToBitField
) {
2042 SetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2044 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2046 } else if (SetValueTo
== GetSetValueWithBuffer
) {
2048 // Copy to storage buffer
2049 // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.
2051 if (Question
->QuestionReferToBitField
) {
2052 SetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2054 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2060 // Allocate enough string buffer.
2063 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
2064 Value
= AllocateZeroPool (BufferLen
);
2065 ASSERT (Value
!= NULL
);
2067 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2069 TemName
= (CHAR16
*) Src
;
2071 for (; *TemName
!= L
'\0'; TemName
++) {
2072 UnicodeValueToStringS (
2074 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
2075 PREFIX_ZERO
| RADIX_HEX
,
2079 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
2082 BufferLen
= StorageWidth
* 2 + 1;
2083 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
2084 ASSERT (Value
!= NULL
);
2086 // Convert Buffer to Hex String
2088 TemBuffer
= Src
+ StorageWidth
- 1;
2090 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2091 UnicodeValueToStringS (
2093 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
2094 PREFIX_ZERO
| RADIX_HEX
,
2098 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2102 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2104 if (EFI_ERROR (Status
)) {
2108 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2110 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2111 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2113 if (IsBufferStorage
) {
2114 Length
= StrLen (Question
->BlockName
) + 7;
2116 Length
= StrLen (Question
->VariableName
) + 2;
2118 if (!IsBufferStorage
&& IsString
) {
2119 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2121 Length
+= (StorageWidth
* 2);
2123 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2124 ASSERT (FormsetStorage
!= NULL
);
2125 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2126 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2127 ASSERT (ConfigResp
!= NULL
);
2129 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2130 if (IsBufferStorage
) {
2131 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2132 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2134 StrCatS (ConfigResp
, MaxLen
, L
"&");
2135 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2136 StrCatS (ConfigResp
, MaxLen
, L
"=");
2139 Value
= ConfigResp
+ StrLen (ConfigResp
);
2141 if (!IsBufferStorage
&& IsString
) {
2143 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2145 TemName
= (CHAR16
*) Src
;
2147 for (; *TemName
!= L
'\0'; TemName
++) {
2148 UnicodeValueToStringS (
2150 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2151 PREFIX_ZERO
| RADIX_HEX
,
2155 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2159 // Convert Buffer to Hex String
2161 TemBuffer
= Src
+ StorageWidth
- 1;
2163 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2164 UnicodeValueToStringS (
2166 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2167 PREFIX_ZERO
| RADIX_HEX
,
2171 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2176 // Convert to lower char.
2178 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2179 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2180 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2185 // Submit Question Value to Configuration Driver
2187 Status
= mHiiConfigRouting
->RouteConfig (
2192 if (EFI_ERROR (Status
)) {
2193 FreePool (ConfigResp
);
2196 FreePool (ConfigResp
);
2199 // Sync storage, from editbuffer to buffer.
2201 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2209 Perform nosubmitif check for a Form.
2211 @param FormSet FormSet data structure.
2212 @param Form Form data structure.
2213 @param Question The Question to be validated.
2214 @param Type Validation type: NoSubmit
2216 @retval EFI_SUCCESS Form validation pass.
2217 @retval other Form validation failed.
2222 IN FORM_BROWSER_FORMSET
*FormSet
,
2223 IN FORM_BROWSER_FORM
*Form
,
2224 IN FORM_BROWSER_STATEMENT
*Question
,
2230 LIST_ENTRY
*ListHead
;
2231 FORM_EXPRESSION
*Expression
;
2232 UINT32 BrowserStatus
;
2235 BrowserStatus
= BROWSER_SUCCESS
;
2239 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2240 ListHead
= &Question
->InconsistentListHead
;
2243 case EFI_HII_EXPRESSION_WARNING_IF
:
2244 ListHead
= &Question
->WarningListHead
;
2247 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2248 ListHead
= &Question
->NoSubmitListHead
;
2253 return EFI_UNSUPPORTED
;
2256 Link
= GetFirstNode (ListHead
);
2257 while (!IsNull (ListHead
, Link
)) {
2258 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2261 // Evaluate the expression
2263 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2264 if (EFI_ERROR (Status
)) {
2268 if (IsTrue (&Expression
->Result
)) {
2270 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2271 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2274 case EFI_HII_EXPRESSION_WARNING_IF
:
2275 BrowserStatus
= BROWSER_WARNING_IF
;
2278 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2279 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2281 // This code only used to compatible with old display engine,
2282 // New display engine will not use this field.
2284 if (Expression
->Error
!= 0) {
2285 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2294 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2296 // If in system submit process and for no_submit_if check, not popup this error message.
2297 // Will process this fail again later in not system submit process.
2299 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2302 if (ErrorStr
!= NULL
) {
2303 FreePool (ErrorStr
);
2306 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2309 return EFI_NOT_READY
;
2313 Link
= GetNextNode (ListHead
, Link
);
2320 Perform question check.
2322 If one question has more than one check, process form high priority to low.
2323 Only one error info will be popup.
2325 @param FormSet FormSet data structure.
2326 @param Form Form data structure.
2327 @param Question The Question to be validated.
2329 @retval EFI_SUCCESS Form validation pass.
2330 @retval other Form validation failed.
2334 ValueChangedValidation (
2335 IN FORM_BROWSER_FORMSET
*FormSet
,
2336 IN FORM_BROWSER_FORM
*Form
,
2337 IN FORM_BROWSER_STATEMENT
*Question
2342 Status
= EFI_SUCCESS
;
2345 // Do the inconsistentif check.
2347 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2348 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2349 if (EFI_ERROR (Status
)) {
2355 // Do the warningif check.
2357 if (!IsListEmpty (&Question
->WarningListHead
)) {
2358 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2365 Perform NoSubmit check for each Form in FormSet.
2367 @param FormSet FormSet data structure.
2368 @param CurrentForm Current input form data structure.
2369 @param Statement The statement for this check.
2371 @retval EFI_SUCCESS Form validation pass.
2372 @retval other Form validation failed.
2377 IN FORM_BROWSER_FORMSET
*FormSet
,
2378 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2379 OUT FORM_BROWSER_STATEMENT
**Statement
2384 FORM_BROWSER_STATEMENT
*Question
;
2385 FORM_BROWSER_FORM
*Form
;
2386 LIST_ENTRY
*LinkForm
;
2388 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2389 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2390 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2391 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2393 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2397 Link
= GetFirstNode (&Form
->StatementListHead
);
2398 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2399 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2400 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2401 if (EFI_ERROR (Status
)) {
2402 if (*CurrentForm
== NULL
) {
2403 *CurrentForm
= Form
;
2405 if (Statement
!= NULL
) {
2406 *Statement
= Question
;
2411 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2419 Fill storage's edit copy with settings requested from Configuration Driver.
2421 @param Storage The storage which need to sync.
2422 @param ConfigRequest The config request string which used to sync storage.
2423 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2424 editbuffer to buffer
2425 if TRUE, copy the editbuffer to the buffer.
2426 if FALSE, copy the buffer to the editbuffer.
2428 @retval EFI_SUCCESS The function completed successfully.
2432 SynchronizeStorage (
2433 OUT BROWSER_STORAGE
*Storage
,
2434 IN CHAR16
*ConfigRequest
,
2435 IN BOOLEAN SyncOrRestore
2439 EFI_STRING Progress
;
2443 NAME_VALUE_NODE
*Node
;
2447 Status
= EFI_SUCCESS
;
2450 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2451 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2452 BufferSize
= Storage
->Size
;
2454 if (SyncOrRestore
) {
2455 Src
= Storage
->EditBuffer
;
2456 Dst
= Storage
->Buffer
;
2458 Src
= Storage
->Buffer
;
2459 Dst
= Storage
->EditBuffer
;
2462 if (ConfigRequest
!= NULL
) {
2463 Status
= mHiiConfigRouting
->BlockToConfig(
2471 if (EFI_ERROR (Status
)) {
2475 Status
= mHiiConfigRouting
->ConfigToBlock (
2482 if (Result
!= NULL
) {
2486 CopyMem (Dst
, Src
, BufferSize
);
2488 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2489 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2490 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2491 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2493 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2494 (ConfigRequest
== NULL
)) {
2495 if (SyncOrRestore
) {
2496 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2498 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2502 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2510 When discard the question value, call the callback function with Changed type
2511 to inform the hii driver.
2513 @param FormSet FormSet data structure.
2514 @param Form Form data structure.
2518 SendDiscardInfoToDriver (
2519 IN FORM_BROWSER_FORMSET
*FormSet
,
2520 IN FORM_BROWSER_FORM
*Form
2524 FORM_BROWSER_STATEMENT
*Question
;
2525 EFI_IFR_TYPE_VALUE
*TypeValue
;
2526 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2528 if (FormSet
->ConfigAccess
== NULL
) {
2532 Link
= GetFirstNode (&Form
->StatementListHead
);
2533 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2534 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2535 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2537 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2541 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2545 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2549 if (!Question
->ValueChanged
) {
2554 // Restore the question value before call the CHANGED callback type.
2556 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2558 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2559 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2562 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2563 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2565 TypeValue
= &Question
->HiiValue
.Value
;
2568 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2569 FormSet
->ConfigAccess
->Callback (
2570 FormSet
->ConfigAccess
,
2571 EFI_BROWSER_ACTION_CHANGED
,
2572 Question
->QuestionId
,
2573 Question
->HiiValue
.Type
,
2581 When submit the question value, call the callback function with Submitted type
2582 to inform the hii driver.
2584 @param FormSet FormSet data structure.
2585 @param Form Form data structure.
2589 SubmitCallbackForForm (
2590 IN FORM_BROWSER_FORMSET
*FormSet
,
2591 IN FORM_BROWSER_FORM
*Form
2595 FORM_BROWSER_STATEMENT
*Question
;
2596 EFI_IFR_TYPE_VALUE
*TypeValue
;
2597 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2599 if (FormSet
->ConfigAccess
== NULL
) {
2603 Link
= GetFirstNode (&Form
->StatementListHead
);
2604 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2605 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2606 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2608 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2612 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2616 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2620 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2621 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2623 TypeValue
= &Question
->HiiValue
.Value
;
2626 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2627 FormSet
->ConfigAccess
->Callback (
2628 FormSet
->ConfigAccess
,
2629 EFI_BROWSER_ACTION_SUBMITTED
,
2630 Question
->QuestionId
,
2631 Question
->HiiValue
.Type
,
2639 When value set Success, call the submit callback function.
2641 @param FormSet FormSet data structure.
2642 @param Form Form data structure.
2647 IN FORM_BROWSER_FORMSET
*FormSet
,
2648 IN FORM_BROWSER_FORM
*Form
2651 FORM_BROWSER_FORM
*CurrentForm
;
2655 SubmitCallbackForForm(FormSet
, Form
);
2659 Link
= GetFirstNode (&FormSet
->FormListHead
);
2660 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2661 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2662 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2664 SubmitCallbackForForm(FormSet
, CurrentForm
);
2669 Validate the HiiHandle.
2671 @param HiiHandle The input HiiHandle which need to validate.
2673 @retval TRUE The handle is validate.
2674 @retval FALSE The handle is invalidate.
2679 EFI_HII_HANDLE HiiHandle
2682 EFI_HII_HANDLE
*HiiHandles
;
2686 if (HiiHandle
== NULL
) {
2692 HiiHandles
= HiiGetHiiHandles (NULL
);
2693 ASSERT (HiiHandles
!= NULL
);
2695 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2696 if (HiiHandles
[Index
] == HiiHandle
) {
2702 FreePool (HiiHandles
);
2708 Validate the FormSet. If the formset is not validate, remove it from the list.
2710 @param FormSet The input FormSet which need to validate.
2712 @retval TRUE The handle is validate.
2713 @retval FALSE The handle is invalidate.
2718 FORM_BROWSER_FORMSET
*FormSet
2723 ASSERT (FormSet
!= NULL
);
2725 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2727 // Should not remove the formset which is being used.
2729 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2730 CleanBrowserStorage(FormSet
);
2731 RemoveEntryList (&FormSet
->Link
);
2732 DestroyFormSet (FormSet
);
2738 Check whether need to enable the reset flag in form level.
2739 Also clean all ValueChanged flag in question.
2741 @param SetFlag Whether need to set the Reset Flag.
2742 @param FormSet FormSet data structure.
2743 @param Form Form data structure.
2749 IN FORM_BROWSER_FORMSET
*FormSet
,
2750 IN FORM_BROWSER_FORM
*Form
2754 FORM_BROWSER_STATEMENT
*Question
;
2757 Link
= GetFirstNode (&Form
->StatementListHead
);
2758 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2759 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2760 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2762 if (!Question
->ValueChanged
) {
2766 OldValue
= Question
->ValueChanged
;
2769 // Compare the buffer and editbuffer data to see whether the data has been saved.
2771 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2774 // Only the changed data has been saved, then need to set the reset flag.
2776 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2777 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2778 gResetRequiredFormLevel
= TRUE
;
2779 gResetRequiredSystemLevel
= TRUE
;
2782 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2783 gFlagReconnect
= TRUE
;
2790 Check whether need to enable the reset flag.
2791 Also clean ValueChanged flag for all statements.
2793 Form level or formset level, only one.
2795 @param SetFlag Whether need to set the Reset Flag.
2796 @param FormSet FormSet data structure.
2797 @param Form Form data structure.
2801 ValueChangeResetFlagUpdate (
2803 IN FORM_BROWSER_FORMSET
*FormSet
,
2804 IN FORM_BROWSER_FORM
*Form
2807 FORM_BROWSER_FORM
*CurrentForm
;
2811 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2815 Link
= GetFirstNode (&FormSet
->FormListHead
);
2816 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2817 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2818 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2820 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2825 Base on the return Progress string to find the form.
2827 Base on the first return Offset/Width (Name) string to find the form
2828 which keep this string.
2830 @param FormSet FormSet data structure.
2831 @param Storage Storage which has this Progress string.
2832 @param Progress The Progress string which has the first fail string.
2833 @param RetForm The return form for this progress string.
2834 @param RetQuestion The return question for the error progress string.
2836 @retval TRUE Find the error form and statement for this error progress string.
2837 @retval FALSE Not find the error form.
2841 FindQuestionFromProgress (
2842 IN FORM_BROWSER_FORMSET
*FormSet
,
2843 IN BROWSER_STORAGE
*Storage
,
2844 IN EFI_STRING Progress
,
2845 OUT FORM_BROWSER_FORM
**RetForm
,
2846 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2850 LIST_ENTRY
*LinkStorage
;
2851 LIST_ENTRY
*LinkStatement
;
2852 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2853 FORM_BROWSER_FORM
*Form
;
2855 FORM_BROWSER_STATEMENT
*Statement
;
2857 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2861 *RetQuestion
= NULL
;
2864 // Skip the first "&" or the ConfigHdr part.
2866 if (*Progress
== '&') {
2870 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2872 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2874 // For Name/Value type, Skip the ConfigHdr part.
2876 EndStr
= StrStr (Progress
, L
"PATH=");
2877 ASSERT (EndStr
!= NULL
);
2878 while (*EndStr
!= '&') {
2885 // For Buffer type, Skip the ConfigHdr part.
2887 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2888 ASSERT (EndStr
!= NULL
);
2892 Progress
= EndStr
+ 1;
2896 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2898 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2900 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2901 // here, just keep the "Fred" string.
2903 EndStr
= StrStr (Progress
, L
"=");
2904 ASSERT (EndStr
!= NULL
);
2908 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2909 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2911 EndStr
= StrStr (Progress
, L
"&VALUE=");
2912 ASSERT (EndStr
!= NULL
);
2917 // Search in the form list.
2919 Link
= GetFirstNode (&FormSet
->FormListHead
);
2920 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2921 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2922 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2925 // Search in the ConfigReqeust list in this form.
2927 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2928 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2929 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2930 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2932 if (Storage
!= ConfigInfo
->Storage
) {
2936 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2938 // Find the OffsetWidth string in this form.
2945 if (*RetForm
!= NULL
) {
2946 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2947 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2948 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2949 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2951 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2952 *RetQuestion
= Statement
;
2956 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2957 *RetQuestion
= Statement
;
2963 if (*RetForm
!= NULL
) {
2969 // restore the OffsetWidth string to the original format.
2971 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2977 return (BOOLEAN
) (*RetForm
!= NULL
);
2981 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2982 for form and formset.
2984 @param Storage Storage which has this Progress string.
2985 @param ConfigRequest The ConfigRequest string.
2986 @param Progress The Progress string which has the first fail string.
2987 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2988 @param SyncConfigRequest Return the SyncConfigRequest string.
2992 GetSyncRestoreConfigRequest(
2993 IN BROWSER_STORAGE
*Storage
,
2994 IN EFI_STRING ConfigRequest
,
2995 IN EFI_STRING Progress
,
2996 OUT EFI_STRING
*RestoreConfigRequest
,
2997 OUT EFI_STRING
*SyncConfigRequest
3001 EFI_STRING ConfigHdrEndStr
;
3002 EFI_STRING ElementStr
;
3004 UINTN RestoreEleSize
;
3007 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
3009 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
3010 // Need to restore all the fields in the ConfigRequest.
3012 if (*Progress
== L
'G') {
3013 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3014 ASSERT (*RestoreConfigRequest
!= NULL
);
3019 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
3021 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3023 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
3024 // here, just keep the "Fred" string.
3026 EndStr
= StrStr (Progress
, L
"=");
3027 ASSERT (EndStr
!= NULL
);
3030 // Find the ConfigHdr in ConfigRequest.
3032 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
3033 ASSERT (ConfigHdrEndStr
!= NULL
);
3034 while (*ConfigHdrEndStr
!= L
'&') {
3039 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
3040 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
3042 EndStr
= StrStr (Progress
, L
"&VALUE=");
3043 ASSERT (EndStr
!= NULL
);
3046 // Find the ConfigHdr in ConfigRequest.
3048 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
3051 // Find the first fail pair in the ConfigRequest.
3053 ElementStr
= StrStr (ConfigRequest
, Progress
);
3054 ASSERT (ElementStr
!= NULL
);
3056 // To get the RestoreConfigRequest.
3058 RestoreEleSize
= StrSize (ElementStr
);
3059 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
3060 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
3061 ASSERT (*RestoreConfigRequest
!= NULL
);
3062 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
3063 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
3065 // To get the SyncConfigRequest.
3067 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
3068 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
3069 ASSERT (*SyncConfigRequest
!= NULL
);
3070 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
3073 // restore the Progress string to the original format.
3075 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3083 Popup an save error info and get user input.
3085 @param TitleId The form title id.
3086 @param HiiHandle The hii handle for this package.
3088 @retval UINT32 The user select option for the save fail.
3089 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3093 IN EFI_STRING_ID TitleId
,
3094 IN EFI_HII_HANDLE HiiHandle
3098 CHAR16
*StringBuffer
;
3101 FormTitle
= GetToken (TitleId
, HiiHandle
);
3103 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3104 ASSERT (StringBuffer
!= NULL
);
3108 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3109 L
"Submit Fail For Form: %s.",
3113 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3115 FreePool (StringBuffer
);
3116 FreePool (FormTitle
);
3122 Popup an NO_SUBMIT_IF error info and get user input.
3124 @param TitleId The form title id.
3125 @param HiiHandle The hii handle for this package.
3127 @retval UINT32 The user select option for the save fail.
3128 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3131 ConfirmNoSubmitFail (
3132 IN EFI_STRING_ID TitleId
,
3133 IN EFI_HII_HANDLE HiiHandle
3137 CHAR16
*StringBuffer
;
3140 FormTitle
= GetToken (TitleId
, HiiHandle
);
3142 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3143 ASSERT (StringBuffer
!= NULL
);
3147 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3148 L
"NO_SUBMIT_IF error For Form: %s.",
3152 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3154 FreePool (StringBuffer
);
3155 FreePool (FormTitle
);
3161 Discard data based on the input setting scope (Form, FormSet or System).
3163 @param FormSet FormSet data structure.
3164 @param Form Form data structure.
3165 @param SettingScope Setting Scope for Discard action.
3167 @retval EFI_SUCCESS The function completed successfully.
3168 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3173 IN FORM_BROWSER_FORMSET
*FormSet
,
3174 IN FORM_BROWSER_FORM
*Form
,
3175 IN BROWSER_SETTING_SCOPE SettingScope
3179 FORMSET_STORAGE
*Storage
;
3180 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3181 FORM_BROWSER_FORMSET
*LocalFormSet
;
3182 FORM_BROWSER_FORMSET
*OldFormSet
;
3185 // Check the supported setting level.
3187 if (SettingScope
>= MaxLevel
) {
3188 return EFI_UNSUPPORTED
;
3191 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3193 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3194 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3195 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3196 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3198 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3203 // Skip if there is no RequestElement
3205 if (ConfigInfo
->ElementCount
== 0) {
3210 // Prepare <ConfigResp>
3212 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3215 // Call callback with Changed type to inform the driver.
3217 SendDiscardInfoToDriver (FormSet
, Form
);
3220 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3221 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3224 // Discard Buffer storage or Name/Value storage
3226 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3227 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3228 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3229 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3231 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3236 // Skip if there is no RequestElement
3238 if (Storage
->ElementCount
== 0) {
3242 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3245 Link
= GetFirstNode (&FormSet
->FormListHead
);
3246 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3247 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3248 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3251 // Call callback with Changed type to inform the driver.
3253 SendDiscardInfoToDriver (FormSet
, Form
);
3256 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3257 } else if (SettingScope
== SystemLevel
) {
3259 // System Level Discard.
3261 OldFormSet
= mSystemLevelFormSet
;
3264 // Discard changed value for each FormSet in the maintain list.
3266 Link
= GetFirstNode (&gBrowserFormSetList
);
3267 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3268 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3269 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3270 if (!ValidateFormSet(LocalFormSet
)) {
3274 mSystemLevelFormSet
= LocalFormSet
;
3276 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3277 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3279 // Remove maintain backup list after discard except for the current using FormSet.
3281 CleanBrowserStorage(LocalFormSet
);
3282 RemoveEntryList (&LocalFormSet
->Link
);
3283 DestroyFormSet (LocalFormSet
);
3287 mSystemLevelFormSet
= OldFormSet
;
3294 Submit data for a form.
3296 @param FormSet FormSet data structure.
3297 @param Form Form data structure.
3299 @retval EFI_SUCCESS The function completed successfully.
3300 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3305 IN FORM_BROWSER_FORMSET
*FormSet
,
3306 IN FORM_BROWSER_FORM
*Form
3311 EFI_STRING ConfigResp
;
3312 EFI_STRING Progress
;
3313 BROWSER_STORAGE
*Storage
;
3314 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3315 BOOLEAN SubmitFormFail
;
3317 SubmitFormFail
= FALSE
;
3319 if (!IsNvUpdateRequiredForForm (Form
)) {
3323 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3324 if (EFI_ERROR (Status
)) {
3328 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3329 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3330 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3331 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3333 Storage
= ConfigInfo
->Storage
;
3334 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3339 // Skip if there is no RequestElement
3341 if (ConfigInfo
->ElementCount
== 0) {
3346 // 1. Prepare <ConfigResp>
3348 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3349 if (EFI_ERROR (Status
)) {
3354 // 2. Set value to hii config routine protocol.
3356 Status
= mHiiConfigRouting
->RouteConfig (
3362 if (EFI_ERROR (Status
)) {
3364 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3366 SubmitFormFail
= TRUE
;
3367 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3368 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3369 FreePool (ConfigResp
);
3373 FreePool (ConfigResp
);
3375 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3377 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3381 // 4. Process the save failed storage.
3383 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3384 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3385 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3386 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3387 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3388 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3390 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3391 // base on the SyncConfigRequest to Sync the buffer.
3393 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3394 FreePool (ConfigInfo
->RestoreConfigRequest
);
3395 ConfigInfo
->RestoreConfigRequest
= NULL
;
3396 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3397 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3398 FreePool (ConfigInfo
->SyncConfigRequest
);
3399 ConfigInfo
->SyncConfigRequest
= NULL
;
3402 Status
= EFI_SUCCESS
;
3404 SendDiscardInfoToDriver (FormSet
,Form
);
3406 Status
= EFI_UNSUPPORTED
;
3410 // Free Form save fail list.
3412 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3413 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3414 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3415 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3420 // 5. Update the NV flag.
3422 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3425 // 6 Call callback with Submitted type to inform the driver.
3427 if (!SubmitFormFail
) {
3428 SubmitCallback (FormSet
, Form
);
3435 Submit data for a formset.
3437 @param FormSet FormSet data structure.
3438 @param SkipProcessFail Whether skip to process the save failed storage.
3439 If submit formset is called when do system level save,
3440 set this value to true and process the failed formset
3442 if submit formset is called when do formset level save,
3443 set the value to false and process the failed storage
3444 right after process all storages for this formset.
3446 @retval EFI_SUCCESS The function completed successfully.
3447 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3452 IN FORM_BROWSER_FORMSET
*FormSet
,
3453 IN BOOLEAN SkipProcessFail
3458 EFI_STRING ConfigResp
;
3459 EFI_STRING Progress
;
3460 BROWSER_STORAGE
*Storage
;
3461 FORMSET_STORAGE
*FormSetStorage
;
3462 FORM_BROWSER_FORM
*Form
;
3463 BOOLEAN HasInserted
;
3464 FORM_BROWSER_STATEMENT
*Question
;
3465 BOOLEAN SubmitFormSetFail
;
3466 BOOLEAN DiscardChange
;
3468 HasInserted
= FALSE
;
3469 SubmitFormSetFail
= FALSE
;
3470 DiscardChange
= FALSE
;
3472 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3477 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3478 if (EFI_ERROR (Status
)) {
3479 if (SkipProcessFail
) {
3481 // Process NO_SUBMIT check first, so insert it at head.
3483 FormSet
->SaveFailForm
= Form
;
3484 FormSet
->SaveFailStatement
= Question
;
3485 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3494 // Submit Buffer storage or Name/Value storage
3496 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3497 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3498 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3499 Storage
= FormSetStorage
->BrowserStorage
;
3500 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3502 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3507 // Skip if there is no RequestElement
3509 if (FormSetStorage
->ElementCount
== 0) {
3514 // 1. Prepare <ConfigResp>
3516 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3517 if (EFI_ERROR (Status
)) {
3522 // 2. Send <ConfigResp> to Routine config Protocol.
3524 Status
= mHiiConfigRouting
->RouteConfig (
3529 if (EFI_ERROR (Status
)) {
3531 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3533 SubmitFormSetFail
= TRUE
;
3534 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3535 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3538 // Call submit formset for system level, save the formset info
3539 // and process later.
3541 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3542 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3543 FormSet
->SaveFailForm
= Form
;
3544 FormSet
->SaveFailStatement
= Question
;
3545 if (SkipProcessFail
) {
3546 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3551 FreePool (ConfigResp
);
3555 FreePool (ConfigResp
);
3557 // 3. Config success, update storage shadow Buffer
3559 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3563 // 4. Has save fail storage need to handle.
3566 if (!SkipProcessFail
) {
3568 // If not in system level, just handl the save failed storage here.
3570 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3571 DiscardChange
= TRUE
;
3572 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3573 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3574 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3575 Storage
= FormSetStorage
->BrowserStorage
;
3576 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3578 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3579 // base on the SyncConfigRequest to Sync the buffer.
3581 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3582 FreePool (FormSetStorage
->RestoreConfigRequest
);
3583 FormSetStorage
->RestoreConfigRequest
= NULL
;
3584 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3585 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3586 FreePool (FormSetStorage
->SyncConfigRequest
);
3587 FormSetStorage
->SyncConfigRequest
= NULL
;
3590 Status
= EFI_SUCCESS
;
3593 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3595 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3596 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3597 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3598 gCurrentSelection
->FormId
= Form
->FormId
;
3599 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3601 Status
= EFI_UNSUPPORTED
;
3605 // Free FormSet save fail list.
3607 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3608 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3609 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3610 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3614 // If in system level, just return error and handle the failed formset later.
3616 Status
= EFI_UNSUPPORTED
;
3621 // If user discard the change, send the discard info to driver.
3623 if (DiscardChange
) {
3624 Link
= GetFirstNode (&FormSet
->FormListHead
);
3625 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3626 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3627 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3629 // Call callback with Changed type to inform the driver.
3631 SendDiscardInfoToDriver (FormSet
, Form
);
3636 // 5. Update the NV flag.
3638 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3641 // 6. Call callback with Submitted type to inform the driver.
3643 if (!SubmitFormSetFail
) {
3644 SubmitCallback (FormSet
, NULL
);
3651 Submit data for all formsets.
3653 @retval EFI_SUCCESS The function completed successfully.
3654 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3664 LIST_ENTRY
*FormLink
;
3665 LIST_ENTRY
*StorageLink
;
3666 FORMSET_STORAGE
*FormSetStorage
;
3667 FORM_BROWSER_FORM
*Form
;
3668 FORM_BROWSER_FORMSET
*LocalFormSet
;
3669 UINT32 UserSelection
;
3670 FORM_BROWSER_STATEMENT
*Question
;
3672 mSystemSubmit
= TRUE
;
3673 Link
= GetFirstNode (&gBrowserFormSetList
);
3674 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3675 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3676 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3677 if (!ValidateFormSet(LocalFormSet
)) {
3681 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3682 if (EFI_ERROR (Status
)) {
3687 // Remove maintain backup list after save except for the current using FormSet.
3689 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3690 CleanBrowserStorage(LocalFormSet
);
3691 RemoveEntryList (&LocalFormSet
->Link
);
3692 DestroyFormSet (LocalFormSet
);
3695 mSystemSubmit
= FALSE
;
3697 Status
= EFI_SUCCESS
;
3700 // Process the save failed formsets.
3702 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3703 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3704 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3705 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3707 if (!ValidateFormSet(LocalFormSet
)) {
3711 Form
= LocalFormSet
->SaveFailForm
;
3712 Question
= LocalFormSet
->SaveFailStatement
;
3715 // Confirm with user, get user input.
3717 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3719 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3721 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3723 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3726 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3727 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3728 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3729 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3730 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3731 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3733 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3736 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3737 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3738 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3739 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3741 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3742 // base on the SyncConfigRequest to Sync the buffer.
3744 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3745 FreePool (FormSetStorage
->RestoreConfigRequest
);
3746 FormSetStorage
->RestoreConfigRequest
= NULL
;
3747 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3748 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3749 FreePool (FormSetStorage
->SyncConfigRequest
);
3750 FormSetStorage
->SyncConfigRequest
= NULL
;
3755 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3756 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3757 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3758 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3760 // Call callback with Changed type to inform the driver.
3762 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3765 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3766 CleanBrowserStorage(LocalFormSet
);
3767 RemoveEntryList (&LocalFormSet
->Link
);
3768 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3769 DestroyFormSet (LocalFormSet
);
3771 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3774 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3775 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3778 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3780 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3781 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3782 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3783 gCurrentSelection
->FormId
= Form
->FormId
;
3784 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3786 Status
= EFI_UNSUPPORTED
;
3792 // Clean the list which will not process.
3794 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3795 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3796 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3797 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3799 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3800 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3801 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3802 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3810 Submit data based on the input Setting level (Form, FormSet or System).
3812 @param FormSet FormSet data structure.
3813 @param Form Form data structure.
3814 @param SettingScope Setting Scope for Submit action.
3816 @retval EFI_SUCCESS The function completed successfully.
3817 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3822 IN FORM_BROWSER_FORMSET
*FormSet
,
3823 IN FORM_BROWSER_FORM
*Form
,
3824 IN BROWSER_SETTING_SCOPE SettingScope
3829 switch (SettingScope
) {
3831 Status
= SubmitForForm(FormSet
, Form
);
3835 Status
= SubmitForFormSet (FormSet
, FALSE
);
3839 Status
= SubmitForSystem ();
3843 Status
= EFI_UNSUPPORTED
;
3851 Converts the unicode character of the string from uppercase to lowercase.
3852 This is a internal function.
3854 @param ConfigString String to be converted
3860 IN EFI_STRING ConfigString
3866 ASSERT (ConfigString
!= NULL
);
3869 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3871 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3872 if (*String
== L
'=') {
3874 } else if (*String
== L
'&') {
3876 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3877 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3883 Find the point in the ConfigResp string for this question.
3885 @param Question The question.
3886 @param ConfigResp Get ConfigResp string.
3888 @retval point to the offset where is for this question.
3892 GetOffsetFromConfigResp (
3893 IN FORM_BROWSER_STATEMENT
*Question
,
3894 IN CHAR16
*ConfigResp
3897 CHAR16
*RequestElement
;
3901 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3903 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3904 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3905 if (RequestElement
!= NULL
) {
3907 // Skip the "VariableName=" field.
3909 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3912 return RequestElement
;
3916 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3920 // Convert all hex digits in ConfigResp to lower case before searching.
3922 HiiToLower (ConfigResp
);
3925 // 1. Directly use Question->BlockName to find.
3927 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3928 if (RequestElement
!= NULL
) {
3930 // Skip the "Question->BlockName&VALUE=" field.
3932 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3933 return RequestElement
;
3937 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3939 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3940 ASSERT (BlockData
!= NULL
);
3941 HiiToLower (BlockData
);
3942 RequestElement
= StrStr (ConfigResp
, BlockData
);
3943 FreePool (BlockData
);
3945 if (RequestElement
!= NULL
) {
3947 // Skip the "Question->BlockName&VALUE=" field.
3949 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3952 return RequestElement
;
3956 Get Question default value from AltCfg string.
3958 @param FormSet The form set.
3959 @param Form The form
3960 @param Question The question.
3962 @retval EFI_SUCCESS Question is reset to default value.
3966 GetDefaultValueFromAltCfg (
3967 IN FORM_BROWSER_FORMSET
*FormSet
,
3968 IN FORM_BROWSER_FORM
*Form
,
3969 IN OUT FORM_BROWSER_STATEMENT
*Question
3972 BROWSER_STORAGE
*Storage
;
3973 FORMSET_STORAGE
*FormSetStorage
;
3977 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3979 Storage
= Question
->Storage
;
3980 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3981 return EFI_NOT_FOUND
;
3985 // Try to get AltCfg string from form. If not found it, then
3986 // try to get it from formset.
3989 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3990 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3991 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3992 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3994 if (Storage
== ConfigInfo
->Storage
) {
3995 ConfigResp
= ConfigInfo
->ConfigAltResp
;
4000 if (ConfigResp
== NULL
) {
4001 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4002 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4003 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4004 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4006 if (Storage
== FormSetStorage
->BrowserStorage
) {
4007 ConfigResp
= FormSetStorage
->ConfigAltResp
;
4013 if (ConfigResp
== NULL
) {
4014 return EFI_NOT_FOUND
;
4017 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
4018 if (Value
== NULL
) {
4019 return EFI_NOT_FOUND
;
4022 return BufferToValue (Question
, Value
);
4026 Get default Id value used for browser.
4028 @param DefaultId The default id value used by hii.
4030 @retval Browser used default value.
4034 GetDefaultIdForCallBack (
4038 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
4039 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
4040 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4041 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
4042 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
4043 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
4044 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
4045 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
4046 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
4047 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
4048 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
4049 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
4058 Return data element in an Array by its Index.
4060 @param Array The data array.
4061 @param Type Type of the data in this array.
4062 @param Index Zero based index for data in this array.
4064 @retval Value The data to be returned
4076 ASSERT (Array
!= NULL
);
4080 case EFI_IFR_TYPE_NUM_SIZE_8
:
4081 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
4084 case EFI_IFR_TYPE_NUM_SIZE_16
:
4085 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
4088 case EFI_IFR_TYPE_NUM_SIZE_32
:
4089 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
4092 case EFI_IFR_TYPE_NUM_SIZE_64
:
4093 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
4105 Set value of a data element in an Array by its Index.
4107 @param Array The data array.
4108 @param Type Type of the data in this array.
4109 @param Index Zero based index for data in this array.
4110 @param Value The value to be set.
4122 ASSERT (Array
!= NULL
);
4125 case EFI_IFR_TYPE_NUM_SIZE_8
:
4126 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
4129 case EFI_IFR_TYPE_NUM_SIZE_16
:
4130 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
4133 case EFI_IFR_TYPE_NUM_SIZE_32
:
4134 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
4137 case EFI_IFR_TYPE_NUM_SIZE_64
:
4138 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
4147 Search an Option of a Question by its value.
4149 @param Question The Question
4150 @param OptionValue Value for Option to be searched.
4152 @retval Pointer Pointer to the found Option.
4153 @retval NULL Option not found.
4158 IN FORM_BROWSER_STATEMENT
*Question
,
4159 IN EFI_HII_VALUE
*OptionValue
4163 QUESTION_OPTION
*Option
;
4166 Link
= GetFirstNode (&Question
->OptionListHead
);
4167 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4168 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4170 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4172 // Check the suppressif condition, only a valid option can be return.
4174 if ((Option
->SuppressExpression
== NULL
) ||
4175 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4180 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4188 Reset Question to its default value.
4190 @param FormSet The form set.
4191 @param Form The form.
4192 @param Question The question.
4193 @param DefaultId The Class of the default.
4195 @retval EFI_SUCCESS Question is reset to default value.
4199 GetQuestionDefault (
4200 IN FORM_BROWSER_FORMSET
*FormSet
,
4201 IN FORM_BROWSER_FORM
*Form
,
4202 IN FORM_BROWSER_STATEMENT
*Question
,
4208 QUESTION_DEFAULT
*Default
;
4209 QUESTION_OPTION
*Option
;
4210 EFI_HII_VALUE
*HiiValue
;
4212 EFI_STRING StrValue
;
4213 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4214 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4217 EFI_IFR_TYPE_VALUE
*TypeValue
;
4218 UINT16 OriginalDefaultId
;
4219 FORMSET_DEFAULTSTORE
*DefaultStore
;
4220 LIST_ENTRY
*DefaultLink
;
4222 Status
= EFI_NOT_FOUND
;
4224 OriginalDefaultId
= DefaultId
;
4225 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4228 // Statement don't have storage, skip them
4230 if (Question
->QuestionId
== 0) {
4235 // There are Five ways to specify default value for a Question:
4236 // 1, use call back function (highest priority)
4237 // 2, use ExtractConfig function
4238 // 3, use nested EFI_IFR_DEFAULT
4239 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4240 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4243 HiiValue
= &Question
->HiiValue
;
4244 TypeValue
= &HiiValue
->Value
;
4245 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4247 // For orderedlist, need to pass the BufferValue to Callback function.
4249 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4253 // Get Question defaut value from call back function.
4255 ConfigAccess
= FormSet
->ConfigAccess
;
4256 Action
= GetDefaultIdForCallBack (DefaultId
);
4257 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4258 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4259 Status
= ConfigAccess
->Callback (
4262 Question
->QuestionId
,
4267 if (!EFI_ERROR (Status
)) {
4268 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4269 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4270 ASSERT (NewString
!= NULL
);
4272 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4273 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4274 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4275 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4277 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4280 FreePool (NewString
);
4287 // Get default value from altcfg string.
4289 if (ConfigAccess
!= NULL
) {
4290 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4291 if (!EFI_ERROR (Status
)) {
4297 // EFI_IFR_DEFAULT has highest priority
4299 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4300 Link
= GetFirstNode (&Question
->DefaultListHead
);
4301 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4302 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4304 if (Default
->DefaultId
== DefaultId
) {
4305 if (Default
->ValueExpression
!= NULL
) {
4307 // Default is provided by an Expression, evaluate it
4309 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4310 if (EFI_ERROR (Status
)) {
4314 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4315 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4316 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4317 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4318 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4320 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4321 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4323 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4325 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4326 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4329 // Default value is embedded in EFI_IFR_DEFAULT
4331 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4332 ASSERT (HiiValue
->Buffer
!= NULL
);
4333 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4335 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4339 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4340 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4341 if (StrValue
== NULL
) {
4342 return EFI_NOT_FOUND
;
4344 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4345 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4346 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4348 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4355 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4360 // EFI_ONE_OF_OPTION
4362 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4363 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4365 // OneOfOption could only provide Standard and Manufacturing default
4367 Link
= GetFirstNode (&Question
->OptionListHead
);
4368 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4369 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4370 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4372 if ((Option
->SuppressExpression
!= NULL
) &&
4373 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4377 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4378 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4380 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4389 // EFI_IFR_CHECKBOX - lowest priority
4391 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4392 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4394 // Checkbox could only provide Standard and Manufacturing default
4396 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4397 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4399 HiiValue
->Value
.b
= TRUE
;
4407 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4408 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4409 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4411 while (!IsNull(&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4412 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink
);
4413 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
,DefaultLink
);
4414 DefaultId
= DefaultStore
->DefaultId
;
4415 if (DefaultId
== OriginalDefaultId
) {
4422 // For Questions without default value for all the default id in the DefaultStoreList.
4424 Status
= EFI_NOT_FOUND
;
4425 switch (Question
->Operand
) {
4426 case EFI_IFR_CHECKBOX_OP
:
4427 HiiValue
->Value
.b
= FALSE
;
4428 Status
= EFI_SUCCESS
;
4431 case EFI_IFR_NUMERIC_OP
:
4433 // Take minimum value as numeric default value
4435 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4437 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4439 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4440 case EFI_IFR_NUMERIC_SIZE_1
:
4441 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4442 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4443 Status
= EFI_SUCCESS
;
4446 case EFI_IFR_NUMERIC_SIZE_2
:
4447 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4448 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4449 Status
= EFI_SUCCESS
;
4452 case EFI_IFR_NUMERIC_SIZE_4
:
4453 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4454 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4455 Status
= EFI_SUCCESS
;
4458 case EFI_IFR_NUMERIC_SIZE_8
:
4459 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4460 HiiValue
->Value
.u64
= Question
->Minimum
;
4461 Status
= EFI_SUCCESS
;
4468 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4469 HiiValue
->Value
.u64
= Question
->Minimum
;
4470 Status
= EFI_SUCCESS
;
4475 case EFI_IFR_ONE_OF_OP
:
4477 // Take first oneof option as oneof's default value
4479 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4480 Link
= GetFirstNode (&Question
->OptionListHead
);
4481 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4482 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4483 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4485 if ((Option
->SuppressExpression
!= NULL
) &&
4486 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4490 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4491 Status
= EFI_SUCCESS
;
4497 case EFI_IFR_ORDERED_LIST_OP
:
4499 // Take option sequence in IFR as ordered list's default value
4502 Link
= GetFirstNode (&Question
->OptionListHead
);
4503 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4504 Status
= EFI_SUCCESS
;
4505 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4506 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4508 if ((Option
->SuppressExpression
!= NULL
) &&
4509 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4513 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4516 if (Index
>= Question
->MaxContainers
) {
4530 Get AltCfg string for current form.
4532 @param FormSet Form data structure.
4533 @param Form Form data structure.
4534 @param DefaultId The Class of the default.
4535 @param BrowserStorage The input request storage for the questions.
4539 ExtractAltCfgForForm (
4540 IN FORM_BROWSER_FORMSET
*FormSet
,
4541 IN FORM_BROWSER_FORM
*Form
,
4542 IN UINT16 DefaultId
,
4543 IN BROWSER_STORAGE
*BrowserStorage
4551 BROWSER_STORAGE
*Storage
;
4552 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4553 FORMSET_STORAGE
*FormSetStorage
;
4556 // Check whether has get AltCfg string for this formset.
4557 // If yes, no need to get AltCfg for form.
4559 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4560 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4561 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4562 Storage
= FormSetStorage
->BrowserStorage
;
4563 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4564 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4568 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4569 FormSetStorage
->ElementCount
!= 0 &&
4570 FormSetStorage
->HasCallAltCfg
) {
4576 // Get AltCfg string for each form.
4578 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4579 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4580 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4581 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4583 Storage
= ConfigInfo
->Storage
;
4584 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4588 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4593 // 1. Skip if there is no RequestElement
4595 if (ConfigInfo
->ElementCount
== 0) {
4600 // 2. Get value through hii config routine protocol.
4602 Status
= mHiiConfigRouting
->ExtractConfig (
4604 ConfigInfo
->ConfigRequest
,
4608 if (EFI_ERROR (Status
)) {
4613 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4614 // Get the default configuration string according to the default ID.
4616 Status
= mHiiConfigRouting
->GetAltConfig (
4622 &DefaultId
, // it can be NULL to get the current setting.
4626 if (EFI_ERROR (Status
)) {
4630 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4635 Clean AltCfg string for current form.
4637 @param Form Form data structure.
4641 CleanAltCfgForForm (
4642 IN FORM_BROWSER_FORM
*Form
4646 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4648 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4649 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4650 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4651 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4653 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4654 FreePool (ConfigInfo
->ConfigAltResp
);
4655 ConfigInfo
->ConfigAltResp
= NULL
;
4661 Get AltCfg string for current formset.
4663 @param FormSet Form data structure.
4664 @param DefaultId The Class of the default.
4665 @param BrowserStorage The input request storage for the questions.
4669 ExtractAltCfgForFormSet (
4670 IN FORM_BROWSER_FORMSET
*FormSet
,
4671 IN UINT16 DefaultId
,
4672 IN BROWSER_STORAGE
*BrowserStorage
4680 BROWSER_STORAGE
*Storage
;
4681 FORMSET_STORAGE
*FormSetStorage
;
4683 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4684 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4685 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4686 Storage
= FormSetStorage
->BrowserStorage
;
4687 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4689 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4693 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4698 // 1. Skip if there is no RequestElement
4700 if (FormSetStorage
->ElementCount
== 0) {
4704 FormSetStorage
->HasCallAltCfg
= TRUE
;
4707 // 2. Get value through hii config routine protocol.
4709 Status
= mHiiConfigRouting
->ExtractConfig (
4711 FormSetStorage
->ConfigRequest
,
4715 if (EFI_ERROR (Status
)) {
4720 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4721 // Get the default configuration string according to the default ID.
4723 Status
= mHiiConfigRouting
->GetAltConfig (
4729 &DefaultId
, // it can be NULL to get the current setting.
4734 if (EFI_ERROR (Status
)) {
4738 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4744 Clean AltCfg string for current formset.
4746 @param FormSet Form data structure.
4750 CleanAltCfgForFormSet (
4751 IN FORM_BROWSER_FORMSET
*FormSet
4755 FORMSET_STORAGE
*FormSetStorage
;
4757 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4758 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4759 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4760 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4762 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4763 FreePool (FormSetStorage
->ConfigAltResp
);
4764 FormSetStorage
->ConfigAltResp
= NULL
;
4767 FormSetStorage
->HasCallAltCfg
= FALSE
;
4772 Reset Questions to their initial value or default value in a Form, Formset or System.
4774 GetDefaultValueScope parameter decides which questions will reset
4775 to its default value.
4777 @param FormSet FormSet data structure.
4778 @param Form Form data structure.
4779 @param DefaultId The Class of the default.
4780 @param SettingScope Setting Scope for Default action.
4781 @param GetDefaultValueScope Get default value scope.
4782 @param Storage Get default value only for this storage.
4783 @param RetrieveValueFirst Whether call the retrieve call back to
4784 get the initial value before get default
4786 @param SkipGetAltCfg Whether skip the get altcfg string process.
4788 @retval EFI_SUCCESS The function completed successfully.
4789 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4794 IN FORM_BROWSER_FORMSET
*FormSet
,
4795 IN FORM_BROWSER_FORM
*Form
,
4796 IN UINT16 DefaultId
,
4797 IN BROWSER_SETTING_SCOPE SettingScope
,
4798 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4799 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4800 IN BOOLEAN RetrieveValueFirst
,
4801 IN BOOLEAN SkipGetAltCfg
4805 LIST_ENTRY
*FormLink
;
4807 FORM_BROWSER_STATEMENT
*Question
;
4808 FORM_BROWSER_FORMSET
*LocalFormSet
;
4809 FORM_BROWSER_FORMSET
*OldFormSet
;
4811 Status
= EFI_SUCCESS
;
4814 // Check the supported setting level.
4816 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4817 return EFI_UNSUPPORTED
;
4820 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4821 return EFI_UNSUPPORTED
;
4824 if (SettingScope
== FormLevel
) {
4826 // Prepare the AltCfg String for form.
4828 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4829 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4833 // Extract Form default
4835 Link
= GetFirstNode (&Form
->StatementListHead
);
4836 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4837 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4838 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4841 // If get default value only for this storage, check the storage first.
4843 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4848 // If get default value only for no storage question, just skip the question which has storage.
4850 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4855 // If Question is disabled, don't reset it to default
4857 if (Question
->Expression
!= NULL
) {
4858 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4863 if (RetrieveValueFirst
) {
4865 // Call the Retrieve call back to get the initial question value.
4867 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4871 // If not request to get the initial value or get initial value fail, then get default value.
4873 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4874 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4875 if (EFI_ERROR (Status
)) {
4881 // Synchronize Buffer storage's Edit buffer
4883 if ((Question
->Storage
!= NULL
) &&
4884 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4885 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4890 // Clean the AltCfg String.
4892 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4893 CleanAltCfgForForm(Form
);
4895 } else if (SettingScope
== FormSetLevel
) {
4897 // Prepare the AltCfg String for formset.
4899 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4900 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4903 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4904 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4905 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4906 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4907 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4911 // Clean the AltCfg String.
4913 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4914 CleanAltCfgForFormSet (FormSet
);
4916 } else if (SettingScope
== SystemLevel
) {
4918 // Preload all Hii formset.
4920 LoadAllHiiFormset();
4922 OldFormSet
= mSystemLevelFormSet
;
4925 // Set Default Value for each FormSet in the maintain list.
4927 Link
= GetFirstNode (&gBrowserFormSetList
);
4928 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4929 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4930 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4931 if (!ValidateFormSet(LocalFormSet
)) {
4935 mSystemLevelFormSet
= LocalFormSet
;
4937 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4940 mSystemLevelFormSet
= OldFormSet
;
4948 Validate whether this question's value has changed.
4950 @param FormSet FormSet data structure.
4951 @param Form Form data structure.
4952 @param Question Question to be initialized.
4953 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4955 @retval TRUE Question's value has changed.
4956 @retval FALSE Question's value has not changed
4960 IsQuestionValueChanged (
4961 IN FORM_BROWSER_FORMSET
*FormSet
,
4962 IN FORM_BROWSER_FORM
*Form
,
4963 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4964 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4967 EFI_HII_VALUE BackUpValue
;
4968 CHAR8
*BackUpBuffer
;
4969 EFI_HII_VALUE BackUpValue2
;
4970 CHAR8
*BackUpBuffer2
;
4972 BOOLEAN ValueChanged
;
4976 // For quetion without storage, always mark it as data not changed.
4978 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4982 BackUpBuffer
= NULL
;
4983 BackUpBuffer2
= NULL
;
4984 ValueChanged
= FALSE
;
4986 switch (Question
->Operand
) {
4987 case EFI_IFR_ORDERED_LIST_OP
:
4988 BufferWidth
= Question
->StorageWidth
;
4989 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4990 ASSERT (BackUpBuffer
!= NULL
);
4993 case EFI_IFR_STRING_OP
:
4994 case EFI_IFR_PASSWORD_OP
:
4995 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4996 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4997 ASSERT (BackUpBuffer
!= NULL
);
5004 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5006 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
5007 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5008 ASSERT_EFI_ERROR(Status
);
5010 switch (Question
->Operand
) {
5011 case EFI_IFR_ORDERED_LIST_OP
:
5012 BufferWidth
= Question
->StorageWidth
;
5013 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5014 ASSERT (BackUpBuffer2
!= NULL
);
5017 case EFI_IFR_STRING_OP
:
5018 case EFI_IFR_PASSWORD_OP
:
5019 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
5020 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5021 ASSERT (BackUpBuffer2
!= NULL
);
5028 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5030 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
5031 ASSERT_EFI_ERROR(Status
);
5033 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5034 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
5035 ValueChanged
= TRUE
;
5038 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
5039 ASSERT_EFI_ERROR(Status
);
5041 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5042 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
5043 ValueChanged
= TRUE
;
5047 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
5048 if (BackUpBuffer
!= NULL
) {
5049 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
5050 FreePool (BackUpBuffer
);
5053 if (BackUpBuffer2
!= NULL
) {
5054 FreePool (BackUpBuffer2
);
5057 Question
->ValueChanged
= ValueChanged
;
5059 return ValueChanged
;
5063 Initialize Question's Edit copy from Storage.
5065 @param Selection Selection contains the information about
5066 the Selection, form and formset to be displayed.
5067 Selection action may be updated in retrieve callback.
5068 If Selection is NULL, only initialize Question value.
5069 @param FormSet FormSet data structure.
5070 @param Form Form data structure.
5072 @retval EFI_SUCCESS The function completed successfully.
5077 IN OUT UI_MENU_SELECTION
*Selection
,
5078 IN FORM_BROWSER_FORMSET
*FormSet
,
5079 IN FORM_BROWSER_FORM
*Form
5084 FORM_BROWSER_STATEMENT
*Question
;
5086 Link
= GetFirstNode (&Form
->StatementListHead
);
5087 while (!IsNull (&Form
->StatementListHead
, Link
)) {
5088 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
5091 // Initialize local copy of Value for each Question
5093 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
5094 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
5096 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5098 if (EFI_ERROR (Status
)) {
5102 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5103 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5106 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5113 Initialize Question's Edit copy from Storage for the whole Formset.
5115 @param Selection Selection contains the information about
5116 the Selection, form and formset to be displayed.
5117 Selection action may be updated in retrieve callback.
5118 If Selection is NULL, only initialize Question value.
5119 @param FormSet FormSet data structure.
5121 @retval EFI_SUCCESS The function completed successfully.
5126 IN OUT UI_MENU_SELECTION
*Selection
,
5127 IN FORM_BROWSER_FORMSET
*FormSet
5132 FORM_BROWSER_FORM
*Form
;
5134 Link
= GetFirstNode (&FormSet
->FormListHead
);
5135 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5136 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5139 // Initialize local copy of Value for each Form
5141 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5142 if (EFI_ERROR (Status
)) {
5146 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5150 // Finished question initialization.
5152 FormSet
->QuestionInited
= TRUE
;
5158 Remove the Request element from the Config Request.
5160 @param Storage Pointer to the browser storage.
5161 @param RequestElement The pointer to the Request element.
5166 IN OUT BROWSER_STORAGE
*Storage
,
5167 IN CHAR16
*RequestElement
5173 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5175 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5177 if (NewStr
== NULL
) {
5182 // Remove this element from this ConfigRequest.
5185 NewStr
+= StrLen (RequestElement
);
5186 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5188 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5192 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5194 @param Storage Pointer to the formset storage.
5195 @param ConfigRequest The pointer to the Request element.
5199 RemoveConfigRequest (
5200 FORMSET_STORAGE
*Storage
,
5201 CHAR16
*ConfigRequest
5204 CHAR16
*RequestElement
;
5205 CHAR16
*NextRequestElement
;
5209 // No request element in it, just return.
5211 if (ConfigRequest
== NULL
) {
5215 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5217 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5222 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5224 SearchKey
= L
"&OFFSET";
5228 // Find SearchKey storage
5230 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5231 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5232 ASSERT (RequestElement
!= NULL
);
5233 RequestElement
= StrStr (RequestElement
, SearchKey
);
5235 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5238 while (RequestElement
!= NULL
) {
5240 // +1 to avoid find header itself.
5242 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5245 // The last Request element in configRequest string.
5247 if (NextRequestElement
!= NULL
) {
5249 // Replace "&" with '\0'.
5251 *NextRequestElement
= L
'\0';
5254 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5256 if (NextRequestElement
!= NULL
) {
5258 // Restore '&' with '\0' for later used.
5260 *NextRequestElement
= L
'&';
5263 RequestElement
= NextRequestElement
;
5267 // If no request element remain, just remove the ConfigRequest string.
5269 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5270 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5271 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5272 Storage
->BrowserStorage
->SpareStrLen
= 0;
5277 Base on the current formset info, clean the ConfigRequest string in browser storage.
5279 @param FormSet Pointer of the FormSet
5283 CleanBrowserStorage (
5284 IN OUT FORM_BROWSER_FORMSET
*FormSet
5288 FORMSET_STORAGE
*Storage
;
5290 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5291 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5292 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5293 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5295 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5296 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5300 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5301 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5302 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5303 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5304 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5305 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5307 Storage
->BrowserStorage
->Initialized
= FALSE
;
5313 Check whether current element in the ConfigReqeust string.
5315 @param BrowserStorage Storage which includes ConfigReqeust.
5316 @param RequestElement New element need to check.
5318 @retval TRUE The Element is in the ConfigReqeust string.
5319 @retval FALSE The Element not in the configReqeust String.
5324 BROWSER_STORAGE
*BrowserStorage
,
5325 CHAR16
*RequestElement
5328 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5332 Append the Request element to the Config Request.
5334 @param ConfigRequest Current ConfigRequest info.
5335 @param SpareStrLen Current remain free buffer for config reqeust.
5336 @param RequestElement New Request element.
5340 AppendConfigRequest (
5341 IN OUT CHAR16
**ConfigRequest
,
5342 IN OUT UINTN
*SpareStrLen
,
5343 IN CHAR16
*RequestElement
5351 StrLength
= StrLen (RequestElement
);
5352 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5353 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5356 // Append <RequestElement> to <ConfigRequest>
5358 if (StrLength
> *SpareStrLen
) {
5360 // Old String buffer is not sufficient for RequestElement, allocate a new one
5362 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5363 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5364 ASSERT (NewStr
!= NULL
);
5366 if (*ConfigRequest
!= NULL
) {
5367 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5368 FreePool (*ConfigRequest
);
5370 *ConfigRequest
= NewStr
;
5371 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5374 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5375 *SpareStrLen
-= StrLength
;
5379 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5381 @param Storage Form set Storage.
5382 @param Request The input request string.
5383 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5385 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5386 @retval FALSE All elements covered by current used elements.
5390 ConfigRequestAdjust (
5391 IN BROWSER_STORAGE
*Storage
,
5393 IN BOOLEAN RespString
5396 CHAR16
*RequestElement
;
5397 CHAR16
*NextRequestElement
;
5398 CHAR16
*NextElementBakup
;
5402 CHAR16
*ConfigRequest
;
5405 NextElementBakup
= NULL
;
5408 if (Request
!= NULL
) {
5409 ConfigRequest
= Request
;
5411 ConfigRequest
= Storage
->ConfigRequest
;
5414 if (Storage
->ConfigRequest
== NULL
) {
5415 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5419 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5421 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5426 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5428 SearchKey
= L
"&OFFSET";
5429 ValueKey
= L
"&VALUE";
5433 // Find SearchKey storage
5435 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5436 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5437 ASSERT (RequestElement
!= NULL
);
5438 RequestElement
= StrStr (RequestElement
, SearchKey
);
5440 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5443 while (RequestElement
!= NULL
) {
5446 // +1 to avoid find header itself.
5448 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5451 // The last Request element in configRequest string.
5453 if (NextRequestElement
!= NULL
) {
5454 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5455 NextElementBakup
= NextRequestElement
;
5456 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5457 ASSERT (NextRequestElement
!= NULL
);
5460 // Replace "&" with '\0'.
5462 *NextRequestElement
= L
'\0';
5464 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5465 NextElementBakup
= NextRequestElement
;
5466 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5467 ASSERT (NextRequestElement
!= NULL
);
5469 // Replace "&" with '\0'.
5471 *NextRequestElement
= L
'\0';
5475 if (!ElementValidation (Storage
, RequestElement
)) {
5477 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5479 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5483 if (NextRequestElement
!= NULL
) {
5485 // Restore '&' with '\0' for later used.
5487 *NextRequestElement
= L
'&';
5490 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5491 RequestElement
= NextElementBakup
;
5493 RequestElement
= NextRequestElement
;
5501 Fill storage's edit copy with settings requested from Configuration Driver.
5503 @param FormSet FormSet data structure.
5504 @param Storage Buffer Storage.
5509 IN FORM_BROWSER_FORMSET
*FormSet
,
5510 IN FORMSET_STORAGE
*Storage
5514 EFI_STRING Progress
;
5517 EFI_STRING ConfigRequest
;
5520 ConfigRequest
= NULL
;
5522 switch (Storage
->BrowserStorage
->Type
) {
5523 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5526 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5527 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5528 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5533 case EFI_HII_VARSTORE_BUFFER
:
5534 case EFI_HII_VARSTORE_NAME_VALUE
:
5536 // Skip if there is no RequestElement.
5538 if (Storage
->ElementCount
== 0) {
5543 // Just update the ConfigRequest, if storage already initialized.
5545 if (Storage
->BrowserStorage
->Initialized
) {
5546 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5550 Storage
->BrowserStorage
->Initialized
= TRUE
;
5557 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5559 // Create the config request string to get all fields for this storage.
5560 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5561 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5563 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5564 ConfigRequest
= AllocateZeroPool (StrLen
);
5565 ASSERT (ConfigRequest
!= NULL
);
5569 L
"%s&OFFSET=0&WIDTH=%04x",
5571 Storage
->BrowserStorage
->Size
);
5573 ConfigRequest
= Storage
->ConfigRequest
;
5577 // Request current settings from Configuration Driver
5579 Status
= mHiiConfigRouting
->ExtractConfig (
5587 // If get value fail, extract default from IFR binary
5589 if (EFI_ERROR (Status
)) {
5590 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5593 // Convert Result from <ConfigAltResp> to <ConfigResp>
5595 StrPtr
= StrStr (Result
, L
"&GUID=");
5596 if (StrPtr
!= NULL
) {
5600 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5604 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5607 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5609 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5611 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5612 if (ConfigRequest
!= NULL
) {
5613 FreePool (ConfigRequest
);
5619 Get Value changed status from old question.
5621 @param NewFormSet FormSet data structure.
5622 @param OldQuestion Old question which has value changed.
5626 SyncStatusForQuestion (
5627 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5628 IN FORM_BROWSER_STATEMENT
*OldQuestion
5632 LIST_ENTRY
*QuestionLink
;
5633 FORM_BROWSER_FORM
*Form
;
5634 FORM_BROWSER_STATEMENT
*Question
;
5637 // For each form in one formset.
5639 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5640 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5641 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5642 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5645 // for each question in one form.
5647 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5648 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5649 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5650 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5652 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5653 Question
->ValueChanged
= TRUE
;
5661 Get Value changed status from old formset.
5663 @param NewFormSet FormSet data structure.
5664 @param OldFormSet FormSet data structure.
5668 SyncStatusForFormSet (
5669 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5670 IN FORM_BROWSER_FORMSET
*OldFormSet
5674 LIST_ENTRY
*QuestionLink
;
5675 FORM_BROWSER_FORM
*Form
;
5676 FORM_BROWSER_STATEMENT
*Question
;
5679 // For each form in one formset.
5681 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5682 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5683 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5684 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5687 // for each question in one form.
5689 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5690 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5691 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5692 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5694 if (!Question
->ValueChanged
) {
5699 // Find the same question in new formset and update the value changed flag.
5701 SyncStatusForQuestion (NewFormSet
, Question
);
5707 Get current setting of Questions.
5709 @param FormSet FormSet data structure.
5713 InitializeCurrentSetting (
5714 IN OUT FORM_BROWSER_FORMSET
*FormSet
5718 FORMSET_STORAGE
*Storage
;
5719 FORM_BROWSER_FORMSET
*OldFormSet
;
5722 // Try to find pre FormSet in the maintain backup list.
5723 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5725 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5726 if (OldFormSet
!= NULL
) {
5727 SyncStatusForFormSet (FormSet
, OldFormSet
);
5728 RemoveEntryList (&OldFormSet
->Link
);
5729 DestroyFormSet (OldFormSet
);
5731 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5734 // Extract default from IFR binary for no storage questions.
5736 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5739 // Request current settings from Configuration Driver
5741 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5742 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5743 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5745 LoadStorage (FormSet
, Storage
);
5747 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5753 Fetch the Ifr binary data of a FormSet.
5755 @param Handle PackageList Handle
5756 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5757 specified (NULL or zero GUID), take the first
5758 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5759 found in package list.
5760 On output, GUID of the formset found(if not NULL).
5761 @param BinaryLength The length of the FormSet IFR binary.
5762 @param BinaryData The buffer designed to receive the FormSet.
5764 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5765 BufferLength was updated.
5766 @retval EFI_INVALID_PARAMETER The handle is unknown.
5767 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5768 be found with the requested FormId.
5773 IN EFI_HII_HANDLE Handle
,
5774 IN OUT EFI_GUID
*FormSetGuid
,
5775 OUT UINTN
*BinaryLength
,
5776 OUT UINT8
**BinaryData
5780 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5786 UINT32 PackageListLength
;
5787 EFI_HII_PACKAGE_HEADER PackageHeader
;
5789 UINT8 NumberOfClassGuid
;
5790 BOOLEAN ClassGuidMatch
;
5791 EFI_GUID
*ClassGuid
;
5792 EFI_GUID
*ComparingGuid
;
5796 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5799 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5801 if (FormSetGuid
== NULL
) {
5802 ComparingGuid
= &gZeroGuid
;
5804 ComparingGuid
= FormSetGuid
;
5808 // Get HII PackageList
5811 HiiPackageList
= NULL
;
5812 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5813 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5814 HiiPackageList
= AllocatePool (BufferSize
);
5815 ASSERT (HiiPackageList
!= NULL
);
5817 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5819 if (EFI_ERROR (Status
)) {
5822 ASSERT (HiiPackageList
!= NULL
);
5825 // Get Form package from this HII package List
5827 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5829 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5831 ClassGuidMatch
= FALSE
;
5832 while (Offset
< PackageListLength
) {
5833 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5834 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5836 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5838 // Search FormSet in this Form Package
5840 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5841 while (Offset2
< PackageHeader
.Length
) {
5842 OpCodeData
= Package
+ Offset2
;
5844 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5846 // Try to compare against formset GUID
5848 if (IsZeroGuid (ComparingGuid
) ||
5849 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5853 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5855 // Try to compare against formset class GUID
5857 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5858 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5859 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5860 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5861 ClassGuidMatch
= TRUE
;
5865 if (ClassGuidMatch
) {
5868 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5869 ClassGuidMatch
= TRUE
;
5874 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5877 if (Offset2
< PackageHeader
.Length
) {
5879 // Target formset found
5885 Offset
+= PackageHeader
.Length
;
5888 if (Offset
>= PackageListLength
) {
5890 // Form package not found in this Package List
5892 FreePool (HiiPackageList
);
5893 return EFI_NOT_FOUND
;
5896 if (FormSetGuid
!= NULL
) {
5898 // Return the FormSet GUID
5900 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5904 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5905 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5906 // of the Form Package.
5908 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5909 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5911 FreePool (HiiPackageList
);
5913 if (*BinaryData
== NULL
) {
5914 return EFI_OUT_OF_RESOURCES
;
5922 Initialize the internal data structure of a FormSet.
5924 @param Handle PackageList Handle
5925 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5926 specified (NULL or zero GUID), take the first
5927 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5928 found in package list.
5929 On output, GUID of the formset found(if not NULL).
5930 @param FormSet FormSet data structure.
5932 @retval EFI_SUCCESS The function completed successfully.
5933 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5938 IN EFI_HII_HANDLE Handle
,
5939 IN OUT EFI_GUID
*FormSetGuid
,
5940 OUT FORM_BROWSER_FORMSET
*FormSet
5944 EFI_HANDLE DriverHandle
;
5946 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5947 if (EFI_ERROR (Status
)) {
5951 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5952 FormSet
->HiiHandle
= Handle
;
5953 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5954 FormSet
->QuestionInited
= FALSE
;
5957 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5959 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5960 if (EFI_ERROR (Status
)) {
5963 FormSet
->DriverHandle
= DriverHandle
;
5964 Status
= gBS
->HandleProtocol (
5966 &gEfiHiiConfigAccessProtocolGuid
,
5967 (VOID
**) &FormSet
->ConfigAccess
5969 if (EFI_ERROR (Status
)) {
5971 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5972 // list, then there will be no configuration action required
5974 FormSet
->ConfigAccess
= NULL
;
5978 // Parse the IFR binary OpCodes
5980 Status
= ParseOpCodes (FormSet
);
5987 Save globals used by previous call to SendForm(). SendForm() may be called from
5988 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5989 So, save globals of previous call to SendForm() and restore them upon exit.
5993 SaveBrowserContext (
5997 BROWSER_CONTEXT
*Context
;
5998 FORM_ENTRY_INFO
*MenuList
;
5999 FORM_BROWSER_FORMSET
*FormSet
;
6001 gBrowserContextCount
++;
6002 if (gBrowserContextCount
== 1) {
6004 // This is not reentry of SendForm(), no context to save
6009 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
6010 ASSERT (Context
!= NULL
);
6012 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
6015 // Save FormBrowser context
6017 Context
->Selection
= gCurrentSelection
;
6018 Context
->ResetRequired
= gResetRequiredFormLevel
;
6019 Context
->FlagReconnect
= gFlagReconnect
;
6020 Context
->CallbackReconnect
= gCallbackReconnect
;
6021 Context
->ExitRequired
= gExitRequired
;
6022 Context
->HiiHandle
= mCurrentHiiHandle
;
6023 Context
->FormId
= mCurrentFormId
;
6024 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
6025 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
6026 Context
->CurFakeQestId
= mCurFakeQestId
;
6027 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
6028 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
6031 // Save the menu history data.
6033 InitializeListHead(&Context
->FormHistoryList
);
6034 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
6035 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
6036 RemoveEntryList (&MenuList
->Link
);
6038 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
6042 // Save formset list.
6044 InitializeListHead(&Context
->FormSetList
);
6045 while (!IsListEmpty (&gBrowserFormSetList
)) {
6046 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
6047 RemoveEntryList (&FormSet
->Link
);
6049 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
6053 // Insert to FormBrowser context list
6055 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
6060 Restore globals used by previous call to SendForm().
6064 RestoreBrowserContext (
6069 BROWSER_CONTEXT
*Context
;
6070 FORM_ENTRY_INFO
*MenuList
;
6071 FORM_BROWSER_FORMSET
*FormSet
;
6073 ASSERT (gBrowserContextCount
!= 0);
6074 gBrowserContextCount
--;
6075 if (gBrowserContextCount
== 0) {
6077 // This is not reentry of SendForm(), no context to restore
6082 ASSERT (!IsListEmpty (&gBrowserContextList
));
6084 Link
= GetFirstNode (&gBrowserContextList
);
6085 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6088 // Restore FormBrowser context
6090 gCurrentSelection
= Context
->Selection
;
6091 gResetRequiredFormLevel
= Context
->ResetRequired
;
6092 gFlagReconnect
= Context
->FlagReconnect
;
6093 gCallbackReconnect
= Context
->CallbackReconnect
;
6094 gExitRequired
= Context
->ExitRequired
;
6095 mCurrentHiiHandle
= Context
->HiiHandle
;
6096 mCurrentFormId
= Context
->FormId
;
6097 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6098 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6099 mCurFakeQestId
= Context
->CurFakeQestId
;
6100 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6101 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6104 // Restore the menu history data.
6106 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6107 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6108 RemoveEntryList (&MenuList
->Link
);
6110 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6114 // Restore the Formset data.
6116 while (!IsListEmpty (&Context
->FormSetList
)) {
6117 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6118 RemoveEntryList (&FormSet
->Link
);
6120 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
6124 // Remove from FormBrowser context list
6126 RemoveEntryList (&Context
->Link
);
6127 gBS
->FreePool (Context
);
6131 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6133 @param Handle The Hii Handle.
6135 @return the found FormSet context. If no found, NULL will return.
6138 FORM_BROWSER_FORMSET
*
6139 GetFormSetFromHiiHandle (
6140 EFI_HII_HANDLE Handle
6144 FORM_BROWSER_FORMSET
*FormSet
;
6146 Link
= GetFirstNode (&gBrowserFormSetList
);
6147 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6148 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6149 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6150 if (!ValidateFormSet(FormSet
)) {
6153 if (FormSet
->HiiHandle
== Handle
) {
6162 Check whether the input HII handle is the FormSet that is being used.
6164 @param Handle The Hii Handle.
6166 @retval TRUE HII handle is being used.
6167 @retval FALSE HII handle is not being used.
6171 IsHiiHandleInBrowserContext (
6172 EFI_HII_HANDLE Handle
6176 BROWSER_CONTEXT
*Context
;
6179 // HiiHandle is Current FormSet.
6181 if (mCurrentHiiHandle
== Handle
) {
6186 // Check whether HiiHandle is in BrowserContext.
6188 Link
= GetFirstNode (&gBrowserContextList
);
6189 while (!IsNull (&gBrowserContextList
, Link
)) {
6190 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6191 if (Context
->HiiHandle
== Handle
) {
6193 // HiiHandle is in BrowserContext
6197 Link
= GetNextNode (&gBrowserContextList
, Link
);
6204 Perform Password check.
6205 Passwork may be encrypted by driver that requires the specific check.
6207 @param Form Form where Password Statement is in.
6208 @param Statement Password statement
6209 @param PasswordString Password string to be checked. It may be NULL.
6210 NULL means to restore password.
6211 "" string can be used to checked whether old password does exist.
6213 @return Status Status of Password check.
6218 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6219 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6220 IN EFI_STRING PasswordString OPTIONAL
6224 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6225 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6226 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6227 FORM_BROWSER_STATEMENT
*Question
;
6229 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6230 Question
= GetBrowserStatement(Statement
);
6231 ASSERT (Question
!= NULL
);
6233 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6234 if (ConfigAccess
== NULL
) {
6235 return EFI_UNSUPPORTED
;
6239 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6241 return EFI_UNSUPPORTED
;
6245 // Prepare password string in HII database
6247 if (PasswordString
!= NULL
) {
6248 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6250 IfrTypeValue
.string
= 0;
6254 // Send password to Configuration Driver for validation
6256 Status
= ConfigAccess
->Callback (
6258 EFI_BROWSER_ACTION_CHANGING
,
6259 Question
->QuestionId
,
6260 Question
->HiiValue
.Type
,
6266 // Remove password string from HII database
6268 if (PasswordString
!= NULL
) {
6269 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6276 Find the registered HotKey based on KeyData.
6278 @param[in] KeyData A pointer to a buffer that describes the keystroke
6279 information for the hot key.
6281 @return The registered HotKey context. If no found, NULL will return.
6284 GetHotKeyFromRegisterList (
6285 IN EFI_INPUT_KEY
*KeyData
6289 BROWSER_HOT_KEY
*HotKey
;
6291 Link
= GetFirstNode (&gBrowserHotKeyList
);
6292 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6293 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6294 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6297 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6304 Configure what scope the hot key will impact.
6305 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6306 If no scope is set, the default scope will be FormSet level.
6307 After all registered hot keys are removed, previous Scope can reset to another level.
6309 @param[in] Scope Scope level to be set.
6311 @retval EFI_SUCCESS Scope is set correctly.
6312 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6313 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6319 IN BROWSER_SETTING_SCOPE Scope
6322 if (Scope
>= MaxLevel
) {
6323 return EFI_INVALID_PARAMETER
;
6327 // When no hot key registered in system or on the first setting,
6328 // Scope can be set.
6330 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6331 gBrowserSettingScope
= Scope
;
6332 mBrowserScopeFirstSet
= FALSE
;
6333 } else if (Scope
!= gBrowserSettingScope
) {
6334 return EFI_UNSUPPORTED
;
6341 Register the hot key with its browser action, or unregistered the hot key.
6342 Only support hot key that is not printable character (control key, function key, etc.).
6343 If the action value is zero, the hot key will be unregistered if it has been registered.
6344 If the same hot key has been registered, the new action and help string will override the previous ones.
6346 @param[in] KeyData A pointer to a buffer that describes the keystroke
6347 information for the hot key. Its type is EFI_INPUT_KEY to
6348 be supported by all ConsoleIn devices.
6349 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6350 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6351 @param[in] HelpString Help string that describes the hot key information.
6352 Its value may be NULL for the unregistered hot key.
6354 @retval EFI_SUCCESS Hot key is registered or unregistered.
6355 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6356 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6357 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6358 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6363 IN EFI_INPUT_KEY
*KeyData
,
6365 IN UINT16 DefaultId
,
6366 IN EFI_STRING HelpString OPTIONAL
6369 BROWSER_HOT_KEY
*HotKey
;
6372 // Check input parameters.
6374 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6375 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6376 return EFI_INVALID_PARAMETER
;
6380 // Check whether the input KeyData is in BrowserHotKeyList.
6382 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6385 // Unregister HotKey
6387 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6388 if (HotKey
!= NULL
) {
6390 // The registered HotKey is found.
6391 // Remove it from List, and free its resource.
6393 RemoveEntryList (&HotKey
->Link
);
6394 FreePool (HotKey
->KeyData
);
6395 FreePool (HotKey
->HelpString
);
6399 // The registered HotKey is not found.
6401 return EFI_NOT_FOUND
;
6405 if (HotKey
!= NULL
) {
6406 return EFI_ALREADY_STARTED
;
6410 // Create new Key, and add it into List.
6412 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6413 ASSERT (HotKey
!= NULL
);
6414 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6415 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6416 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6419 // Fill HotKey information.
6421 HotKey
->Action
= Action
;
6422 HotKey
->DefaultId
= DefaultId
;
6423 if (HotKey
->HelpString
!= NULL
) {
6424 FreePool (HotKey
->HelpString
);
6426 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6432 Register Exit handler function.
6433 When more than one handler function is registered, the latter one will override the previous one.
6434 When NULL handler is specified, the previous Exit handler will be unregistered.
6436 @param[in] Handler Pointer to handler function.
6441 RegiserExitHandler (
6442 IN EXIT_HANDLER Handler
6445 ExitHandlerFunction
= Handler
;
6450 Check whether the browser data has been modified.
6452 @retval TRUE Browser data is modified.
6453 @retval FALSE No browser data is modified.
6458 IsBrowserDataModified (
6463 FORM_BROWSER_FORMSET
*FormSet
;
6465 switch (gBrowserSettingScope
) {
6467 if (gCurrentSelection
== NULL
) {
6470 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6473 if (gCurrentSelection
== NULL
) {
6476 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6479 Link
= GetFirstNode (&gBrowserFormSetList
);
6480 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6481 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6482 if (!ValidateFormSet(FormSet
)) {
6486 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6489 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6499 Execute the action requested by the Action parameter.
6501 @param[in] Action Execute the request action.
6502 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6504 @retval EFI_SUCCESS Execute the request action succss.
6505 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6516 FORM_BROWSER_FORMSET
*FormSet
;
6517 FORM_BROWSER_FORM
*Form
;
6519 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6520 return EFI_NOT_READY
;
6523 Status
= EFI_SUCCESS
;
6526 if (gBrowserSettingScope
< SystemLevel
) {
6527 FormSet
= gCurrentSelection
->FormSet
;
6528 Form
= gCurrentSelection
->Form
;
6532 // Executet the discard action.
6534 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6535 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6536 if (EFI_ERROR (Status
)) {
6542 // Executet the difault action.
6544 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6545 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6546 if (EFI_ERROR (Status
)) {
6549 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6553 // Executet the submit action.
6555 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6556 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6557 if (EFI_ERROR (Status
)) {
6563 // Executet the reset action.
6565 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6566 gResetRequiredFormLevel
= TRUE
;
6567 gResetRequiredSystemLevel
= TRUE
;
6571 // Executet the exit action.
6573 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6574 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6575 if (gBrowserSettingScope
== SystemLevel
) {
6576 if (ExitHandlerFunction
!= NULL
) {
6577 ExitHandlerFunction ();
6581 gExitRequired
= TRUE
;
6588 Create reminder to let user to choose save or discard the changed browser data.
6589 Caller can use it to actively check the changed browser data.
6591 @retval BROWSER_NO_CHANGES No browser data is changed.
6592 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6593 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6594 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6604 FORM_BROWSER_FORMSET
*FormSet
;
6605 BOOLEAN IsDataChanged
;
6606 UINT32 DataSavedAction
;
6609 DataSavedAction
= BROWSER_NO_CHANGES
;
6610 IsDataChanged
= FALSE
;
6611 Link
= GetFirstNode (&gBrowserFormSetList
);
6612 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6613 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6614 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6615 if (!ValidateFormSet(FormSet
)) {
6618 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6619 IsDataChanged
= TRUE
;
6625 // No data is changed. No save is required.
6627 if (!IsDataChanged
) {
6628 return DataSavedAction
;
6632 // If data is changed, prompt user to save or discard it.
6635 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6637 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6638 SubmitForm (NULL
, NULL
, SystemLevel
);
6639 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6641 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6642 DiscardForm (NULL
, NULL
, SystemLevel
);
6643 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6645 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6646 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6651 return DataSavedAction
;
6655 Check whether the Reset Required for the browser
6657 @retval TRUE Browser required to reset after exit.
6658 @retval FALSE Browser not need to reset after exit.
6667 return gResetRequiredSystemLevel
;