2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
31 BROWSER_EXTENSION2_VERSION_1_1
,
35 IsBrowserDataModified
,
43 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
44 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
45 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
46 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
48 UINTN gBrowserContextCount
= 0;
49 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
50 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
51 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
52 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
53 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
55 BOOLEAN mSystemSubmit
= FALSE
;
56 BOOLEAN gResetRequiredFormLevel
;
57 BOOLEAN gResetRequiredSystemLevel
= FALSE
;
58 BOOLEAN gExitRequired
;
59 BOOLEAN gFlagReconnect
;
60 BOOLEAN gCallbackReconnect
;
61 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
62 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
63 EXIT_HANDLER ExitHandlerFunction
= NULL
;
64 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
67 // Browser Global Strings
70 CHAR16
*mUnknownString
= L
"!";
72 extern EFI_GUID mCurrentFormSetGuid
;
73 extern EFI_HII_HANDLE mCurrentHiiHandle
;
74 extern UINT16 mCurrentFormId
;
75 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
78 Create a menu with specified formset GUID and form ID, and add it as a child
79 of the given parent menu.
81 @param HiiHandle Hii handle related to this formset.
82 @param FormSetGuid The Formset Guid of menu to be added.
83 @param FormId The Form ID of menu to be added.
84 @param QuestionId The question id of this menu to be added.
86 @return A pointer to the newly added menu or NULL if memory is insufficient.
91 IN EFI_HII_HANDLE HiiHandle
,
92 IN EFI_GUID
*FormSetGuid
,
97 FORM_ENTRY_INFO
*MenuList
;
99 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
100 if (MenuList
== NULL
) {
104 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
106 MenuList
->HiiHandle
= HiiHandle
;
107 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
108 MenuList
->FormId
= FormId
;
109 MenuList
->QuestionId
= QuestionId
;
112 // If parent is not specified, it is the root Form of a Formset
114 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
120 Return the form id for the input hiihandle and formset.
122 @param HiiHandle HiiHandle for FormSet.
123 @param FormSetGuid The Formset GUID of the menu to search.
125 @return First form's id for this form set.
130 IN EFI_HII_HANDLE HiiHandle
,
131 IN EFI_GUID
*FormSetGuid
135 FORM_BROWSER_FORM
*Form
;
137 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
138 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
144 Search Menu with given FormSetGuid and FormId in all cached menu list.
146 @param HiiHandle HiiHandle for FormSet.
147 @param FormSetGuid The Formset GUID of the menu to search.
148 @param FormId The Form ID of menu to search.
150 @return A pointer to menu found or NULL if not found.
155 IN EFI_HII_HANDLE HiiHandle
,
156 IN EFI_GUID
*FormSetGuid
,
161 FORM_ENTRY_INFO
*MenuList
;
162 FORM_ENTRY_INFO
*RetMenu
;
163 EFI_FORM_ID FirstFormId
;
167 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
168 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
169 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
170 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
173 // If already find the menu, free the menus behind it.
175 if (RetMenu
!= NULL
) {
176 RemoveEntryList (&MenuList
->Link
);
182 // Find the same FromSet.
184 if (MenuList
->HiiHandle
== HiiHandle
) {
185 if (IsZeroGuid (&MenuList
->FormSetGuid
)) {
187 // FormSetGuid is not specified.
190 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
191 if (MenuList
->FormId
== FormId
) {
193 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
194 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
195 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
207 Find parent menu for current menu.
209 @param CurrentMenu Current Menu
210 @param SettingLevel Whether find parent menu in Form Level or Formset level.
211 In form level, just find the parent menu;
212 In formset level, find the parent menu which has different
215 @retval The parent menu for current menu.
219 IN FORM_ENTRY_INFO
*CurrentMenu
,
220 IN BROWSER_SETTING_SCOPE SettingLevel
223 FORM_ENTRY_INFO
*ParentMenu
;
226 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
228 if (CurrentMenu
== NULL
) {
233 Link
= &CurrentMenu
->Link
;
235 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
236 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
238 if (SettingLevel
== FormLevel
) {
240 // For FormLevel, just find the parent menu, return.
245 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
247 // For SystemLevel, must find the menu which has different formset.
252 Link
= Link
->BackLink
;
256 // Not find the parent menu, just return NULL.
258 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
266 Free Menu list linked list.
268 @param MenuListHead One Menu list point in the menu list.
273 LIST_ENTRY
*MenuListHead
276 FORM_ENTRY_INFO
*MenuList
;
278 while (!IsListEmpty (MenuListHead
)) {
279 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
280 RemoveEntryList (&MenuList
->Link
);
287 Copy current Menu list to the new menu list.
289 @param NewMenuListHead New create Menu list.
290 @param CurrentMenuListHead Current Menu list.
295 OUT LIST_ENTRY
*NewMenuListHead
,
296 IN LIST_ENTRY
*CurrentMenuListHead
300 FORM_ENTRY_INFO
*MenuList
;
301 FORM_ENTRY_INFO
*NewMenuEntry
;
304 // If new menu list not empty, free it first.
306 UiFreeMenuList (NewMenuListHead
);
308 Link
= GetFirstNode (CurrentMenuListHead
);
309 while (!IsNull (CurrentMenuListHead
, Link
)) {
310 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
311 Link
= GetNextNode (CurrentMenuListHead
, Link
);
313 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
314 ASSERT (NewMenuEntry
!= NULL
);
315 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
316 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
317 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
318 NewMenuEntry
->FormId
= MenuList
->FormId
;
319 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
321 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
326 Load all hii formset to the browser.
334 FORM_BROWSER_FORMSET
*LocalFormSet
;
335 EFI_HII_HANDLE
*HiiHandles
;
339 FORM_BROWSER_FORMSET
*OldFormset
;
341 OldFormset
= mSystemLevelFormSet
;
344 // Get all the Hii handles
346 HiiHandles
= HiiGetHiiHandles (NULL
);
347 ASSERT (HiiHandles
!= NULL
);
350 // Search for formset of each class type
352 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
354 // Check HiiHandles[Index] does exist in global maintain list.
356 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
361 // Initilize FormSet Setting
363 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
364 ASSERT (LocalFormSet
!= NULL
);
365 mSystemLevelFormSet
= LocalFormSet
;
367 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
368 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
369 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
370 DestroyFormSet (LocalFormSet
);
373 InitializeCurrentSetting (LocalFormSet
);
376 // Initilize Questions' Value
378 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
379 if (EFI_ERROR (Status
)) {
380 DestroyFormSet (LocalFormSet
);
386 // Free resources, and restore gOldFormSet and gClassOfVfr
388 FreePool (HiiHandles
);
390 mSystemLevelFormSet
= OldFormset
;
394 Pop up the error info.
396 @param BrowserStatus The input browser status.
397 @param HiiHandle The Hiihandle for this opcode.
398 @param OpCode The opcode use to get the erro info and timeout value.
399 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
404 IN UINT32 BrowserStatus
,
405 IN EFI_HII_HANDLE HiiHandle
,
406 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
407 IN CHAR16
*ErrorString
410 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
411 USER_INPUT UserInputData
;
415 if (OpCode
!= NULL
) {
416 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
417 ASSERT (Statement
!= NULL
);
418 Statement
->OpCode
= OpCode
;
419 gDisplayFormData
.HighLightedStatement
= Statement
;
423 // Used to compatible with old display engine.
424 // New display engine not use this field.
426 gDisplayFormData
.ErrorString
= ErrorString
;
427 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
429 if (HiiHandle
!= NULL
) {
430 gDisplayFormData
.HiiHandle
= HiiHandle
;
433 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
435 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
436 gDisplayFormData
.ErrorString
= NULL
;
438 if (OpCode
!= NULL
) {
439 FreePool (Statement
);
442 return UserInputData
.Action
;
446 This is the routine which an external caller uses to direct the browser
447 where to obtain it's information.
450 @param This The Form Browser protocol instanse.
451 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
452 display a list of the formsets for the handles specified.
453 @param HandleCount The number of Handles specified in Handle.
454 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
455 field in the EFI_IFR_FORM_SET op-code for the specified
456 forms-based package. If FormSetGuid is NULL, then this
457 function will display the first found forms package.
458 @param FormId This field specifies which EFI_IFR_FORM to render as the first
459 displayable page. If this field has a value of 0x0000, then
460 the forms browser will render the specified forms in their encoded order.
461 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
463 @param ActionRequest Points to the action recommended by the form.
465 @retval EFI_SUCCESS The function completed successfully.
466 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
467 @retval EFI_NOT_FOUND No valid forms could be found to display.
473 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
474 IN EFI_HII_HANDLE
*Handles
,
475 IN UINTN HandleCount
,
476 IN EFI_GUID
*FormSetGuid
, OPTIONAL
477 IN UINT16 FormId
, OPTIONAL
478 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
479 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
483 UI_MENU_SELECTION
*Selection
;
485 FORM_BROWSER_FORMSET
*FormSet
;
486 FORM_ENTRY_INFO
*MenuList
;
490 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
492 if (mFormDisplay
== NULL
) {
493 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
494 return EFI_UNSUPPORTED
;
498 // Save globals used by SendForm()
500 SaveBrowserContext ();
502 gFlagReconnect
= FALSE
;
503 gResetRequiredFormLevel
= FALSE
;
504 gExitRequired
= FALSE
;
505 gCallbackReconnect
= FALSE
;
506 Status
= EFI_SUCCESS
;
508 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
510 for (Index
= 0; Index
< HandleCount
; Index
++) {
511 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
512 ASSERT (Selection
!= NULL
);
514 Selection
->Handle
= Handles
[Index
];
515 if (FormSetGuid
!= NULL
) {
516 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
517 Selection
->FormId
= FormId
;
519 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
523 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
524 ASSERT (FormSet
!= NULL
);
527 // Validate the HiiHandle
528 // if validate failed, find the first validate parent HiiHandle.
530 if (!ValidateHiiHandle(Selection
->Handle
)) {
531 FindNextMenu (Selection
, FormSetLevel
);
535 // Initialize internal data structures of FormSet
537 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
538 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
539 DestroyFormSet (FormSet
);
542 Selection
->FormSet
= FormSet
;
543 mSystemLevelFormSet
= FormSet
;
546 // Display this formset
548 gCurrentSelection
= Selection
;
550 Status
= SetupBrowser (Selection
);
552 gCurrentSelection
= NULL
;
553 mSystemLevelFormSet
= NULL
;
555 if (gFlagReconnect
|| gCallbackReconnect
) {
556 RetVal
= ReconnectController (FormSet
->DriverHandle
);
558 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
560 gFlagReconnect
= FALSE
;
561 gCallbackReconnect
= FALSE
;
565 // If no data is changed, don't need to save current FormSet into the maintain list.
567 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
568 CleanBrowserStorage(FormSet
);
569 RemoveEntryList (&FormSet
->Link
);
570 DestroyFormSet (FormSet
);
573 if (EFI_ERROR (Status
)) {
576 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
578 FreePool (Selection
);
581 if (ActionRequest
!= NULL
) {
582 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
583 if (gResetRequiredFormLevel
) {
584 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
588 mFormDisplay
->ExitDisplay();
591 // Clear the menu history data.
593 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
594 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
595 RemoveEntryList (&MenuList
->Link
);
600 // Restore globals used by SendForm()
602 RestoreBrowserContext ();
608 Get or set data to the storage.
610 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
611 @param ResultsData A string returned from an IFR browser or
612 equivalent. The results string will have no
613 routing information in them.
614 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
615 (if RetrieveData = TRUE) data from the uncommitted
616 browser state information or set (if RetrieveData
617 = FALSE) data in the uncommitted browser state
619 @param Storage The pointer to the storage.
621 @retval EFI_SUCCESS The results have been distributed or are awaiting
627 IN OUT UINTN
*ResultsDataSize
,
628 IN OUT EFI_STRING
*ResultsData
,
629 IN BOOLEAN RetrieveData
,
630 IN BROWSER_STORAGE
*Storage
639 FORMSET_STORAGE
*BrowserStorage
;
643 // Generate <ConfigResp>
645 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
646 if (EFI_ERROR (Status
)) {
651 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
652 // Also need to consider add "\0" at first time.
654 StrPtr
= StrStr (ConfigResp
, L
"PATH");
655 ASSERT (StrPtr
!= NULL
);
656 StrPtr
= StrStr (StrPtr
, L
"&");
658 BufferSize
= StrSize (StrPtr
);
661 // Copy the data if the input buffer is bigger enough.
663 if (*ResultsDataSize
>= BufferSize
) {
664 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
667 *ResultsDataSize
= BufferSize
;
668 FreePool (ConfigResp
);
671 // Prepare <ConfigResp>
673 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
674 ASSERT (BrowserStorage
!= NULL
);
675 TmpSize
= StrLen (*ResultsData
);
676 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
677 MaxLen
= BufferSize
/ sizeof (CHAR16
);
678 ConfigResp
= AllocateZeroPool (BufferSize
);
679 ASSERT (ConfigResp
!= NULL
);
681 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
682 StrCatS (ConfigResp
, MaxLen
, L
"&");
683 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
686 // Update Browser uncommited data
688 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
689 FreePool (ConfigResp
);
690 if (EFI_ERROR (Status
)) {
699 This routine called this service in the browser to retrieve or set certain uncommitted
700 state information that resides in the open formsets.
702 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
704 @param ResultsDataSize A pointer to the size of the buffer associated
706 @param ResultsData A string returned from an IFR browser or
707 equivalent. The results string will have no
708 routing information in them.
709 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
710 (if RetrieveData = TRUE) data from the uncommitted
711 browser state information or set (if RetrieveData
712 = FALSE) data in the uncommitted browser state
714 @param VariableGuid An optional field to indicate the target variable
716 @param VariableName An optional field to indicate the target
717 human-readable variable name.
719 @retval EFI_SUCCESS The results have been distributed or are awaiting
721 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
722 contain the results data.
728 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
729 IN OUT UINTN
*ResultsDataSize
,
730 IN OUT EFI_STRING ResultsData
,
731 IN BOOLEAN RetrieveData
,
732 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
733 IN CONST CHAR16
*VariableName OPTIONAL
738 BROWSER_STORAGE
*Storage
;
739 FORMSET_STORAGE
*FormsetStorage
;
743 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
744 return EFI_INVALID_PARAMETER
;
747 TotalSize
= *ResultsDataSize
;
750 Status
= EFI_SUCCESS
;
752 if (VariableGuid
!= NULL
) {
754 // Try to find target storage in the current formset.
756 Link
= GetFirstNode (&gBrowserStorageList
);
757 while (!IsNull (&gBrowserStorageList
, Link
)) {
758 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
759 Link
= GetNextNode (&gBrowserStorageList
, Link
);
761 // Check the current storage.
763 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
767 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
768 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
770 // Buffer storage require both GUID and Name
772 if (VariableName
== NULL
) {
773 return EFI_NOT_FOUND
;
776 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
781 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
782 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
783 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
784 return EFI_NOT_FOUND
;
787 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
792 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
793 if (EFI_ERROR (Status
)) {
797 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
798 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
802 // Different formsets may have same varstore, so here just set the flag
803 // not exit the circle.
810 return EFI_NOT_FOUND
;
814 // GUID/Name is not specified, take the first storage in FormSet
816 if (mSystemLevelFormSet
== NULL
) {
817 return EFI_NOT_READY
;
821 // Generate <ConfigResp>
823 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
824 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
825 return EFI_UNSUPPORTED
;
828 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
830 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
831 if (EFI_ERROR (Status
)) {
837 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
838 *ResultsDataSize
= TotalSize
;
847 Callback function for SimpleTextInEx protocol install events
849 @param Event the event that is signaled.
850 @param Context not used here.
855 FormDisplayCallback (
860 if (mFormDisplay
!= NULL
) {
864 gBS
->LocateProtocol (
865 &gEdkiiFormDisplayEngineProtocolGuid
,
867 (VOID
**) &mFormDisplay
872 Initialize Setup Browser driver.
874 @param ImageHandle The image handle.
875 @param SystemTable The system table.
877 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
878 @return Other value if failed to initialize the Setup Browser module.
884 IN EFI_HANDLE ImageHandle
,
885 IN EFI_SYSTEM_TABLE
*SystemTable
892 // Locate required Hii relative protocols
894 Status
= gBS
->LocateProtocol (
895 &gEfiHiiDatabaseProtocolGuid
,
897 (VOID
**) &mHiiDatabase
899 ASSERT_EFI_ERROR (Status
);
901 Status
= gBS
->LocateProtocol (
902 &gEfiHiiConfigRoutingProtocolGuid
,
904 (VOID
**) &mHiiConfigRouting
906 ASSERT_EFI_ERROR (Status
);
908 Status
= gBS
->LocateProtocol (
909 &gEfiDevicePathFromTextProtocolGuid
,
911 (VOID
**) &mPathFromText
915 // Install FormBrowser2 protocol
917 mPrivateData
.Handle
= NULL
;
918 Status
= gBS
->InstallProtocolInterface (
919 &mPrivateData
.Handle
,
920 &gEfiFormBrowser2ProtocolGuid
,
921 EFI_NATIVE_INTERFACE
,
922 &mPrivateData
.FormBrowser2
924 ASSERT_EFI_ERROR (Status
);
927 // Install FormBrowserEx2 protocol
929 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
930 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
931 mPrivateData
.Handle
= NULL
;
932 Status
= gBS
->InstallProtocolInterface (
933 &mPrivateData
.Handle
,
934 &gEdkiiFormBrowserEx2ProtocolGuid
,
935 EFI_NATIVE_INTERFACE
,
936 &mPrivateData
.FormBrowserEx2
938 ASSERT_EFI_ERROR (Status
);
940 Status
= gBS
->InstallProtocolInterface (
941 &mPrivateData
.Handle
,
942 &gEdkiiFormBrowserExProtocolGuid
,
943 EFI_NATIVE_INTERFACE
,
944 &mPrivateData
.FormBrowserEx
946 ASSERT_EFI_ERROR (Status
);
948 InitializeDisplayFormData ();
950 Status
= gBS
->LocateProtocol (
951 &gEdkiiFormDisplayEngineProtocolGuid
,
953 (VOID
**) &mFormDisplay
956 if (EFI_ERROR (Status
)) {
957 EfiCreateProtocolNotifyEvent (
958 &gEdkiiFormDisplayEngineProtocolGuid
,
971 Create a new string in HII Package List.
973 @param String The String to be added
974 @param HiiHandle The package list in the HII database to insert the
977 @return The output string.
983 IN EFI_HII_HANDLE HiiHandle
986 EFI_STRING_ID StringId
;
988 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
989 ASSERT (StringId
!= 0);
996 Delete a string from HII Package List.
998 @param StringId Id of the string in HII database.
999 @param HiiHandle The HII package list handle.
1001 @retval EFI_SUCCESS The string was deleted successfully.
1006 IN EFI_STRING_ID StringId
,
1007 IN EFI_HII_HANDLE HiiHandle
1012 NullChar
= CHAR_NULL
;
1013 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1019 Get the string based on the StringId and HII Package List Handle.
1021 @param Token The String's ID.
1022 @param HiiHandle The package list in the HII database to search for
1023 the specified string.
1025 @return The output string.
1030 IN EFI_STRING_ID Token
,
1031 IN EFI_HII_HANDLE HiiHandle
1036 if (HiiHandle
== NULL
) {
1040 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1041 if (String
== NULL
) {
1042 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1043 ASSERT (String
!= NULL
);
1045 return (CHAR16
*) String
;
1050 Allocate new memory and then copy the Unicode string Source to Destination.
1052 @param Dest Location to copy string
1053 @param Src String to copy
1058 IN OUT CHAR16
**Dest
,
1062 if (*Dest
!= NULL
) {
1065 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1066 ASSERT (*Dest
!= NULL
);
1071 Allocate new memory and concatinate Source on the end of Destination.
1073 @param Dest String to added to the end of.
1074 @param Src String to concatinate.
1079 IN OUT CHAR16
**Dest
,
1086 if (*Dest
== NULL
) {
1087 NewStringCpy (Dest
, Src
);
1091 MaxLen
= ( StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1092 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1093 ASSERT (NewString
!= NULL
);
1095 StrCpyS (NewString
, MaxLen
, *Dest
);
1096 StrCatS (NewString
, MaxLen
, Src
);
1103 Get Value for given Name from a NameValue Storage.
1105 @param Storage The NameValue Storage.
1106 @param Name The Name.
1107 @param Value The retured Value.
1108 @param GetValueFrom Where to get source value, from EditValue or Value.
1110 @retval EFI_SUCCESS Value found for given Name.
1111 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1116 IN BROWSER_STORAGE
*Storage
,
1118 IN OUT CHAR16
**Value
,
1119 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1123 NAME_VALUE_NODE
*Node
;
1125 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1126 return EFI_INVALID_PARAMETER
;
1131 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1132 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1133 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1135 if (StrCmp (Name
, Node
->Name
) == 0) {
1136 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1137 NewStringCpy (Value
, Node
->EditValue
);
1139 NewStringCpy (Value
, Node
->Value
);
1144 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1147 return EFI_NOT_FOUND
;
1152 Set Value of given Name in a NameValue Storage.
1154 @param Storage The NameValue Storage.
1155 @param Name The Name.
1156 @param Value The Value to set.
1157 @param SetValueTo Whether update editValue or Value.
1158 @param ReturnNode The node use the input name.
1160 @retval EFI_SUCCESS Value found for given Name.
1161 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1166 IN BROWSER_STORAGE
*Storage
,
1169 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1170 OUT NAME_VALUE_NODE
**ReturnNode
1174 NAME_VALUE_NODE
*Node
;
1177 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1178 return EFI_INVALID_PARAMETER
;
1181 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1182 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1183 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1185 if (StrCmp (Name
, Node
->Name
) == 0) {
1186 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1187 Buffer
= Node
->EditValue
;
1189 Buffer
= Node
->Value
;
1191 if (Buffer
!= NULL
) {
1194 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1195 ASSERT (Buffer
!= NULL
);
1196 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1197 Node
->EditValue
= Buffer
;
1199 Node
->Value
= Buffer
;
1202 if (ReturnNode
!= NULL
) {
1209 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1212 return EFI_NOT_FOUND
;
1217 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1219 @param Storage The Storage to be conveted.
1220 @param ConfigResp The returned <ConfigResp>.
1221 @param ConfigRequest The ConfigRequest string.
1222 @param GetEditBuf Get the data from editbuffer or buffer.
1224 @retval EFI_SUCCESS Convert success.
1225 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1229 StorageToConfigResp (
1230 IN BROWSER_STORAGE
*Storage
,
1231 IN CHAR16
**ConfigResp
,
1232 IN CHAR16
*ConfigRequest
,
1233 IN BOOLEAN GetEditBuf
1237 EFI_STRING Progress
;
1239 NAME_VALUE_NODE
*Node
;
1241 FORMSET_STORAGE
*FormsetStorage
;
1243 Status
= EFI_SUCCESS
;
1245 switch (Storage
->Type
) {
1246 case EFI_HII_VARSTORE_BUFFER
:
1247 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1248 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1249 Status
= mHiiConfigRouting
->BlockToConfig (
1259 case EFI_HII_VARSTORE_NAME_VALUE
:
1261 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1262 ASSERT (FormsetStorage
!= NULL
);
1263 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1265 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1266 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1267 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1269 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1270 NewStringCat (ConfigResp
, L
"&");
1271 NewStringCat (ConfigResp
, Node
->Name
);
1272 NewStringCat (ConfigResp
, L
"=");
1274 NewStringCat (ConfigResp
, Node
->EditValue
);
1276 NewStringCat (ConfigResp
, Node
->Value
);
1279 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1283 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1285 Status
= EFI_INVALID_PARAMETER
;
1294 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1296 @param Storage The Storage to receive the settings.
1297 @param ConfigResp The <ConfigResp> to be converted.
1299 @retval EFI_SUCCESS Convert success.
1300 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1304 ConfigRespToStorage (
1305 IN BROWSER_STORAGE
*Storage
,
1306 IN CHAR16
*ConfigResp
1310 EFI_STRING Progress
;
1316 Status
= EFI_SUCCESS
;
1318 switch (Storage
->Type
) {
1319 case EFI_HII_VARSTORE_BUFFER
:
1320 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1321 BufferSize
= Storage
->Size
;
1322 Status
= mHiiConfigRouting
->ConfigToBlock (
1325 Storage
->EditBuffer
,
1331 case EFI_HII_VARSTORE_NAME_VALUE
:
1332 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1333 if (StrPtr
== NULL
) {
1336 StrPtr
= StrStr (ConfigResp
, L
"&");
1337 while (StrPtr
!= NULL
) {
1341 StrPtr
= StrPtr
+ 1;
1343 StrPtr
= StrStr (StrPtr
, L
"=");
1344 if (StrPtr
== NULL
) {
1352 StrPtr
= StrPtr
+ 1;
1354 StrPtr
= StrStr (StrPtr
, L
"&");
1355 if (StrPtr
!= NULL
) {
1358 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1362 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1364 Status
= EFI_INVALID_PARAMETER
;
1372 Convert the buffer value to HiiValue.
1374 @param Question The question.
1375 @param Value Unicode buffer save the question value.
1377 @retval Status whether convert the value success.
1382 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1387 BOOLEAN IsBufferStorage
;
1399 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1400 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1401 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1402 IsBufferStorage
= TRUE
;
1404 IsBufferStorage
= FALSE
;
1408 // Question Value is provided by Buffer Storage or NameValue Storage
1410 if (Question
->BufferValue
!= NULL
) {
1412 // This Question is password or orderedlist
1414 Dst
= Question
->BufferValue
;
1417 // Other type of Questions
1419 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1423 // Temp cut at the end of this section, end with '\0' or '&'.
1426 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1429 TempChar
= *StringPtr
;
1432 LengthStr
= StrLen (Value
);
1435 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1436 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1437 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1438 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1440 if (LengthStr
> (UINTN
) Question
->StorageWidth
* 2) {
1441 Length
= (UINTN
) Question
->StorageWidth
* 2;
1446 Status
= EFI_SUCCESS
;
1447 if (!IsBufferStorage
&& IsString
) {
1449 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1450 // Add string tail char L'\0' into Length
1452 DstBuf
= (CHAR16
*) Dst
;
1453 ZeroMem (TemStr
, sizeof (TemStr
));
1454 for (Index
= 0; Index
< Length
; Index
+= 4) {
1455 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1456 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1459 // Add tailing L'\0' character
1461 DstBuf
[Index
/4] = L
'\0';
1463 ZeroMem (TemStr
, sizeof (TemStr
));
1464 for (Index
= 0; Index
< Length
; Index
++) {
1465 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1466 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1467 if ((Index
& 1) == 0) {
1468 Dst
[Index
/2] = DigitUint8
;
1470 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1475 *StringPtr
= TempChar
;
1481 Get Question's current Value.
1483 @param FormSet FormSet data structure.
1484 @param Form Form data structure.
1485 @param Question Question to be initialized.
1486 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1488 @retval EFI_SUCCESS The function completed successfully.
1493 IN FORM_BROWSER_FORMSET
*FormSet
,
1494 IN FORM_BROWSER_FORM
*Form
,
1495 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1496 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1505 BROWSER_STORAGE
*Storage
;
1506 FORMSET_STORAGE
*FormsetStorage
;
1507 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1508 CHAR16
*ConfigRequest
;
1513 BOOLEAN IsBufferStorage
;
1516 Status
= EFI_SUCCESS
;
1520 if (GetValueFrom
>= GetSetValueWithMax
) {
1521 return EFI_INVALID_PARAMETER
;
1525 // Question value is provided by an Expression, evaluate it
1527 if (Question
->ValueExpression
!= NULL
) {
1528 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1529 if (!EFI_ERROR (Status
)) {
1530 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1531 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1532 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1533 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1534 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1536 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1537 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1539 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1541 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1542 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1548 // Get question value by read expression.
1550 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1551 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1552 if (!EFI_ERROR (Status
) &&
1553 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1555 // Only update question value to the valid result.
1557 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1558 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1559 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1560 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1561 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1563 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1564 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1566 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1568 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1569 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1575 // Question value is provided by RTC
1577 Storage
= Question
->Storage
;
1578 QuestionValue
= &Question
->HiiValue
.Value
;
1579 if (Storage
== NULL
) {
1581 // It's a Question without storage, or RTC date/time
1583 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1585 // Date and time define the same Flags bit
1587 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1588 case QF_DATE_STORAGE_TIME
:
1589 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1592 case QF_DATE_STORAGE_WAKEUP
:
1593 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1596 case QF_DATE_STORAGE_NORMAL
:
1599 // For date/time without storage
1604 if (EFI_ERROR (Status
)) {
1605 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1606 QuestionValue
->date
.Year
= 0xff;
1607 QuestionValue
->date
.Month
= 0xff;
1608 QuestionValue
->date
.Day
= 0xff;
1610 QuestionValue
->time
.Hour
= 0xff;
1611 QuestionValue
->time
.Minute
= 0xff;
1612 QuestionValue
->time
.Second
= 0xff;
1617 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1618 QuestionValue
->date
.Year
= EfiTime
.Year
;
1619 QuestionValue
->date
.Month
= EfiTime
.Month
;
1620 QuestionValue
->date
.Day
= EfiTime
.Day
;
1622 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1623 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1624 QuestionValue
->time
.Second
= EfiTime
.Second
;
1632 // Question value is provided by EFI variable
1634 StorageWidth
= Question
->StorageWidth
;
1635 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1636 if (Question
->BufferValue
!= NULL
) {
1637 Dst
= Question
->BufferValue
;
1639 Dst
= (UINT8
*) QuestionValue
;
1642 Status
= gRT
->GetVariable (
1643 Question
->VariableName
,
1650 // Always return success, even this EFI variable doesn't exist
1656 // Question Value is provided by Buffer Storage or NameValue Storage
1658 if (Question
->BufferValue
!= NULL
) {
1660 // This Question is password or orderedlist
1662 Dst
= Question
->BufferValue
;
1665 // Other type of Questions
1667 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1670 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1671 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1672 IsBufferStorage
= TRUE
;
1674 IsBufferStorage
= FALSE
;
1676 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1677 if (IsBufferStorage
) {
1678 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1680 // Copy from storage Edit buffer
1682 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1685 // Copy from storage Edit buffer
1687 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1691 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1692 if (EFI_ERROR (Status
)) {
1696 ASSERT (Value
!= NULL
);
1697 Status
= BufferToValue (Question
, Value
);
1701 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1702 ASSERT (FormsetStorage
!= NULL
);
1704 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1705 // <ConfigHdr> + "&" + <VariableName>
1707 if (IsBufferStorage
) {
1708 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1709 Length
+= StrLen (Question
->BlockName
);
1711 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1712 Length
+= StrLen (Question
->VariableName
) + 1;
1714 // Allocate buffer include '\0'
1715 MaxLen
= Length
+ 1;
1716 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1717 ASSERT (ConfigRequest
!= NULL
);
1719 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1720 if (IsBufferStorage
) {
1721 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1723 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1724 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1728 // Request current settings from Configuration Driver
1730 Status
= mHiiConfigRouting
->ExtractConfig (
1736 FreePool (ConfigRequest
);
1737 if (EFI_ERROR (Status
)) {
1742 // Skip <ConfigRequest>
1744 if (IsBufferStorage
) {
1745 Value
= StrStr (Result
, L
"&VALUE");
1746 if (Value
== NULL
) {
1748 return EFI_NOT_FOUND
;
1755 Value
= Result
+ Length
;
1757 if (*Value
!= '=') {
1759 return EFI_NOT_FOUND
;
1762 // Skip '=', point to value
1766 Status
= BufferToValue (Question
, Value
);
1767 if (EFI_ERROR (Status
)) {
1773 // Synchronize Edit Buffer
1775 if (IsBufferStorage
) {
1776 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1778 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1781 if (Result
!= NULL
) {
1791 Save Question Value to edit copy(cached) or Storage(uncached).
1793 @param FormSet FormSet data structure.
1794 @param Form Form data structure.
1795 @param Question Pointer to the Question.
1796 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1798 @retval EFI_SUCCESS The function completed successfully.
1803 IN FORM_BROWSER_FORMSET
*FormSet
,
1804 IN FORM_BROWSER_FORM
*Form
,
1805 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1806 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1816 BROWSER_STORAGE
*Storage
;
1817 FORMSET_STORAGE
*FormsetStorage
;
1818 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1823 BOOLEAN IsBufferStorage
;
1829 NAME_VALUE_NODE
*Node
;
1832 Status
= EFI_SUCCESS
;
1835 if (SetValueTo
>= GetSetValueWithMax
) {
1836 return EFI_INVALID_PARAMETER
;
1840 // If Question value is provided by an Expression, then it is read only
1842 if (Question
->ValueExpression
!= NULL
) {
1847 // Before set question value, evaluate its write expression.
1849 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1850 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1851 if (EFI_ERROR (Status
)) {
1857 // Question value is provided by RTC
1859 Storage
= Question
->Storage
;
1860 QuestionValue
= &Question
->HiiValue
.Value
;
1861 if (Storage
== NULL
) {
1863 // It's a Question without storage, or RTC date/time
1865 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1867 // Date and time define the same Flags bit
1869 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1870 case QF_DATE_STORAGE_TIME
:
1871 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1874 case QF_DATE_STORAGE_WAKEUP
:
1875 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1878 case QF_DATE_STORAGE_NORMAL
:
1881 // For date/time without storage
1886 if (EFI_ERROR (Status
)) {
1890 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1891 EfiTime
.Year
= QuestionValue
->date
.Year
;
1892 EfiTime
.Month
= QuestionValue
->date
.Month
;
1893 EfiTime
.Day
= QuestionValue
->date
.Day
;
1895 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1896 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1897 EfiTime
.Second
= QuestionValue
->time
.Second
;
1900 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1901 Status
= gRT
->SetTime (&EfiTime
);
1903 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1911 // Question value is provided by EFI variable
1913 StorageWidth
= Question
->StorageWidth
;
1914 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1915 if (Question
->BufferValue
!= NULL
) {
1916 Src
= Question
->BufferValue
;
1918 Src
= (UINT8
*) QuestionValue
;
1921 Status
= gRT
->SetVariable (
1922 Question
->VariableName
,
1924 Storage
->Attributes
,
1932 // Question Value is provided by Buffer Storage or NameValue Storage
1934 if (Question
->BufferValue
!= NULL
) {
1935 Src
= Question
->BufferValue
;
1937 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1940 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1941 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1942 IsBufferStorage
= TRUE
;
1944 IsBufferStorage
= FALSE
;
1946 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1948 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1949 if (IsBufferStorage
) {
1950 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1952 // Copy to storage edit buffer
1954 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1955 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1957 // Copy to storage edit buffer
1959 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1964 // Allocate enough string buffer.
1967 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1968 Value
= AllocateZeroPool (BufferLen
);
1969 ASSERT (Value
!= NULL
);
1971 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1973 TemName
= (CHAR16
*) Src
;
1975 for (; *TemName
!= L
'\0'; TemName
++) {
1976 UnicodeValueToStringS (
1978 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
1979 PREFIX_ZERO
| RADIX_HEX
,
1983 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
1986 BufferLen
= StorageWidth
* 2 + 1;
1987 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1988 ASSERT (Value
!= NULL
);
1990 // Convert Buffer to Hex String
1992 TemBuffer
= Src
+ StorageWidth
- 1;
1994 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1995 UnicodeValueToStringS (
1997 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
1998 PREFIX_ZERO
| RADIX_HEX
,
2002 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2006 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2008 if (EFI_ERROR (Status
)) {
2012 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2014 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2015 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2017 if (IsBufferStorage
) {
2018 Length
= StrLen (Question
->BlockName
) + 7;
2020 Length
= StrLen (Question
->VariableName
) + 2;
2022 if (!IsBufferStorage
&& IsString
) {
2023 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2025 Length
+= (StorageWidth
* 2);
2027 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2028 ASSERT (FormsetStorage
!= NULL
);
2029 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2030 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2031 ASSERT (ConfigResp
!= NULL
);
2033 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2034 if (IsBufferStorage
) {
2035 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2036 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2038 StrCatS (ConfigResp
, MaxLen
, L
"&");
2039 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2040 StrCatS (ConfigResp
, MaxLen
, L
"=");
2043 Value
= ConfigResp
+ StrLen (ConfigResp
);
2045 if (!IsBufferStorage
&& IsString
) {
2047 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2049 TemName
= (CHAR16
*) Src
;
2051 for (; *TemName
!= L
'\0'; TemName
++) {
2052 UnicodeValueToStringS (
2054 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2055 PREFIX_ZERO
| RADIX_HEX
,
2059 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2063 // Convert Buffer to Hex String
2065 TemBuffer
= Src
+ StorageWidth
- 1;
2067 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2068 UnicodeValueToStringS (
2070 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2071 PREFIX_ZERO
| RADIX_HEX
,
2075 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2080 // Convert to lower char.
2082 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2083 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2084 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2089 // Submit Question Value to Configuration Driver
2091 Status
= mHiiConfigRouting
->RouteConfig (
2096 if (EFI_ERROR (Status
)) {
2097 FreePool (ConfigResp
);
2100 FreePool (ConfigResp
);
2103 // Sync storage, from editbuffer to buffer.
2105 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2113 Perform nosubmitif check for a Form.
2115 @param FormSet FormSet data structure.
2116 @param Form Form data structure.
2117 @param Question The Question to be validated.
2118 @param Type Validation type: NoSubmit
2120 @retval EFI_SUCCESS Form validation pass.
2121 @retval other Form validation failed.
2126 IN FORM_BROWSER_FORMSET
*FormSet
,
2127 IN FORM_BROWSER_FORM
*Form
,
2128 IN FORM_BROWSER_STATEMENT
*Question
,
2134 LIST_ENTRY
*ListHead
;
2135 FORM_EXPRESSION
*Expression
;
2136 UINT32 BrowserStatus
;
2139 BrowserStatus
= BROWSER_SUCCESS
;
2143 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2144 ListHead
= &Question
->InconsistentListHead
;
2147 case EFI_HII_EXPRESSION_WARNING_IF
:
2148 ListHead
= &Question
->WarningListHead
;
2151 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2152 ListHead
= &Question
->NoSubmitListHead
;
2157 return EFI_UNSUPPORTED
;
2160 Link
= GetFirstNode (ListHead
);
2161 while (!IsNull (ListHead
, Link
)) {
2162 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2165 // Evaluate the expression
2167 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2168 if (EFI_ERROR (Status
)) {
2172 if (IsTrue (&Expression
->Result
)) {
2174 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2175 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2178 case EFI_HII_EXPRESSION_WARNING_IF
:
2179 BrowserStatus
= BROWSER_WARNING_IF
;
2182 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2183 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2185 // This code only used to compatible with old display engine,
2186 // New display engine will not use this field.
2188 if (Expression
->Error
!= 0) {
2189 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2198 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2200 // If in system submit process and for no_submit_if check, not popup this error message.
2201 // Will process this fail again later in not system submit process.
2203 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2206 if (ErrorStr
!= NULL
) {
2207 FreePool (ErrorStr
);
2210 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2213 return EFI_NOT_READY
;
2217 Link
= GetNextNode (ListHead
, Link
);
2224 Perform question check.
2226 If one question has more than one check, process form high priority to low.
2227 Only one error info will be popup.
2229 @param FormSet FormSet data structure.
2230 @param Form Form data structure.
2231 @param Question The Question to be validated.
2233 @retval EFI_SUCCESS Form validation pass.
2234 @retval other Form validation failed.
2238 ValueChangedValidation (
2239 IN FORM_BROWSER_FORMSET
*FormSet
,
2240 IN FORM_BROWSER_FORM
*Form
,
2241 IN FORM_BROWSER_STATEMENT
*Question
2246 Status
= EFI_SUCCESS
;
2249 // Do the inconsistentif check.
2251 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2252 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2253 if (EFI_ERROR (Status
)) {
2259 // Do the warningif check.
2261 if (!IsListEmpty (&Question
->WarningListHead
)) {
2262 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2269 Perform NoSubmit check for each Form in FormSet.
2271 @param FormSet FormSet data structure.
2272 @param CurrentForm Current input form data structure.
2273 @param Statement The statement for this check.
2275 @retval EFI_SUCCESS Form validation pass.
2276 @retval other Form validation failed.
2281 IN FORM_BROWSER_FORMSET
*FormSet
,
2282 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2283 OUT FORM_BROWSER_STATEMENT
**Statement
2288 FORM_BROWSER_STATEMENT
*Question
;
2289 FORM_BROWSER_FORM
*Form
;
2290 LIST_ENTRY
*LinkForm
;
2292 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2293 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2294 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2295 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2297 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2301 Link
= GetFirstNode (&Form
->StatementListHead
);
2302 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2303 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2304 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2305 if (EFI_ERROR (Status
)) {
2306 if (*CurrentForm
== NULL
) {
2307 *CurrentForm
= Form
;
2309 if (Statement
!= NULL
) {
2310 *Statement
= Question
;
2315 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2323 Fill storage's edit copy with settings requested from Configuration Driver.
2325 @param Storage The storage which need to sync.
2326 @param ConfigRequest The config request string which used to sync storage.
2327 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2328 editbuffer to buffer
2329 if TRUE, copy the editbuffer to the buffer.
2330 if FALSE, copy the buffer to the editbuffer.
2332 @retval EFI_SUCCESS The function completed successfully.
2336 SynchronizeStorage (
2337 OUT BROWSER_STORAGE
*Storage
,
2338 IN CHAR16
*ConfigRequest
,
2339 IN BOOLEAN SyncOrRestore
2343 EFI_STRING Progress
;
2347 NAME_VALUE_NODE
*Node
;
2351 Status
= EFI_SUCCESS
;
2354 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2355 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2356 BufferSize
= Storage
->Size
;
2358 if (SyncOrRestore
) {
2359 Src
= Storage
->EditBuffer
;
2360 Dst
= Storage
->Buffer
;
2362 Src
= Storage
->Buffer
;
2363 Dst
= Storage
->EditBuffer
;
2366 if (ConfigRequest
!= NULL
) {
2367 Status
= mHiiConfigRouting
->BlockToConfig(
2375 if (EFI_ERROR (Status
)) {
2379 Status
= mHiiConfigRouting
->ConfigToBlock (
2386 if (Result
!= NULL
) {
2390 CopyMem (Dst
, Src
, BufferSize
);
2392 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2393 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2394 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2395 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2397 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2398 (ConfigRequest
== NULL
)) {
2399 if (SyncOrRestore
) {
2400 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2402 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2406 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2414 When discard the question value, call the callback function with Changed type
2415 to inform the hii driver.
2417 @param FormSet FormSet data structure.
2418 @param Form Form data structure.
2422 SendDiscardInfoToDriver (
2423 IN FORM_BROWSER_FORMSET
*FormSet
,
2424 IN FORM_BROWSER_FORM
*Form
2428 FORM_BROWSER_STATEMENT
*Question
;
2429 EFI_IFR_TYPE_VALUE
*TypeValue
;
2430 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2432 if (FormSet
->ConfigAccess
== NULL
) {
2436 Link
= GetFirstNode (&Form
->StatementListHead
);
2437 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2438 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2439 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2441 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2445 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2449 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2453 if (!Question
->ValueChanged
) {
2458 // Restore the question value before call the CHANGED callback type.
2460 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2462 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2463 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2466 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2467 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2469 TypeValue
= &Question
->HiiValue
.Value
;
2472 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2473 FormSet
->ConfigAccess
->Callback (
2474 FormSet
->ConfigAccess
,
2475 EFI_BROWSER_ACTION_CHANGED
,
2476 Question
->QuestionId
,
2477 Question
->HiiValue
.Type
,
2485 When submit the question value, call the callback function with Submitted type
2486 to inform the hii driver.
2488 @param FormSet FormSet data structure.
2489 @param Form Form data structure.
2493 SubmitCallbackForForm (
2494 IN FORM_BROWSER_FORMSET
*FormSet
,
2495 IN FORM_BROWSER_FORM
*Form
2499 FORM_BROWSER_STATEMENT
*Question
;
2500 EFI_IFR_TYPE_VALUE
*TypeValue
;
2501 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2503 if (FormSet
->ConfigAccess
== NULL
) {
2507 Link
= GetFirstNode (&Form
->StatementListHead
);
2508 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2509 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2510 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2512 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2516 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2520 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2524 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2525 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2527 TypeValue
= &Question
->HiiValue
.Value
;
2530 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2531 FormSet
->ConfigAccess
->Callback (
2532 FormSet
->ConfigAccess
,
2533 EFI_BROWSER_ACTION_SUBMITTED
,
2534 Question
->QuestionId
,
2535 Question
->HiiValue
.Type
,
2543 When value set Success, call the submit callback function.
2545 @param FormSet FormSet data structure.
2546 @param Form Form data structure.
2551 IN FORM_BROWSER_FORMSET
*FormSet
,
2552 IN FORM_BROWSER_FORM
*Form
2555 FORM_BROWSER_FORM
*CurrentForm
;
2559 SubmitCallbackForForm(FormSet
, Form
);
2563 Link
= GetFirstNode (&FormSet
->FormListHead
);
2564 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2565 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2566 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2568 SubmitCallbackForForm(FormSet
, CurrentForm
);
2573 Validate the HiiHandle.
2575 @param HiiHandle The input HiiHandle which need to validate.
2577 @retval TRUE The handle is validate.
2578 @retval FALSE The handle is invalidate.
2583 EFI_HII_HANDLE HiiHandle
2586 EFI_HII_HANDLE
*HiiHandles
;
2590 if (HiiHandle
== NULL
) {
2596 HiiHandles
= HiiGetHiiHandles (NULL
);
2597 ASSERT (HiiHandles
!= NULL
);
2599 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2600 if (HiiHandles
[Index
] == HiiHandle
) {
2606 FreePool (HiiHandles
);
2612 Validate the FormSet. If the formset is not validate, remove it from the list.
2614 @param FormSet The input FormSet which need to validate.
2616 @retval TRUE The handle is validate.
2617 @retval FALSE The handle is invalidate.
2622 FORM_BROWSER_FORMSET
*FormSet
2627 ASSERT (FormSet
!= NULL
);
2629 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2631 // Should not remove the formset which is being used.
2633 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2634 CleanBrowserStorage(FormSet
);
2635 RemoveEntryList (&FormSet
->Link
);
2636 DestroyFormSet (FormSet
);
2642 Check whether need to enable the reset flag in form level.
2643 Also clean all ValueChanged flag in question.
2645 @param SetFlag Whether need to set the Reset Flag.
2646 @param FormSet FormSet data structure.
2647 @param Form Form data structure.
2653 IN FORM_BROWSER_FORMSET
*FormSet
,
2654 IN FORM_BROWSER_FORM
*Form
2658 FORM_BROWSER_STATEMENT
*Question
;
2661 Link
= GetFirstNode (&Form
->StatementListHead
);
2662 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2663 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2664 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2666 if (!Question
->ValueChanged
) {
2670 OldValue
= Question
->ValueChanged
;
2673 // Compare the buffer and editbuffer data to see whether the data has been saved.
2675 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2678 // Only the changed data has been saved, then need to set the reset flag.
2680 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2681 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2682 gResetRequiredFormLevel
= TRUE
;
2683 gResetRequiredSystemLevel
= TRUE
;
2686 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2687 gFlagReconnect
= TRUE
;
2694 Check whether need to enable the reset flag.
2695 Also clean ValueChanged flag for all statements.
2697 Form level or formset level, only one.
2699 @param SetFlag Whether need to set the Reset Flag.
2700 @param FormSet FormSet data structure.
2701 @param Form Form data structure.
2705 ValueChangeResetFlagUpdate (
2707 IN FORM_BROWSER_FORMSET
*FormSet
,
2708 IN FORM_BROWSER_FORM
*Form
2711 FORM_BROWSER_FORM
*CurrentForm
;
2715 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2719 Link
= GetFirstNode (&FormSet
->FormListHead
);
2720 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2721 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2722 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2724 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2729 Base on the return Progress string to find the form.
2731 Base on the first return Offset/Width (Name) string to find the form
2732 which keep this string.
2734 @param FormSet FormSet data structure.
2735 @param Storage Storage which has this Progress string.
2736 @param Progress The Progress string which has the first fail string.
2737 @param RetForm The return form for this progress string.
2738 @param RetQuestion The return question for the error progress string.
2740 @retval TRUE Find the error form and statement for this error progress string.
2741 @retval FALSE Not find the error form.
2745 FindQuestionFromProgress (
2746 IN FORM_BROWSER_FORMSET
*FormSet
,
2747 IN BROWSER_STORAGE
*Storage
,
2748 IN EFI_STRING Progress
,
2749 OUT FORM_BROWSER_FORM
**RetForm
,
2750 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2754 LIST_ENTRY
*LinkStorage
;
2755 LIST_ENTRY
*LinkStatement
;
2756 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2757 FORM_BROWSER_FORM
*Form
;
2759 FORM_BROWSER_STATEMENT
*Statement
;
2761 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2765 *RetQuestion
= NULL
;
2768 // Skip the first "&" or the ConfigHdr part.
2770 if (*Progress
== '&') {
2774 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2776 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2778 // For Name/Value type, Skip the ConfigHdr part.
2780 EndStr
= StrStr (Progress
, L
"PATH=");
2781 ASSERT (EndStr
!= NULL
);
2782 while (*EndStr
!= '&') {
2789 // For Buffer type, Skip the ConfigHdr part.
2791 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2792 ASSERT (EndStr
!= NULL
);
2796 Progress
= EndStr
+ 1;
2800 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2802 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2804 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2805 // here, just keep the "Fred" string.
2807 EndStr
= StrStr (Progress
, L
"=");
2808 ASSERT (EndStr
!= NULL
);
2812 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2813 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2815 EndStr
= StrStr (Progress
, L
"&VALUE=");
2816 ASSERT (EndStr
!= NULL
);
2821 // Search in the form list.
2823 Link
= GetFirstNode (&FormSet
->FormListHead
);
2824 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2825 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2826 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2829 // Search in the ConfigReqeust list in this form.
2831 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2832 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2833 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2834 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2836 if (Storage
!= ConfigInfo
->Storage
) {
2840 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2842 // Find the OffsetWidth string in this form.
2849 if (*RetForm
!= NULL
) {
2850 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2851 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2852 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2853 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2855 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2856 *RetQuestion
= Statement
;
2860 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2861 *RetQuestion
= Statement
;
2867 if (*RetForm
!= NULL
) {
2873 // restore the OffsetWidth string to the original format.
2875 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2881 return (BOOLEAN
) (*RetForm
!= NULL
);
2885 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2886 for form and formset.
2888 @param Storage Storage which has this Progress string.
2889 @param ConfigRequest The ConfigRequest string.
2890 @param Progress The Progress string which has the first fail string.
2891 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2892 @param SyncConfigRequest Return the SyncConfigRequest string.
2896 GetSyncRestoreConfigRequest(
2897 IN BROWSER_STORAGE
*Storage
,
2898 IN EFI_STRING ConfigRequest
,
2899 IN EFI_STRING Progress
,
2900 OUT EFI_STRING
*RestoreConfigRequest
,
2901 OUT EFI_STRING
*SyncConfigRequest
2905 EFI_STRING ConfigHdrEndStr
;
2906 EFI_STRING ElementStr
;
2908 UINTN RestoreEleSize
;
2911 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
2913 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
2914 // Need to restore all the fields in the ConfigRequest.
2916 if (*Progress
== L
'G') {
2917 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2918 ASSERT (*RestoreConfigRequest
!= NULL
);
2923 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2925 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2927 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2928 // here, just keep the "Fred" string.
2930 EndStr
= StrStr (Progress
, L
"=");
2931 ASSERT (EndStr
!= NULL
);
2934 // Find the ConfigHdr in ConfigRequest.
2936 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
2937 ASSERT (ConfigHdrEndStr
!= NULL
);
2938 while (*ConfigHdrEndStr
!= L
'&') {
2943 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2944 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2946 EndStr
= StrStr (Progress
, L
"&VALUE=");
2947 ASSERT (EndStr
!= NULL
);
2950 // Find the ConfigHdr in ConfigRequest.
2952 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
2955 // Find the first fail pair in the ConfigRequest.
2957 ElementStr
= StrStr (ConfigRequest
, Progress
);
2958 ASSERT (ElementStr
!= NULL
);
2960 // To get the RestoreConfigRequest.
2962 RestoreEleSize
= StrSize (ElementStr
);
2963 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
2964 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
2965 ASSERT (*RestoreConfigRequest
!= NULL
);
2966 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
2967 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
2969 // To get the SyncConfigRequest.
2971 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
2972 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
2973 ASSERT (*SyncConfigRequest
!= NULL
);
2974 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
2977 // restore the Progress string to the original format.
2979 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2987 Popup an save error info and get user input.
2989 @param TitleId The form title id.
2990 @param HiiHandle The hii handle for this package.
2992 @retval UINT32 The user select option for the save fail.
2993 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2997 IN EFI_STRING_ID TitleId
,
2998 IN EFI_HII_HANDLE HiiHandle
3002 CHAR16
*StringBuffer
;
3005 FormTitle
= GetToken (TitleId
, HiiHandle
);
3007 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3008 ASSERT (StringBuffer
!= NULL
);
3012 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3013 L
"Submit Fail For Form: %s.",
3017 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3019 FreePool (StringBuffer
);
3020 FreePool (FormTitle
);
3026 Popup an NO_SUBMIT_IF error info and get user input.
3028 @param TitleId The form title id.
3029 @param HiiHandle The hii handle for this package.
3031 @retval UINT32 The user select option for the save fail.
3032 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3035 ConfirmNoSubmitFail (
3036 IN EFI_STRING_ID TitleId
,
3037 IN EFI_HII_HANDLE HiiHandle
3041 CHAR16
*StringBuffer
;
3044 FormTitle
= GetToken (TitleId
, HiiHandle
);
3046 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3047 ASSERT (StringBuffer
!= NULL
);
3051 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3052 L
"NO_SUBMIT_IF error For Form: %s.",
3056 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3058 FreePool (StringBuffer
);
3059 FreePool (FormTitle
);
3065 Discard data based on the input setting scope (Form, FormSet or System).
3067 @param FormSet FormSet data structure.
3068 @param Form Form data structure.
3069 @param SettingScope Setting Scope for Discard action.
3071 @retval EFI_SUCCESS The function completed successfully.
3072 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3077 IN FORM_BROWSER_FORMSET
*FormSet
,
3078 IN FORM_BROWSER_FORM
*Form
,
3079 IN BROWSER_SETTING_SCOPE SettingScope
3083 FORMSET_STORAGE
*Storage
;
3084 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3085 FORM_BROWSER_FORMSET
*LocalFormSet
;
3086 FORM_BROWSER_FORMSET
*OldFormSet
;
3089 // Check the supported setting level.
3091 if (SettingScope
>= MaxLevel
) {
3092 return EFI_UNSUPPORTED
;
3095 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3097 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3098 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3099 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3100 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3102 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3107 // Skip if there is no RequestElement
3109 if (ConfigInfo
->ElementCount
== 0) {
3114 // Prepare <ConfigResp>
3116 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3119 // Call callback with Changed type to inform the driver.
3121 SendDiscardInfoToDriver (FormSet
, Form
);
3124 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3125 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3128 // Discard Buffer storage or Name/Value storage
3130 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3131 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3132 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3133 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3135 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3140 // Skip if there is no RequestElement
3142 if (Storage
->ElementCount
== 0) {
3146 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3149 Link
= GetFirstNode (&FormSet
->FormListHead
);
3150 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3151 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3152 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3155 // Call callback with Changed type to inform the driver.
3157 SendDiscardInfoToDriver (FormSet
, Form
);
3160 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3161 } else if (SettingScope
== SystemLevel
) {
3163 // System Level Discard.
3165 OldFormSet
= mSystemLevelFormSet
;
3168 // Discard changed value for each FormSet in the maintain list.
3170 Link
= GetFirstNode (&gBrowserFormSetList
);
3171 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3172 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3173 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3174 if (!ValidateFormSet(LocalFormSet
)) {
3178 mSystemLevelFormSet
= LocalFormSet
;
3180 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3181 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3183 // Remove maintain backup list after discard except for the current using FormSet.
3185 CleanBrowserStorage(LocalFormSet
);
3186 RemoveEntryList (&LocalFormSet
->Link
);
3187 DestroyFormSet (LocalFormSet
);
3191 mSystemLevelFormSet
= OldFormSet
;
3198 Submit data for a form.
3200 @param FormSet FormSet data structure.
3201 @param Form Form data structure.
3203 @retval EFI_SUCCESS The function completed successfully.
3204 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3209 IN FORM_BROWSER_FORMSET
*FormSet
,
3210 IN FORM_BROWSER_FORM
*Form
3215 EFI_STRING ConfigResp
;
3216 EFI_STRING Progress
;
3217 BROWSER_STORAGE
*Storage
;
3218 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3219 BOOLEAN SubmitFormFail
;
3221 SubmitFormFail
= FALSE
;
3223 if (!IsNvUpdateRequiredForForm (Form
)) {
3227 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3228 if (EFI_ERROR (Status
)) {
3232 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3233 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3234 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3235 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3237 Storage
= ConfigInfo
->Storage
;
3238 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3243 // Skip if there is no RequestElement
3245 if (ConfigInfo
->ElementCount
== 0) {
3250 // 1. Prepare <ConfigResp>
3252 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3253 if (EFI_ERROR (Status
)) {
3258 // 2. Set value to hii config routine protocol.
3260 Status
= mHiiConfigRouting
->RouteConfig (
3266 if (EFI_ERROR (Status
)) {
3268 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3270 SubmitFormFail
= TRUE
;
3271 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3272 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3273 FreePool (ConfigResp
);
3277 FreePool (ConfigResp
);
3279 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3281 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3285 // 4. Process the save failed storage.
3287 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3288 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3289 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3290 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3291 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3292 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3294 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3295 // base on the SyncConfigRequest to Sync the buffer.
3297 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3298 FreePool (ConfigInfo
->RestoreConfigRequest
);
3299 ConfigInfo
->RestoreConfigRequest
= NULL
;
3300 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3301 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3302 FreePool (ConfigInfo
->SyncConfigRequest
);
3303 ConfigInfo
->SyncConfigRequest
= NULL
;
3306 Status
= EFI_SUCCESS
;
3308 SendDiscardInfoToDriver (FormSet
,Form
);
3310 Status
= EFI_UNSUPPORTED
;
3314 // Free Form save fail list.
3316 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3317 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3318 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3319 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3324 // 5. Update the NV flag.
3326 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3329 // 6 Call callback with Submitted type to inform the driver.
3331 if (!SubmitFormFail
) {
3332 SubmitCallback (FormSet
, Form
);
3339 Submit data for a formset.
3341 @param FormSet FormSet data structure.
3342 @param SkipProcessFail Whether skip to process the save failed storage.
3343 If submit formset is called when do system level save,
3344 set this value to true and process the failed formset
3346 if submit formset is called when do formset level save,
3347 set the value to false and process the failed storage
3348 right after process all storages for this formset.
3350 @retval EFI_SUCCESS The function completed successfully.
3351 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3356 IN FORM_BROWSER_FORMSET
*FormSet
,
3357 IN BOOLEAN SkipProcessFail
3362 EFI_STRING ConfigResp
;
3363 EFI_STRING Progress
;
3364 BROWSER_STORAGE
*Storage
;
3365 FORMSET_STORAGE
*FormSetStorage
;
3366 FORM_BROWSER_FORM
*Form
;
3367 BOOLEAN HasInserted
;
3368 FORM_BROWSER_STATEMENT
*Question
;
3369 BOOLEAN SubmitFormSetFail
;
3370 BOOLEAN DiscardChange
;
3372 HasInserted
= FALSE
;
3373 SubmitFormSetFail
= FALSE
;
3374 DiscardChange
= FALSE
;
3376 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3381 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3382 if (EFI_ERROR (Status
)) {
3383 if (SkipProcessFail
) {
3385 // Process NO_SUBMIT check first, so insert it at head.
3387 FormSet
->SaveFailForm
= Form
;
3388 FormSet
->SaveFailStatement
= Question
;
3389 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3398 // Submit Buffer storage or Name/Value storage
3400 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3401 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3402 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3403 Storage
= FormSetStorage
->BrowserStorage
;
3404 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3406 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3411 // Skip if there is no RequestElement
3413 if (FormSetStorage
->ElementCount
== 0) {
3418 // 1. Prepare <ConfigResp>
3420 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3421 if (EFI_ERROR (Status
)) {
3426 // 2. Send <ConfigResp> to Routine config Protocol.
3428 Status
= mHiiConfigRouting
->RouteConfig (
3433 if (EFI_ERROR (Status
)) {
3435 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3437 SubmitFormSetFail
= TRUE
;
3438 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3439 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3442 // Call submit formset for system level, save the formset info
3443 // and process later.
3445 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3446 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3447 FormSet
->SaveFailForm
= Form
;
3448 FormSet
->SaveFailStatement
= Question
;
3449 if (SkipProcessFail
) {
3450 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3455 FreePool (ConfigResp
);
3459 FreePool (ConfigResp
);
3461 // 3. Config success, update storage shadow Buffer
3463 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3467 // 4. Has save fail storage need to handle.
3470 if (!SkipProcessFail
) {
3472 // If not in system level, just handl the save failed storage here.
3474 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3475 DiscardChange
= TRUE
;
3476 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3477 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3478 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3479 Storage
= FormSetStorage
->BrowserStorage
;
3480 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3482 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3483 // base on the SyncConfigRequest to Sync the buffer.
3485 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3486 FreePool (FormSetStorage
->RestoreConfigRequest
);
3487 FormSetStorage
->RestoreConfigRequest
= NULL
;
3488 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3489 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3490 FreePool (FormSetStorage
->SyncConfigRequest
);
3491 FormSetStorage
->SyncConfigRequest
= NULL
;
3494 Status
= EFI_SUCCESS
;
3497 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3499 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3500 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3501 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3502 gCurrentSelection
->FormId
= Form
->FormId
;
3503 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3505 Status
= EFI_UNSUPPORTED
;
3509 // Free FormSet save fail list.
3511 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3512 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3513 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3514 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3518 // If in system level, just return error and handle the failed formset later.
3520 Status
= EFI_UNSUPPORTED
;
3525 // If user discard the change, send the discard info to driver.
3527 if (DiscardChange
) {
3528 Link
= GetFirstNode (&FormSet
->FormListHead
);
3529 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3530 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3531 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3533 // Call callback with Changed type to inform the driver.
3535 SendDiscardInfoToDriver (FormSet
, Form
);
3540 // 5. Update the NV flag.
3542 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3545 // 6. Call callback with Submitted type to inform the driver.
3547 if (!SubmitFormSetFail
) {
3548 SubmitCallback (FormSet
, NULL
);
3555 Submit data for all formsets.
3557 @retval EFI_SUCCESS The function completed successfully.
3558 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3568 LIST_ENTRY
*FormLink
;
3569 LIST_ENTRY
*StorageLink
;
3570 FORMSET_STORAGE
*FormSetStorage
;
3571 FORM_BROWSER_FORM
*Form
;
3572 FORM_BROWSER_FORMSET
*LocalFormSet
;
3573 UINT32 UserSelection
;
3574 FORM_BROWSER_STATEMENT
*Question
;
3576 mSystemSubmit
= TRUE
;
3577 Link
= GetFirstNode (&gBrowserFormSetList
);
3578 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3579 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3580 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3581 if (!ValidateFormSet(LocalFormSet
)) {
3585 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3586 if (EFI_ERROR (Status
)) {
3591 // Remove maintain backup list after save except for the current using FormSet.
3593 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3594 CleanBrowserStorage(LocalFormSet
);
3595 RemoveEntryList (&LocalFormSet
->Link
);
3596 DestroyFormSet (LocalFormSet
);
3599 mSystemSubmit
= FALSE
;
3601 Status
= EFI_SUCCESS
;
3604 // Process the save failed formsets.
3606 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3607 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3608 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3609 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3611 if (!ValidateFormSet(LocalFormSet
)) {
3615 Form
= LocalFormSet
->SaveFailForm
;
3616 Question
= LocalFormSet
->SaveFailStatement
;
3619 // Confirm with user, get user input.
3621 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3623 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3625 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3627 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3630 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3631 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3632 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3633 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3634 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3635 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3637 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3640 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3641 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3642 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3643 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3645 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3646 // base on the SyncConfigRequest to Sync the buffer.
3648 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3649 FreePool (FormSetStorage
->RestoreConfigRequest
);
3650 FormSetStorage
->RestoreConfigRequest
= NULL
;
3651 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3652 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3653 FreePool (FormSetStorage
->SyncConfigRequest
);
3654 FormSetStorage
->SyncConfigRequest
= NULL
;
3659 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3660 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3661 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3662 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3664 // Call callback with Changed type to inform the driver.
3666 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3669 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3670 CleanBrowserStorage(LocalFormSet
);
3671 RemoveEntryList (&LocalFormSet
->Link
);
3672 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3673 DestroyFormSet (LocalFormSet
);
3675 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3678 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3679 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3682 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3684 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3685 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3686 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3687 gCurrentSelection
->FormId
= Form
->FormId
;
3688 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3690 Status
= EFI_UNSUPPORTED
;
3696 // Clean the list which will not process.
3698 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3699 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3700 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3701 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3703 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3704 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3705 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3706 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3714 Submit data based on the input Setting level (Form, FormSet or System).
3716 @param FormSet FormSet data structure.
3717 @param Form Form data structure.
3718 @param SettingScope Setting Scope for Submit action.
3720 @retval EFI_SUCCESS The function completed successfully.
3721 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3726 IN FORM_BROWSER_FORMSET
*FormSet
,
3727 IN FORM_BROWSER_FORM
*Form
,
3728 IN BROWSER_SETTING_SCOPE SettingScope
3733 switch (SettingScope
) {
3735 Status
= SubmitForForm(FormSet
, Form
);
3739 Status
= SubmitForFormSet (FormSet
, FALSE
);
3743 Status
= SubmitForSystem ();
3747 Status
= EFI_UNSUPPORTED
;
3755 Converts the unicode character of the string from uppercase to lowercase.
3756 This is a internal function.
3758 @param ConfigString String to be converted
3764 IN EFI_STRING ConfigString
3770 ASSERT (ConfigString
!= NULL
);
3773 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3775 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3776 if (*String
== L
'=') {
3778 } else if (*String
== L
'&') {
3780 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3781 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3787 Find the point in the ConfigResp string for this question.
3789 @param Question The question.
3790 @param ConfigResp Get ConfigResp string.
3792 @retval point to the offset where is for this question.
3796 GetOffsetFromConfigResp (
3797 IN FORM_BROWSER_STATEMENT
*Question
,
3798 IN CHAR16
*ConfigResp
3801 CHAR16
*RequestElement
;
3805 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3807 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3808 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3809 if (RequestElement
!= NULL
) {
3811 // Skip the "VariableName=" field.
3813 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3816 return RequestElement
;
3820 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3824 // Convert all hex digits in ConfigResp to lower case before searching.
3826 HiiToLower (ConfigResp
);
3829 // 1. Directly use Question->BlockName to find.
3831 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3832 if (RequestElement
!= NULL
) {
3834 // Skip the "Question->BlockName&VALUE=" field.
3836 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3837 return RequestElement
;
3841 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3843 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3844 ASSERT (BlockData
!= NULL
);
3845 HiiToLower (BlockData
);
3846 RequestElement
= StrStr (ConfigResp
, BlockData
);
3847 FreePool (BlockData
);
3849 if (RequestElement
!= NULL
) {
3851 // Skip the "Question->BlockName&VALUE=" field.
3853 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3856 return RequestElement
;
3860 Get Question default value from AltCfg string.
3862 @param FormSet The form set.
3863 @param Form The form
3864 @param Question The question.
3866 @retval EFI_SUCCESS Question is reset to default value.
3870 GetDefaultValueFromAltCfg (
3871 IN FORM_BROWSER_FORMSET
*FormSet
,
3872 IN FORM_BROWSER_FORM
*Form
,
3873 IN OUT FORM_BROWSER_STATEMENT
*Question
3876 BROWSER_STORAGE
*Storage
;
3877 FORMSET_STORAGE
*FormSetStorage
;
3881 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3883 Storage
= Question
->Storage
;
3884 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3885 return EFI_NOT_FOUND
;
3889 // Try to get AltCfg string from form. If not found it, then
3890 // try to get it from formset.
3893 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3894 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3895 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3896 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3898 if (Storage
== ConfigInfo
->Storage
) {
3899 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3904 if (ConfigResp
== NULL
) {
3905 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3906 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3907 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3908 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3910 if (Storage
== FormSetStorage
->BrowserStorage
) {
3911 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3917 if (ConfigResp
== NULL
) {
3918 return EFI_NOT_FOUND
;
3921 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3922 if (Value
== NULL
) {
3923 return EFI_NOT_FOUND
;
3926 return BufferToValue (Question
, Value
);
3930 Get default Id value used for browser.
3932 @param DefaultId The default id value used by hii.
3934 @retval Browser used default value.
3938 GetDefaultIdForCallBack (
3942 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3943 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3944 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3945 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3946 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3947 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3948 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3949 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3950 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3951 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3952 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3953 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3962 Return data element in an Array by its Index.
3964 @param Array The data array.
3965 @param Type Type of the data in this array.
3966 @param Index Zero based index for data in this array.
3968 @retval Value The data to be returned
3980 ASSERT (Array
!= NULL
);
3984 case EFI_IFR_TYPE_NUM_SIZE_8
:
3985 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3988 case EFI_IFR_TYPE_NUM_SIZE_16
:
3989 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3992 case EFI_IFR_TYPE_NUM_SIZE_32
:
3993 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3996 case EFI_IFR_TYPE_NUM_SIZE_64
:
3997 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
4009 Set value of a data element in an Array by its Index.
4011 @param Array The data array.
4012 @param Type Type of the data in this array.
4013 @param Index Zero based index for data in this array.
4014 @param Value The value to be set.
4026 ASSERT (Array
!= NULL
);
4029 case EFI_IFR_TYPE_NUM_SIZE_8
:
4030 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
4033 case EFI_IFR_TYPE_NUM_SIZE_16
:
4034 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
4037 case EFI_IFR_TYPE_NUM_SIZE_32
:
4038 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
4041 case EFI_IFR_TYPE_NUM_SIZE_64
:
4042 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
4051 Search an Option of a Question by its value.
4053 @param Question The Question
4054 @param OptionValue Value for Option to be searched.
4056 @retval Pointer Pointer to the found Option.
4057 @retval NULL Option not found.
4062 IN FORM_BROWSER_STATEMENT
*Question
,
4063 IN EFI_HII_VALUE
*OptionValue
4067 QUESTION_OPTION
*Option
;
4070 Link
= GetFirstNode (&Question
->OptionListHead
);
4071 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4072 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4074 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4076 // Check the suppressif condition, only a valid option can be return.
4078 if ((Option
->SuppressExpression
== NULL
) ||
4079 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4084 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4092 Reset Question to its default value.
4094 @param FormSet The form set.
4095 @param Form The form.
4096 @param Question The question.
4097 @param DefaultId The Class of the default.
4099 @retval EFI_SUCCESS Question is reset to default value.
4103 GetQuestionDefault (
4104 IN FORM_BROWSER_FORMSET
*FormSet
,
4105 IN FORM_BROWSER_FORM
*Form
,
4106 IN FORM_BROWSER_STATEMENT
*Question
,
4112 QUESTION_DEFAULT
*Default
;
4113 QUESTION_OPTION
*Option
;
4114 EFI_HII_VALUE
*HiiValue
;
4116 EFI_STRING StrValue
;
4117 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4118 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4121 EFI_IFR_TYPE_VALUE
*TypeValue
;
4122 UINT16 OriginalDefaultId
;
4123 FORMSET_DEFAULTSTORE
*DefaultStore
;
4124 LIST_ENTRY
*DefaultLink
;
4126 Status
= EFI_NOT_FOUND
;
4128 OriginalDefaultId
= DefaultId
;
4129 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4132 // Statement don't have storage, skip them
4134 if (Question
->QuestionId
== 0) {
4139 // There are Five ways to specify default value for a Question:
4140 // 1, use call back function (highest priority)
4141 // 2, use ExtractConfig function
4142 // 3, use nested EFI_IFR_DEFAULT
4143 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4144 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4147 HiiValue
= &Question
->HiiValue
;
4148 TypeValue
= &HiiValue
->Value
;
4149 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4151 // For orderedlist, need to pass the BufferValue to Callback function.
4153 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4157 // Get Question defaut value from call back function.
4159 ConfigAccess
= FormSet
->ConfigAccess
;
4160 Action
= GetDefaultIdForCallBack (DefaultId
);
4161 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4162 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4163 Status
= ConfigAccess
->Callback (
4166 Question
->QuestionId
,
4171 if (!EFI_ERROR (Status
)) {
4172 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4173 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4174 ASSERT (NewString
!= NULL
);
4176 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4177 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4178 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4179 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4181 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4184 FreePool (NewString
);
4191 // Get default value from altcfg string.
4193 if (ConfigAccess
!= NULL
) {
4194 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4195 if (!EFI_ERROR (Status
)) {
4201 // EFI_IFR_DEFAULT has highest priority
4203 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4204 Link
= GetFirstNode (&Question
->DefaultListHead
);
4205 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4206 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4208 if (Default
->DefaultId
== DefaultId
) {
4209 if (Default
->ValueExpression
!= NULL
) {
4211 // Default is provided by an Expression, evaluate it
4213 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4214 if (EFI_ERROR (Status
)) {
4218 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4219 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4220 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4221 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4222 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4224 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4225 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4227 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4229 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4230 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4233 // Default value is embedded in EFI_IFR_DEFAULT
4235 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4236 ASSERT (HiiValue
->Buffer
!= NULL
);
4237 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4239 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4243 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4244 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4245 if (StrValue
== NULL
) {
4246 return EFI_NOT_FOUND
;
4248 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4249 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4250 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4252 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4259 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4264 // EFI_ONE_OF_OPTION
4266 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4267 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4269 // OneOfOption could only provide Standard and Manufacturing default
4271 Link
= GetFirstNode (&Question
->OptionListHead
);
4272 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4273 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4274 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4276 if ((Option
->SuppressExpression
!= NULL
) &&
4277 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4281 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4282 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4284 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4293 // EFI_IFR_CHECKBOX - lowest priority
4295 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4296 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4298 // Checkbox could only provide Standard and Manufacturing default
4300 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4301 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4303 HiiValue
->Value
.b
= TRUE
;
4311 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4312 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4313 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4315 while (!IsNull(&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4316 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink
);
4317 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
,DefaultLink
);
4318 DefaultId
= DefaultStore
->DefaultId
;
4319 if (DefaultId
== OriginalDefaultId
) {
4326 // For Questions without default value for all the default id in the DefaultStoreList.
4328 Status
= EFI_NOT_FOUND
;
4329 switch (Question
->Operand
) {
4330 case EFI_IFR_CHECKBOX_OP
:
4331 HiiValue
->Value
.b
= FALSE
;
4332 Status
= EFI_SUCCESS
;
4335 case EFI_IFR_NUMERIC_OP
:
4337 // Take minimum value as numeric default value
4339 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4341 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4343 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4344 case EFI_IFR_NUMERIC_SIZE_1
:
4345 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4346 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4347 Status
= EFI_SUCCESS
;
4350 case EFI_IFR_NUMERIC_SIZE_2
:
4351 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4352 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4353 Status
= EFI_SUCCESS
;
4356 case EFI_IFR_NUMERIC_SIZE_4
:
4357 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4358 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4359 Status
= EFI_SUCCESS
;
4362 case EFI_IFR_NUMERIC_SIZE_8
:
4363 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4364 HiiValue
->Value
.u64
= Question
->Minimum
;
4365 Status
= EFI_SUCCESS
;
4372 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4373 HiiValue
->Value
.u64
= Question
->Minimum
;
4374 Status
= EFI_SUCCESS
;
4379 case EFI_IFR_ONE_OF_OP
:
4381 // Take first oneof option as oneof's default value
4383 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4384 Link
= GetFirstNode (&Question
->OptionListHead
);
4385 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4386 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4387 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4389 if ((Option
->SuppressExpression
!= NULL
) &&
4390 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4394 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4395 Status
= EFI_SUCCESS
;
4401 case EFI_IFR_ORDERED_LIST_OP
:
4403 // Take option sequence in IFR as ordered list's default value
4406 Link
= GetFirstNode (&Question
->OptionListHead
);
4407 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4408 Status
= EFI_SUCCESS
;
4409 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4410 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4412 if ((Option
->SuppressExpression
!= NULL
) &&
4413 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4417 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4420 if (Index
>= Question
->MaxContainers
) {
4434 Get AltCfg string for current form.
4436 @param FormSet Form data structure.
4437 @param Form Form data structure.
4438 @param DefaultId The Class of the default.
4439 @param BrowserStorage The input request storage for the questions.
4443 ExtractAltCfgForForm (
4444 IN FORM_BROWSER_FORMSET
*FormSet
,
4445 IN FORM_BROWSER_FORM
*Form
,
4446 IN UINT16 DefaultId
,
4447 IN BROWSER_STORAGE
*BrowserStorage
4455 BROWSER_STORAGE
*Storage
;
4456 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4457 FORMSET_STORAGE
*FormSetStorage
;
4460 // Check whether has get AltCfg string for this formset.
4461 // If yes, no need to get AltCfg for form.
4463 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4464 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4465 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4466 Storage
= FormSetStorage
->BrowserStorage
;
4467 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4468 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4472 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4473 FormSetStorage
->ElementCount
!= 0 &&
4474 FormSetStorage
->HasCallAltCfg
) {
4480 // Get AltCfg string for each form.
4482 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4483 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4484 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4485 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4487 Storage
= ConfigInfo
->Storage
;
4488 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4492 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4497 // 1. Skip if there is no RequestElement
4499 if (ConfigInfo
->ElementCount
== 0) {
4504 // 2. Get value through hii config routine protocol.
4506 Status
= mHiiConfigRouting
->ExtractConfig (
4508 ConfigInfo
->ConfigRequest
,
4512 if (EFI_ERROR (Status
)) {
4517 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4518 // Get the default configuration string according to the default ID.
4520 Status
= mHiiConfigRouting
->GetAltConfig (
4526 &DefaultId
, // it can be NULL to get the current setting.
4530 if (EFI_ERROR (Status
)) {
4534 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4539 Clean AltCfg string for current form.
4541 @param Form Form data structure.
4545 CleanAltCfgForForm (
4546 IN FORM_BROWSER_FORM
*Form
4550 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4552 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4553 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4554 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4555 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4557 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4558 FreePool (ConfigInfo
->ConfigAltResp
);
4559 ConfigInfo
->ConfigAltResp
= NULL
;
4565 Get AltCfg string for current formset.
4567 @param FormSet Form data structure.
4568 @param DefaultId The Class of the default.
4569 @param BrowserStorage The input request storage for the questions.
4573 ExtractAltCfgForFormSet (
4574 IN FORM_BROWSER_FORMSET
*FormSet
,
4575 IN UINT16 DefaultId
,
4576 IN BROWSER_STORAGE
*BrowserStorage
4584 BROWSER_STORAGE
*Storage
;
4585 FORMSET_STORAGE
*FormSetStorage
;
4587 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4588 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4589 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4590 Storage
= FormSetStorage
->BrowserStorage
;
4591 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4593 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4597 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4602 // 1. Skip if there is no RequestElement
4604 if (FormSetStorage
->ElementCount
== 0) {
4608 FormSetStorage
->HasCallAltCfg
= TRUE
;
4611 // 2. Get value through hii config routine protocol.
4613 Status
= mHiiConfigRouting
->ExtractConfig (
4615 FormSetStorage
->ConfigRequest
,
4619 if (EFI_ERROR (Status
)) {
4624 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4625 // Get the default configuration string according to the default ID.
4627 Status
= mHiiConfigRouting
->GetAltConfig (
4633 &DefaultId
, // it can be NULL to get the current setting.
4638 if (EFI_ERROR (Status
)) {
4642 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4648 Clean AltCfg string for current formset.
4650 @param FormSet Form data structure.
4654 CleanAltCfgForFormSet (
4655 IN FORM_BROWSER_FORMSET
*FormSet
4659 FORMSET_STORAGE
*FormSetStorage
;
4661 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4662 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4663 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4664 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4666 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4667 FreePool (FormSetStorage
->ConfigAltResp
);
4668 FormSetStorage
->ConfigAltResp
= NULL
;
4671 FormSetStorage
->HasCallAltCfg
= FALSE
;
4676 Reset Questions to their initial value or default value in a Form, Formset or System.
4678 GetDefaultValueScope parameter decides which questions will reset
4679 to its default value.
4681 @param FormSet FormSet data structure.
4682 @param Form Form data structure.
4683 @param DefaultId The Class of the default.
4684 @param SettingScope Setting Scope for Default action.
4685 @param GetDefaultValueScope Get default value scope.
4686 @param Storage Get default value only for this storage.
4687 @param RetrieveValueFirst Whether call the retrieve call back to
4688 get the initial value before get default
4690 @param SkipGetAltCfg Whether skip the get altcfg string process.
4692 @retval EFI_SUCCESS The function completed successfully.
4693 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4698 IN FORM_BROWSER_FORMSET
*FormSet
,
4699 IN FORM_BROWSER_FORM
*Form
,
4700 IN UINT16 DefaultId
,
4701 IN BROWSER_SETTING_SCOPE SettingScope
,
4702 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4703 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4704 IN BOOLEAN RetrieveValueFirst
,
4705 IN BOOLEAN SkipGetAltCfg
4709 LIST_ENTRY
*FormLink
;
4711 FORM_BROWSER_STATEMENT
*Question
;
4712 FORM_BROWSER_FORMSET
*LocalFormSet
;
4713 FORM_BROWSER_FORMSET
*OldFormSet
;
4715 Status
= EFI_SUCCESS
;
4718 // Check the supported setting level.
4720 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4721 return EFI_UNSUPPORTED
;
4724 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4725 return EFI_UNSUPPORTED
;
4728 if (SettingScope
== FormLevel
) {
4730 // Prepare the AltCfg String for form.
4732 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4733 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4737 // Extract Form default
4739 Link
= GetFirstNode (&Form
->StatementListHead
);
4740 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4741 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4742 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4745 // If get default value only for this storage, check the storage first.
4747 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4752 // If get default value only for no storage question, just skip the question which has storage.
4754 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4759 // If Question is disabled, don't reset it to default
4761 if (Question
->Expression
!= NULL
) {
4762 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4767 if (RetrieveValueFirst
) {
4769 // Call the Retrieve call back to get the initial question value.
4771 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4775 // If not request to get the initial value or get initial value fail, then get default value.
4777 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4778 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4779 if (EFI_ERROR (Status
)) {
4785 // Synchronize Buffer storage's Edit buffer
4787 if ((Question
->Storage
!= NULL
) &&
4788 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4789 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4794 // Clean the AltCfg String.
4796 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4797 CleanAltCfgForForm(Form
);
4799 } else if (SettingScope
== FormSetLevel
) {
4801 // Prepare the AltCfg String for formset.
4803 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4804 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4807 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4808 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4809 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4810 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4811 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4815 // Clean the AltCfg String.
4817 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4818 CleanAltCfgForFormSet (FormSet
);
4820 } else if (SettingScope
== SystemLevel
) {
4822 // Preload all Hii formset.
4824 LoadAllHiiFormset();
4826 OldFormSet
= mSystemLevelFormSet
;
4829 // Set Default Value for each FormSet in the maintain list.
4831 Link
= GetFirstNode (&gBrowserFormSetList
);
4832 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4833 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4834 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4835 if (!ValidateFormSet(LocalFormSet
)) {
4839 mSystemLevelFormSet
= LocalFormSet
;
4841 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4844 mSystemLevelFormSet
= OldFormSet
;
4852 Validate whether this question's value has changed.
4854 @param FormSet FormSet data structure.
4855 @param Form Form data structure.
4856 @param Question Question to be initialized.
4857 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4859 @retval TRUE Question's value has changed.
4860 @retval FALSE Question's value has not changed
4864 IsQuestionValueChanged (
4865 IN FORM_BROWSER_FORMSET
*FormSet
,
4866 IN FORM_BROWSER_FORM
*Form
,
4867 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4868 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4871 EFI_HII_VALUE BackUpValue
;
4872 CHAR8
*BackUpBuffer
;
4873 EFI_HII_VALUE BackUpValue2
;
4874 CHAR8
*BackUpBuffer2
;
4876 BOOLEAN ValueChanged
;
4880 // For quetion without storage, always mark it as data not changed.
4882 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4886 BackUpBuffer
= NULL
;
4887 BackUpBuffer2
= NULL
;
4888 ValueChanged
= FALSE
;
4890 switch (Question
->Operand
) {
4891 case EFI_IFR_ORDERED_LIST_OP
:
4892 BufferWidth
= Question
->StorageWidth
;
4893 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4894 ASSERT (BackUpBuffer
!= NULL
);
4897 case EFI_IFR_STRING_OP
:
4898 case EFI_IFR_PASSWORD_OP
:
4899 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4900 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4901 ASSERT (BackUpBuffer
!= NULL
);
4908 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4910 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4911 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4912 ASSERT_EFI_ERROR(Status
);
4914 switch (Question
->Operand
) {
4915 case EFI_IFR_ORDERED_LIST_OP
:
4916 BufferWidth
= Question
->StorageWidth
;
4917 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4918 ASSERT (BackUpBuffer2
!= NULL
);
4921 case EFI_IFR_STRING_OP
:
4922 case EFI_IFR_PASSWORD_OP
:
4923 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4924 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4925 ASSERT (BackUpBuffer2
!= NULL
);
4932 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4934 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4935 ASSERT_EFI_ERROR(Status
);
4937 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4938 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4939 ValueChanged
= TRUE
;
4942 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4943 ASSERT_EFI_ERROR(Status
);
4945 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4946 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4947 ValueChanged
= TRUE
;
4951 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4952 if (BackUpBuffer
!= NULL
) {
4953 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4954 FreePool (BackUpBuffer
);
4957 if (BackUpBuffer2
!= NULL
) {
4958 FreePool (BackUpBuffer2
);
4961 Question
->ValueChanged
= ValueChanged
;
4963 return ValueChanged
;
4967 Initialize Question's Edit copy from Storage.
4969 @param Selection Selection contains the information about
4970 the Selection, form and formset to be displayed.
4971 Selection action may be updated in retrieve callback.
4972 If Selection is NULL, only initialize Question value.
4973 @param FormSet FormSet data structure.
4974 @param Form Form data structure.
4976 @retval EFI_SUCCESS The function completed successfully.
4981 IN OUT UI_MENU_SELECTION
*Selection
,
4982 IN FORM_BROWSER_FORMSET
*FormSet
,
4983 IN FORM_BROWSER_FORM
*Form
4988 FORM_BROWSER_STATEMENT
*Question
;
4990 Link
= GetFirstNode (&Form
->StatementListHead
);
4991 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4992 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4995 // Initialize local copy of Value for each Question
4997 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4998 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
5000 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5002 if (EFI_ERROR (Status
)) {
5006 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5007 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5010 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5017 Initialize Question's Edit copy from Storage for the whole Formset.
5019 @param Selection Selection contains the information about
5020 the Selection, form and formset to be displayed.
5021 Selection action may be updated in retrieve callback.
5022 If Selection is NULL, only initialize Question value.
5023 @param FormSet FormSet data structure.
5025 @retval EFI_SUCCESS The function completed successfully.
5030 IN OUT UI_MENU_SELECTION
*Selection
,
5031 IN FORM_BROWSER_FORMSET
*FormSet
5036 FORM_BROWSER_FORM
*Form
;
5038 Link
= GetFirstNode (&FormSet
->FormListHead
);
5039 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5040 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5043 // Initialize local copy of Value for each Form
5045 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5046 if (EFI_ERROR (Status
)) {
5050 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5054 // Finished question initialization.
5056 FormSet
->QuestionInited
= TRUE
;
5062 Remove the Request element from the Config Request.
5064 @param Storage Pointer to the browser storage.
5065 @param RequestElement The pointer to the Request element.
5070 IN OUT BROWSER_STORAGE
*Storage
,
5071 IN CHAR16
*RequestElement
5077 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5079 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5081 if (NewStr
== NULL
) {
5086 // Remove this element from this ConfigRequest.
5089 NewStr
+= StrLen (RequestElement
);
5090 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5092 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5096 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5098 @param Storage Pointer to the formset storage.
5099 @param ConfigRequest The pointer to the Request element.
5103 RemoveConfigRequest (
5104 FORMSET_STORAGE
*Storage
,
5105 CHAR16
*ConfigRequest
5108 CHAR16
*RequestElement
;
5109 CHAR16
*NextRequestElement
;
5113 // No request element in it, just return.
5115 if (ConfigRequest
== NULL
) {
5119 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5121 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5126 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5128 SearchKey
= L
"&OFFSET";
5132 // Find SearchKey storage
5134 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5135 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5136 ASSERT (RequestElement
!= NULL
);
5137 RequestElement
= StrStr (RequestElement
, SearchKey
);
5139 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5142 while (RequestElement
!= NULL
) {
5144 // +1 to avoid find header itself.
5146 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5149 // The last Request element in configRequest string.
5151 if (NextRequestElement
!= NULL
) {
5153 // Replace "&" with '\0'.
5155 *NextRequestElement
= L
'\0';
5158 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5160 if (NextRequestElement
!= NULL
) {
5162 // Restore '&' with '\0' for later used.
5164 *NextRequestElement
= L
'&';
5167 RequestElement
= NextRequestElement
;
5171 // If no request element remain, just remove the ConfigRequest string.
5173 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5174 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5175 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5176 Storage
->BrowserStorage
->SpareStrLen
= 0;
5181 Base on the current formset info, clean the ConfigRequest string in browser storage.
5183 @param FormSet Pointer of the FormSet
5187 CleanBrowserStorage (
5188 IN OUT FORM_BROWSER_FORMSET
*FormSet
5192 FORMSET_STORAGE
*Storage
;
5194 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5195 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5196 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5197 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5199 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5200 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5204 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5205 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5206 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5207 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5208 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5209 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5211 Storage
->BrowserStorage
->Initialized
= FALSE
;
5217 Check whether current element in the ConfigReqeust string.
5219 @param BrowserStorage Storage which includes ConfigReqeust.
5220 @param RequestElement New element need to check.
5222 @retval TRUE The Element is in the ConfigReqeust string.
5223 @retval FALSE The Element not in the configReqeust String.
5228 BROWSER_STORAGE
*BrowserStorage
,
5229 CHAR16
*RequestElement
5232 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5236 Append the Request element to the Config Request.
5238 @param ConfigRequest Current ConfigRequest info.
5239 @param SpareStrLen Current remain free buffer for config reqeust.
5240 @param RequestElement New Request element.
5244 AppendConfigRequest (
5245 IN OUT CHAR16
**ConfigRequest
,
5246 IN OUT UINTN
*SpareStrLen
,
5247 IN CHAR16
*RequestElement
5255 StrLength
= StrLen (RequestElement
);
5256 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5257 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5260 // Append <RequestElement> to <ConfigRequest>
5262 if (StrLength
> *SpareStrLen
) {
5264 // Old String buffer is not sufficient for RequestElement, allocate a new one
5266 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5267 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5268 ASSERT (NewStr
!= NULL
);
5270 if (*ConfigRequest
!= NULL
) {
5271 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5272 FreePool (*ConfigRequest
);
5274 *ConfigRequest
= NewStr
;
5275 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5278 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5279 *SpareStrLen
-= StrLength
;
5283 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5285 @param Storage Form set Storage.
5286 @param Request The input request string.
5287 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5289 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5290 @retval FALSE All elements covered by current used elements.
5294 ConfigRequestAdjust (
5295 IN BROWSER_STORAGE
*Storage
,
5297 IN BOOLEAN RespString
5300 CHAR16
*RequestElement
;
5301 CHAR16
*NextRequestElement
;
5302 CHAR16
*NextElementBakup
;
5306 CHAR16
*ConfigRequest
;
5309 NextElementBakup
= NULL
;
5312 if (Request
!= NULL
) {
5313 ConfigRequest
= Request
;
5315 ConfigRequest
= Storage
->ConfigRequest
;
5318 if (Storage
->ConfigRequest
== NULL
) {
5319 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5323 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5325 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5330 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5332 SearchKey
= L
"&OFFSET";
5333 ValueKey
= L
"&VALUE";
5337 // Find SearchKey storage
5339 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5340 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5341 ASSERT (RequestElement
!= NULL
);
5342 RequestElement
= StrStr (RequestElement
, SearchKey
);
5344 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5347 while (RequestElement
!= NULL
) {
5350 // +1 to avoid find header itself.
5352 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5355 // The last Request element in configRequest string.
5357 if (NextRequestElement
!= NULL
) {
5358 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5359 NextElementBakup
= NextRequestElement
;
5360 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5361 ASSERT (NextRequestElement
!= NULL
);
5364 // Replace "&" with '\0'.
5366 *NextRequestElement
= L
'\0';
5368 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5369 NextElementBakup
= NextRequestElement
;
5370 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5371 ASSERT (NextRequestElement
!= NULL
);
5373 // Replace "&" with '\0'.
5375 *NextRequestElement
= L
'\0';
5379 if (!ElementValidation (Storage
, RequestElement
)) {
5381 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5383 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5387 if (NextRequestElement
!= NULL
) {
5389 // Restore '&' with '\0' for later used.
5391 *NextRequestElement
= L
'&';
5394 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5395 RequestElement
= NextElementBakup
;
5397 RequestElement
= NextRequestElement
;
5405 Fill storage's edit copy with settings requested from Configuration Driver.
5407 @param FormSet FormSet data structure.
5408 @param Storage Buffer Storage.
5413 IN FORM_BROWSER_FORMSET
*FormSet
,
5414 IN FORMSET_STORAGE
*Storage
5418 EFI_STRING Progress
;
5421 EFI_STRING ConfigRequest
;
5424 ConfigRequest
= NULL
;
5426 switch (Storage
->BrowserStorage
->Type
) {
5427 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5430 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5431 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5432 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5437 case EFI_HII_VARSTORE_BUFFER
:
5438 case EFI_HII_VARSTORE_NAME_VALUE
:
5440 // Skip if there is no RequestElement.
5442 if (Storage
->ElementCount
== 0) {
5447 // Just update the ConfigRequest, if storage already initialized.
5449 if (Storage
->BrowserStorage
->Initialized
) {
5450 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5454 Storage
->BrowserStorage
->Initialized
= TRUE
;
5461 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5463 // Create the config request string to get all fields for this storage.
5464 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5465 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5467 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5468 ConfigRequest
= AllocateZeroPool (StrLen
);
5469 ASSERT (ConfigRequest
!= NULL
);
5473 L
"%s&OFFSET=0&WIDTH=%04x",
5475 Storage
->BrowserStorage
->Size
);
5477 ConfigRequest
= Storage
->ConfigRequest
;
5481 // Request current settings from Configuration Driver
5483 Status
= mHiiConfigRouting
->ExtractConfig (
5491 // If get value fail, extract default from IFR binary
5493 if (EFI_ERROR (Status
)) {
5494 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5497 // Convert Result from <ConfigAltResp> to <ConfigResp>
5499 StrPtr
= StrStr (Result
, L
"&GUID=");
5500 if (StrPtr
!= NULL
) {
5504 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5508 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5511 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5513 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5515 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5516 if (ConfigRequest
!= NULL
) {
5517 FreePool (ConfigRequest
);
5523 Get Value changed status from old question.
5525 @param NewFormSet FormSet data structure.
5526 @param OldQuestion Old question which has value changed.
5530 SyncStatusForQuestion (
5531 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5532 IN FORM_BROWSER_STATEMENT
*OldQuestion
5536 LIST_ENTRY
*QuestionLink
;
5537 FORM_BROWSER_FORM
*Form
;
5538 FORM_BROWSER_STATEMENT
*Question
;
5541 // For each form in one formset.
5543 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5544 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5545 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5546 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5549 // for each question in one form.
5551 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5552 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5553 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5554 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5556 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5557 Question
->ValueChanged
= TRUE
;
5565 Get Value changed status from old formset.
5567 @param NewFormSet FormSet data structure.
5568 @param OldFormSet FormSet data structure.
5572 SyncStatusForFormSet (
5573 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5574 IN FORM_BROWSER_FORMSET
*OldFormSet
5578 LIST_ENTRY
*QuestionLink
;
5579 FORM_BROWSER_FORM
*Form
;
5580 FORM_BROWSER_STATEMENT
*Question
;
5583 // For each form in one formset.
5585 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5586 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5587 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5588 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5591 // for each question in one form.
5593 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5594 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5595 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5596 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5598 if (!Question
->ValueChanged
) {
5603 // Find the same question in new formset and update the value changed flag.
5605 SyncStatusForQuestion (NewFormSet
, Question
);
5611 Get current setting of Questions.
5613 @param FormSet FormSet data structure.
5617 InitializeCurrentSetting (
5618 IN OUT FORM_BROWSER_FORMSET
*FormSet
5622 FORMSET_STORAGE
*Storage
;
5623 FORM_BROWSER_FORMSET
*OldFormSet
;
5626 // Try to find pre FormSet in the maintain backup list.
5627 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5629 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5630 if (OldFormSet
!= NULL
) {
5631 SyncStatusForFormSet (FormSet
, OldFormSet
);
5632 RemoveEntryList (&OldFormSet
->Link
);
5633 DestroyFormSet (OldFormSet
);
5635 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5638 // Extract default from IFR binary for no storage questions.
5640 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5643 // Request current settings from Configuration Driver
5645 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5646 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5647 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5649 LoadStorage (FormSet
, Storage
);
5651 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5657 Fetch the Ifr binary data of a FormSet.
5659 @param Handle PackageList Handle
5660 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5661 specified (NULL or zero GUID), take the first
5662 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5663 found in package list.
5664 On output, GUID of the formset found(if not NULL).
5665 @param BinaryLength The length of the FormSet IFR binary.
5666 @param BinaryData The buffer designed to receive the FormSet.
5668 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5669 BufferLength was updated.
5670 @retval EFI_INVALID_PARAMETER The handle is unknown.
5671 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5672 be found with the requested FormId.
5677 IN EFI_HII_HANDLE Handle
,
5678 IN OUT EFI_GUID
*FormSetGuid
,
5679 OUT UINTN
*BinaryLength
,
5680 OUT UINT8
**BinaryData
5684 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5690 UINT32 PackageListLength
;
5691 EFI_HII_PACKAGE_HEADER PackageHeader
;
5693 UINT8 NumberOfClassGuid
;
5694 BOOLEAN ClassGuidMatch
;
5695 EFI_GUID
*ClassGuid
;
5696 EFI_GUID
*ComparingGuid
;
5700 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5703 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5705 if (FormSetGuid
== NULL
) {
5706 ComparingGuid
= &gZeroGuid
;
5708 ComparingGuid
= FormSetGuid
;
5712 // Get HII PackageList
5715 HiiPackageList
= NULL
;
5716 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5717 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5718 HiiPackageList
= AllocatePool (BufferSize
);
5719 ASSERT (HiiPackageList
!= NULL
);
5721 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5723 if (EFI_ERROR (Status
)) {
5726 ASSERT (HiiPackageList
!= NULL
);
5729 // Get Form package from this HII package List
5731 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5733 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5735 ClassGuidMatch
= FALSE
;
5736 while (Offset
< PackageListLength
) {
5737 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5738 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5740 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5742 // Search FormSet in this Form Package
5744 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5745 while (Offset2
< PackageHeader
.Length
) {
5746 OpCodeData
= Package
+ Offset2
;
5748 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5750 // Try to compare against formset GUID
5752 if (IsZeroGuid (FormSetGuid
) ||
5753 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5757 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5759 // Try to compare against formset class GUID
5761 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5762 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5763 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5764 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5765 ClassGuidMatch
= TRUE
;
5769 if (ClassGuidMatch
) {
5772 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5773 ClassGuidMatch
= TRUE
;
5778 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5781 if (Offset2
< PackageHeader
.Length
) {
5783 // Target formset found
5789 Offset
+= PackageHeader
.Length
;
5792 if (Offset
>= PackageListLength
) {
5794 // Form package not found in this Package List
5796 FreePool (HiiPackageList
);
5797 return EFI_NOT_FOUND
;
5800 if (FormSetGuid
!= NULL
) {
5802 // Return the FormSet GUID
5804 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5808 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5809 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5810 // of the Form Package.
5812 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5813 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5815 FreePool (HiiPackageList
);
5817 if (*BinaryData
== NULL
) {
5818 return EFI_OUT_OF_RESOURCES
;
5826 Initialize the internal data structure of a FormSet.
5828 @param Handle PackageList Handle
5829 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5830 specified (NULL or zero GUID), take the first
5831 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5832 found in package list.
5833 On output, GUID of the formset found(if not NULL).
5834 @param FormSet FormSet data structure.
5836 @retval EFI_SUCCESS The function completed successfully.
5837 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5842 IN EFI_HII_HANDLE Handle
,
5843 IN OUT EFI_GUID
*FormSetGuid
,
5844 OUT FORM_BROWSER_FORMSET
*FormSet
5848 EFI_HANDLE DriverHandle
;
5850 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5851 if (EFI_ERROR (Status
)) {
5855 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5856 FormSet
->HiiHandle
= Handle
;
5857 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5858 FormSet
->QuestionInited
= FALSE
;
5861 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5863 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5864 if (EFI_ERROR (Status
)) {
5867 FormSet
->DriverHandle
= DriverHandle
;
5868 Status
= gBS
->HandleProtocol (
5870 &gEfiHiiConfigAccessProtocolGuid
,
5871 (VOID
**) &FormSet
->ConfigAccess
5873 if (EFI_ERROR (Status
)) {
5875 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5876 // list, then there will be no configuration action required
5878 FormSet
->ConfigAccess
= NULL
;
5882 // Parse the IFR binary OpCodes
5884 Status
= ParseOpCodes (FormSet
);
5891 Save globals used by previous call to SendForm(). SendForm() may be called from
5892 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5893 So, save globals of previous call to SendForm() and restore them upon exit.
5897 SaveBrowserContext (
5901 BROWSER_CONTEXT
*Context
;
5902 FORM_ENTRY_INFO
*MenuList
;
5903 FORM_BROWSER_FORMSET
*FormSet
;
5905 gBrowserContextCount
++;
5906 if (gBrowserContextCount
== 1) {
5908 // This is not reentry of SendForm(), no context to save
5913 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5914 ASSERT (Context
!= NULL
);
5916 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5919 // Save FormBrowser context
5921 Context
->Selection
= gCurrentSelection
;
5922 Context
->ResetRequired
= gResetRequiredFormLevel
;
5923 Context
->FlagReconnect
= gFlagReconnect
;
5924 Context
->CallbackReconnect
= gCallbackReconnect
;
5925 Context
->ExitRequired
= gExitRequired
;
5926 Context
->HiiHandle
= mCurrentHiiHandle
;
5927 Context
->FormId
= mCurrentFormId
;
5928 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5929 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
5930 Context
->CurFakeQestId
= mCurFakeQestId
;
5931 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
5932 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
5935 // Save the menu history data.
5937 InitializeListHead(&Context
->FormHistoryList
);
5938 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5939 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5940 RemoveEntryList (&MenuList
->Link
);
5942 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5946 // Save formset list.
5948 InitializeListHead(&Context
->FormSetList
);
5949 while (!IsListEmpty (&gBrowserFormSetList
)) {
5950 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
5951 RemoveEntryList (&FormSet
->Link
);
5953 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
5957 // Insert to FormBrowser context list
5959 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5964 Restore globals used by previous call to SendForm().
5968 RestoreBrowserContext (
5973 BROWSER_CONTEXT
*Context
;
5974 FORM_ENTRY_INFO
*MenuList
;
5975 FORM_BROWSER_FORMSET
*FormSet
;
5977 ASSERT (gBrowserContextCount
!= 0);
5978 gBrowserContextCount
--;
5979 if (gBrowserContextCount
== 0) {
5981 // This is not reentry of SendForm(), no context to restore
5986 ASSERT (!IsListEmpty (&gBrowserContextList
));
5988 Link
= GetFirstNode (&gBrowserContextList
);
5989 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5992 // Restore FormBrowser context
5994 gCurrentSelection
= Context
->Selection
;
5995 gResetRequiredFormLevel
= Context
->ResetRequired
;
5996 gFlagReconnect
= Context
->FlagReconnect
;
5997 gCallbackReconnect
= Context
->CallbackReconnect
;
5998 gExitRequired
= Context
->ExitRequired
;
5999 mCurrentHiiHandle
= Context
->HiiHandle
;
6000 mCurrentFormId
= Context
->FormId
;
6001 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6002 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6003 mCurFakeQestId
= Context
->CurFakeQestId
;
6004 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6005 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6008 // Restore the menu history data.
6010 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6011 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6012 RemoveEntryList (&MenuList
->Link
);
6014 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6018 // Restore the Formset data.
6020 while (!IsListEmpty (&Context
->FormSetList
)) {
6021 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6022 RemoveEntryList (&FormSet
->Link
);
6024 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
6028 // Remove from FormBrowser context list
6030 RemoveEntryList (&Context
->Link
);
6031 gBS
->FreePool (Context
);
6035 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6037 @param Handle The Hii Handle.
6039 @return the found FormSet context. If no found, NULL will return.
6042 FORM_BROWSER_FORMSET
*
6043 GetFormSetFromHiiHandle (
6044 EFI_HII_HANDLE Handle
6048 FORM_BROWSER_FORMSET
*FormSet
;
6050 Link
= GetFirstNode (&gBrowserFormSetList
);
6051 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6052 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6053 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6054 if (!ValidateFormSet(FormSet
)) {
6057 if (FormSet
->HiiHandle
== Handle
) {
6066 Check whether the input HII handle is the FormSet that is being used.
6068 @param Handle The Hii Handle.
6070 @retval TRUE HII handle is being used.
6071 @retval FALSE HII handle is not being used.
6075 IsHiiHandleInBrowserContext (
6076 EFI_HII_HANDLE Handle
6080 BROWSER_CONTEXT
*Context
;
6083 // HiiHandle is Current FormSet.
6085 if (mCurrentHiiHandle
== Handle
) {
6090 // Check whether HiiHandle is in BrowserContext.
6092 Link
= GetFirstNode (&gBrowserContextList
);
6093 while (!IsNull (&gBrowserContextList
, Link
)) {
6094 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6095 if (Context
->HiiHandle
== Handle
) {
6097 // HiiHandle is in BrowserContext
6101 Link
= GetNextNode (&gBrowserContextList
, Link
);
6108 Perform Password check.
6109 Passwork may be encrypted by driver that requires the specific check.
6111 @param Form Form where Password Statement is in.
6112 @param Statement Password statement
6113 @param PasswordString Password string to be checked. It may be NULL.
6114 NULL means to restore password.
6115 "" string can be used to checked whether old password does exist.
6117 @return Status Status of Password check.
6122 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6123 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6124 IN EFI_STRING PasswordString OPTIONAL
6128 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6129 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6130 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6131 FORM_BROWSER_STATEMENT
*Question
;
6133 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6134 Question
= GetBrowserStatement(Statement
);
6135 ASSERT (Question
!= NULL
);
6137 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6138 if (ConfigAccess
== NULL
) {
6139 return EFI_UNSUPPORTED
;
6143 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6145 return EFI_UNSUPPORTED
;
6149 // Prepare password string in HII database
6151 if (PasswordString
!= NULL
) {
6152 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6154 IfrTypeValue
.string
= 0;
6158 // Send password to Configuration Driver for validation
6160 Status
= ConfigAccess
->Callback (
6162 EFI_BROWSER_ACTION_CHANGING
,
6163 Question
->QuestionId
,
6164 Question
->HiiValue
.Type
,
6170 // Remove password string from HII database
6172 if (PasswordString
!= NULL
) {
6173 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6180 Find the registered HotKey based on KeyData.
6182 @param[in] KeyData A pointer to a buffer that describes the keystroke
6183 information for the hot key.
6185 @return The registered HotKey context. If no found, NULL will return.
6188 GetHotKeyFromRegisterList (
6189 IN EFI_INPUT_KEY
*KeyData
6193 BROWSER_HOT_KEY
*HotKey
;
6195 Link
= GetFirstNode (&gBrowserHotKeyList
);
6196 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6197 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6198 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6201 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6208 Configure what scope the hot key will impact.
6209 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6210 If no scope is set, the default scope will be FormSet level.
6211 After all registered hot keys are removed, previous Scope can reset to another level.
6213 @param[in] Scope Scope level to be set.
6215 @retval EFI_SUCCESS Scope is set correctly.
6216 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6217 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6223 IN BROWSER_SETTING_SCOPE Scope
6226 if (Scope
>= MaxLevel
) {
6227 return EFI_INVALID_PARAMETER
;
6231 // When no hot key registered in system or on the first setting,
6232 // Scope can be set.
6234 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6235 gBrowserSettingScope
= Scope
;
6236 mBrowserScopeFirstSet
= FALSE
;
6237 } else if (Scope
!= gBrowserSettingScope
) {
6238 return EFI_UNSUPPORTED
;
6245 Register the hot key with its browser action, or unregistered the hot key.
6246 Only support hot key that is not printable character (control key, function key, etc.).
6247 If the action value is zero, the hot key will be unregistered if it has been registered.
6248 If the same hot key has been registered, the new action and help string will override the previous ones.
6250 @param[in] KeyData A pointer to a buffer that describes the keystroke
6251 information for the hot key. Its type is EFI_INPUT_KEY to
6252 be supported by all ConsoleIn devices.
6253 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6254 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6255 @param[in] HelpString Help string that describes the hot key information.
6256 Its value may be NULL for the unregistered hot key.
6258 @retval EFI_SUCCESS Hot key is registered or unregistered.
6259 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6260 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6261 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6262 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6267 IN EFI_INPUT_KEY
*KeyData
,
6269 IN UINT16 DefaultId
,
6270 IN EFI_STRING HelpString OPTIONAL
6273 BROWSER_HOT_KEY
*HotKey
;
6276 // Check input parameters.
6278 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6279 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6280 return EFI_INVALID_PARAMETER
;
6284 // Check whether the input KeyData is in BrowserHotKeyList.
6286 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6289 // Unregister HotKey
6291 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6292 if (HotKey
!= NULL
) {
6294 // The registered HotKey is found.
6295 // Remove it from List, and free its resource.
6297 RemoveEntryList (&HotKey
->Link
);
6298 FreePool (HotKey
->KeyData
);
6299 FreePool (HotKey
->HelpString
);
6303 // The registered HotKey is not found.
6305 return EFI_NOT_FOUND
;
6309 if (HotKey
!= NULL
) {
6310 return EFI_ALREADY_STARTED
;
6314 // Create new Key, and add it into List.
6316 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6317 ASSERT (HotKey
!= NULL
);
6318 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6319 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6320 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6323 // Fill HotKey information.
6325 HotKey
->Action
= Action
;
6326 HotKey
->DefaultId
= DefaultId
;
6327 if (HotKey
->HelpString
!= NULL
) {
6328 FreePool (HotKey
->HelpString
);
6330 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6336 Register Exit handler function.
6337 When more than one handler function is registered, the latter one will override the previous one.
6338 When NULL handler is specified, the previous Exit handler will be unregistered.
6340 @param[in] Handler Pointer to handler function.
6345 RegiserExitHandler (
6346 IN EXIT_HANDLER Handler
6349 ExitHandlerFunction
= Handler
;
6354 Check whether the browser data has been modified.
6356 @retval TRUE Browser data is modified.
6357 @retval FALSE No browser data is modified.
6362 IsBrowserDataModified (
6367 FORM_BROWSER_FORMSET
*FormSet
;
6369 switch (gBrowserSettingScope
) {
6371 if (gCurrentSelection
== NULL
) {
6374 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6377 if (gCurrentSelection
== NULL
) {
6380 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6383 Link
= GetFirstNode (&gBrowserFormSetList
);
6384 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6385 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6386 if (!ValidateFormSet(FormSet
)) {
6390 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6393 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6403 Execute the action requested by the Action parameter.
6405 @param[in] Action Execute the request action.
6406 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6408 @retval EFI_SUCCESS Execute the request action succss.
6409 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6420 FORM_BROWSER_FORMSET
*FormSet
;
6421 FORM_BROWSER_FORM
*Form
;
6423 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6424 return EFI_NOT_READY
;
6427 Status
= EFI_SUCCESS
;
6430 if (gBrowserSettingScope
< SystemLevel
) {
6431 FormSet
= gCurrentSelection
->FormSet
;
6432 Form
= gCurrentSelection
->Form
;
6436 // Executet the discard action.
6438 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6439 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6440 if (EFI_ERROR (Status
)) {
6446 // Executet the difault action.
6448 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6449 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6450 if (EFI_ERROR (Status
)) {
6453 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6457 // Executet the submit action.
6459 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6460 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6461 if (EFI_ERROR (Status
)) {
6467 // Executet the reset action.
6469 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6470 gResetRequiredFormLevel
= TRUE
;
6471 gResetRequiredSystemLevel
= TRUE
;
6475 // Executet the exit action.
6477 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6478 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6479 if (gBrowserSettingScope
== SystemLevel
) {
6480 if (ExitHandlerFunction
!= NULL
) {
6481 ExitHandlerFunction ();
6485 gExitRequired
= TRUE
;
6492 Create reminder to let user to choose save or discard the changed browser data.
6493 Caller can use it to actively check the changed browser data.
6495 @retval BROWSER_NO_CHANGES No browser data is changed.
6496 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6497 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6498 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6508 FORM_BROWSER_FORMSET
*FormSet
;
6509 BOOLEAN IsDataChanged
;
6510 UINT32 DataSavedAction
;
6513 DataSavedAction
= BROWSER_NO_CHANGES
;
6514 IsDataChanged
= FALSE
;
6515 Link
= GetFirstNode (&gBrowserFormSetList
);
6516 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6517 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6518 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6519 if (!ValidateFormSet(FormSet
)) {
6522 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6523 IsDataChanged
= TRUE
;
6529 // No data is changed. No save is required.
6531 if (!IsDataChanged
) {
6532 return DataSavedAction
;
6536 // If data is changed, prompt user to save or discard it.
6539 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6541 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6542 SubmitForm (NULL
, NULL
, SystemLevel
);
6543 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6545 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6546 DiscardForm (NULL
, NULL
, SystemLevel
);
6547 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6549 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6550 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6555 return DataSavedAction
;
6559 Check whether the Reset Required for the browser
6561 @retval TRUE Browser required to reset after exit.
6562 @retval FALSE Browser not need to reset after exit.
6571 return gResetRequiredSystemLevel
;