2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2014, 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
);
54 BOOLEAN gResetRequired
;
55 BOOLEAN gExitRequired
;
56 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
57 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
58 EXIT_HANDLER ExitHandlerFunction
= NULL
;
59 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
62 // Browser Global Strings
65 CHAR16
*mUnknownString
= L
"!";
67 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
69 extern EFI_GUID mCurrentFormSetGuid
;
70 extern EFI_HII_HANDLE mCurrentHiiHandle
;
71 extern UINT16 mCurrentFormId
;
72 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
75 Create a menu with specified formset GUID and form ID, and add it as a child
76 of the given parent menu.
78 @param HiiHandle Hii handle related to this formset.
79 @param FormSetGuid The Formset Guid of menu to be added.
80 @param FormId The Form ID of menu to be added.
81 @param QuestionId The question id of this menu to be added.
83 @return A pointer to the newly added menu or NULL if memory is insufficient.
88 IN EFI_HII_HANDLE HiiHandle
,
89 IN EFI_GUID
*FormSetGuid
,
94 FORM_ENTRY_INFO
*MenuList
;
96 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
97 if (MenuList
== NULL
) {
101 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
103 MenuList
->HiiHandle
= HiiHandle
;
104 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
105 MenuList
->FormId
= FormId
;
106 MenuList
->QuestionId
= QuestionId
;
109 // If parent is not specified, it is the root Form of a Formset
111 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
117 Return the form id for the input hiihandle and formset.
119 @param HiiHandle HiiHandle for FormSet.
120 @param FormSetGuid The Formset GUID of the menu to search.
122 @return First form's id for this form set.
127 IN EFI_HII_HANDLE HiiHandle
,
128 IN EFI_GUID
*FormSetGuid
132 FORM_BROWSER_FORM
*Form
;
134 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
135 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
141 Search Menu with given FormSetGuid and FormId in all cached menu list.
143 @param HiiHandle HiiHandle for FormSet.
144 @param FormSetGuid The Formset GUID of the menu to search.
145 @param FormId The Form ID of menu to search.
147 @return A pointer to menu found or NULL if not found.
152 IN EFI_HII_HANDLE HiiHandle
,
153 IN EFI_GUID
*FormSetGuid
,
158 FORM_ENTRY_INFO
*MenuList
;
159 FORM_ENTRY_INFO
*RetMenu
;
160 EFI_FORM_ID FirstFormId
;
164 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
165 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
166 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
167 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
170 // If already find the menu, free the menus behind it.
172 if (RetMenu
!= NULL
) {
173 RemoveEntryList (&MenuList
->Link
);
179 // Find the same FromSet.
181 if (MenuList
->HiiHandle
== HiiHandle
) {
182 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
184 // FormSetGuid is not specified.
187 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
188 if (MenuList
->FormId
== FormId
) {
190 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
191 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
192 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
204 Find parent menu for current menu.
206 @param CurrentMenu Current Menu
208 @retval The parent menu for current menu.
212 IN FORM_ENTRY_INFO
*CurrentMenu
215 FORM_ENTRY_INFO
*ParentMenu
;
218 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
219 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
226 Free Menu list linked list.
228 @param MenuListHead One Menu list point in the menu list.
233 LIST_ENTRY
*MenuListHead
236 FORM_ENTRY_INFO
*MenuList
;
238 while (!IsListEmpty (MenuListHead
)) {
239 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
240 RemoveEntryList (&MenuList
->Link
);
247 Load all hii formset to the browser.
255 FORM_BROWSER_FORMSET
*LocalFormSet
;
256 EFI_HII_HANDLE
*HiiHandles
;
260 FORM_BROWSER_FORMSET
*OldFormset
;
262 OldFormset
= mSystemLevelFormSet
;
265 // Get all the Hii handles
267 HiiHandles
= HiiGetHiiHandles (NULL
);
268 ASSERT (HiiHandles
!= NULL
);
271 // Search for formset of each class type
273 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
275 // Check HiiHandles[Index] does exist in global maintain list.
277 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
282 // Initilize FormSet Setting
284 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
285 ASSERT (LocalFormSet
!= NULL
);
286 mSystemLevelFormSet
= LocalFormSet
;
288 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
289 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
290 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
291 DestroyFormSet (LocalFormSet
);
294 InitializeCurrentSetting (LocalFormSet
);
297 // Initilize Questions' Value
299 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
300 if (EFI_ERROR (Status
)) {
301 DestroyFormSet (LocalFormSet
);
307 // Free resources, and restore gOldFormSet and gClassOfVfr
309 FreePool (HiiHandles
);
311 mSystemLevelFormSet
= OldFormset
;
315 Pop up the error info.
317 @param BrowserStatus The input browser status.
318 @param OpCode The opcode use to get the erro info and timeout value.
319 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
324 IN UINT32 BrowserStatus
,
325 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
326 IN CHAR16
*ErrorString
329 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
333 if (OpCode
!= NULL
) {
334 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
335 ASSERT (Statement
!= NULL
);
336 Statement
->OpCode
= OpCode
;
337 gDisplayFormData
.HighLightedStatement
= Statement
;
341 // Used to compatible with old display engine.
342 // New display engine not use this field.
344 gDisplayFormData
.ErrorString
= ErrorString
;
345 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
347 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
349 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
350 gDisplayFormData
.ErrorString
= NULL
;
352 if (OpCode
!= NULL
) {
353 FreePool (Statement
);
358 This is the routine which an external caller uses to direct the browser
359 where to obtain it's information.
362 @param This The Form Browser protocol instanse.
363 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
364 display a list of the formsets for the handles specified.
365 @param HandleCount The number of Handles specified in Handle.
366 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
367 field in the EFI_IFR_FORM_SET op-code for the specified
368 forms-based package. If FormSetGuid is NULL, then this
369 function will display the first found forms package.
370 @param FormId This field specifies which EFI_IFR_FORM to render as the first
371 displayable page. If this field has a value of 0x0000, then
372 the forms browser will render the specified forms in their encoded order.
373 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
375 @param ActionRequest Points to the action recommended by the form.
377 @retval EFI_SUCCESS The function completed successfully.
378 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
379 @retval EFI_NOT_FOUND No valid forms could be found to display.
385 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
386 IN EFI_HII_HANDLE
*Handles
,
387 IN UINTN HandleCount
,
388 IN EFI_GUID
*FormSetGuid
, OPTIONAL
389 IN UINT16 FormId
, OPTIONAL
390 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
391 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
395 UI_MENU_SELECTION
*Selection
;
397 FORM_BROWSER_FORMSET
*FormSet
;
398 FORM_ENTRY_INFO
*MenuList
;
401 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
403 if (mFormDisplay
== NULL
) {
404 return EFI_UNSUPPORTED
;
408 // Save globals used by SendForm()
410 SaveBrowserContext ();
412 gResetRequired
= FALSE
;
413 gExitRequired
= FALSE
;
414 Status
= EFI_SUCCESS
;
416 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
418 for (Index
= 0; Index
< HandleCount
; Index
++) {
419 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
420 ASSERT (Selection
!= NULL
);
422 Selection
->Handle
= Handles
[Index
];
423 if (FormSetGuid
!= NULL
) {
424 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
425 Selection
->FormId
= FormId
;
427 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
431 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
432 ASSERT (FormSet
!= NULL
);
435 // Initialize internal data structures of FormSet
437 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
438 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
439 DestroyFormSet (FormSet
);
442 Selection
->FormSet
= FormSet
;
443 mSystemLevelFormSet
= FormSet
;
446 // Display this formset
448 gCurrentSelection
= Selection
;
450 Status
= SetupBrowser (Selection
);
452 gCurrentSelection
= NULL
;
453 mSystemLevelFormSet
= NULL
;
456 // If no data is changed, don't need to save current FormSet into the maintain list.
458 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
459 CleanBrowserStorage(FormSet
);
460 RemoveEntryList (&FormSet
->Link
);
461 DestroyFormSet (FormSet
);
464 if (EFI_ERROR (Status
)) {
467 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
469 FreePool (Selection
);
472 if (ActionRequest
!= NULL
) {
473 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
474 if (gResetRequired
) {
475 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
479 mFormDisplay
->ExitDisplay();
482 // Clear the menu history data.
484 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
485 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
486 RemoveEntryList (&MenuList
->Link
);
491 // Restore globals used by SendForm()
493 RestoreBrowserContext ();
499 Get or set data to the storage.
501 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
502 @param ResultsData A string returned from an IFR browser or
503 equivalent. The results string will have no
504 routing information in them.
505 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
506 (if RetrieveData = TRUE) data from the uncommitted
507 browser state information or set (if RetrieveData
508 = FALSE) data in the uncommitted browser state
510 @param Storage The pointer to the storage.
512 @retval EFI_SUCCESS The results have been distributed or are awaiting
518 IN OUT UINTN
*ResultsDataSize
,
519 IN OUT EFI_STRING
*ResultsData
,
520 IN BOOLEAN RetrieveData
,
521 IN BROWSER_STORAGE
*Storage
532 // Generate <ConfigResp>
534 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
535 if (EFI_ERROR (Status
)) {
540 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
541 // Also need to consider add "\0" at first time.
543 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
544 BufferSize
= StrSize (StrPtr
);
548 // Copy the data if the input buffer is bigger enough.
550 if (*ResultsDataSize
>= BufferSize
) {
551 StrCpy (*ResultsData
, StrPtr
);
554 *ResultsDataSize
= BufferSize
;
555 FreePool (ConfigResp
);
558 // Prepare <ConfigResp>
560 TmpSize
= StrLen (*ResultsData
);
561 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
562 ConfigResp
= AllocateZeroPool (BufferSize
);
563 ASSERT (ConfigResp
!= NULL
);
565 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
566 StrCat (ConfigResp
, L
"&");
567 StrCat (ConfigResp
, *ResultsData
);
570 // Update Browser uncommited data
572 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
573 FreePool (ConfigResp
);
574 if (EFI_ERROR (Status
)) {
583 This routine called this service in the browser to retrieve or set certain uncommitted
584 state information that resides in the open formsets.
586 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
588 @param ResultsDataSize A pointer to the size of the buffer associated
590 @param ResultsData A string returned from an IFR browser or
591 equivalent. The results string will have no
592 routing information in them.
593 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
594 (if RetrieveData = TRUE) data from the uncommitted
595 browser state information or set (if RetrieveData
596 = FALSE) data in the uncommitted browser state
598 @param VariableGuid An optional field to indicate the target variable
600 @param VariableName An optional field to indicate the target
601 human-readable variable name.
603 @retval EFI_SUCCESS The results have been distributed or are awaiting
605 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
606 contain the results data.
612 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
613 IN OUT UINTN
*ResultsDataSize
,
614 IN OUT EFI_STRING ResultsData
,
615 IN BOOLEAN RetrieveData
,
616 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
617 IN CONST CHAR16
*VariableName OPTIONAL
622 BROWSER_STORAGE
*Storage
;
623 FORMSET_STORAGE
*FormsetStorage
;
627 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
628 return EFI_INVALID_PARAMETER
;
631 TotalSize
= *ResultsDataSize
;
634 Status
= EFI_SUCCESS
;
636 if (VariableGuid
!= NULL
) {
638 // Try to find target storage in the current formset.
640 Link
= GetFirstNode (&gBrowserStorageList
);
641 while (!IsNull (&gBrowserStorageList
, Link
)) {
642 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
643 Link
= GetNextNode (&gBrowserStorageList
, Link
);
645 // Check the current storage.
647 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
651 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
652 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
654 // Buffer storage require both GUID and Name
656 if (VariableName
== NULL
) {
657 return EFI_NOT_FOUND
;
660 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
665 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
666 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
667 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
668 return EFI_NOT_FOUND
;
671 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
676 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
677 if (EFI_ERROR (Status
)) {
681 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
682 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
686 // Different formsets may have same varstore, so here just set the flag
687 // not exit the circle.
694 return EFI_NOT_FOUND
;
698 // GUID/Name is not specified, take the first storage in FormSet
700 if (mSystemLevelFormSet
== NULL
) {
701 return EFI_NOT_READY
;
705 // Generate <ConfigResp>
707 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
708 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
709 return EFI_UNSUPPORTED
;
712 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
714 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
715 if (EFI_ERROR (Status
)) {
721 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
722 *ResultsDataSize
= TotalSize
;
731 Callback function for SimpleTextInEx protocol install events
733 @param Event the event that is signaled.
734 @param Context not used here.
739 FormDisplayCallback (
746 if (mFormDisplay
!= NULL
) {
750 Status
= gBS
->LocateProtocol (
751 &gEdkiiFormDisplayEngineProtocolGuid
,
753 (VOID
**) &mFormDisplay
758 Initialize Setup Browser driver.
760 @param ImageHandle The image handle.
761 @param SystemTable The system table.
763 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
764 @return Other value if failed to initialize the Setup Browser module.
770 IN EFI_HANDLE ImageHandle
,
771 IN EFI_SYSTEM_TABLE
*SystemTable
778 // Locate required Hii relative protocols
780 Status
= gBS
->LocateProtocol (
781 &gEfiHiiDatabaseProtocolGuid
,
783 (VOID
**) &mHiiDatabase
785 ASSERT_EFI_ERROR (Status
);
787 Status
= gBS
->LocateProtocol (
788 &gEfiHiiConfigRoutingProtocolGuid
,
790 (VOID
**) &mHiiConfigRouting
792 ASSERT_EFI_ERROR (Status
);
794 Status
= gBS
->LocateProtocol (
795 &gEfiDevicePathFromTextProtocolGuid
,
797 (VOID
**) &mPathFromText
801 // Install FormBrowser2 protocol
803 mPrivateData
.Handle
= NULL
;
804 Status
= gBS
->InstallProtocolInterface (
805 &mPrivateData
.Handle
,
806 &gEfiFormBrowser2ProtocolGuid
,
807 EFI_NATIVE_INTERFACE
,
808 &mPrivateData
.FormBrowser2
810 ASSERT_EFI_ERROR (Status
);
813 // Install FormBrowserEx2 protocol
815 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
816 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
817 mPrivateData
.Handle
= NULL
;
818 Status
= gBS
->InstallProtocolInterface (
819 &mPrivateData
.Handle
,
820 &gEdkiiFormBrowserEx2ProtocolGuid
,
821 EFI_NATIVE_INTERFACE
,
822 &mPrivateData
.FormBrowserEx2
824 ASSERT_EFI_ERROR (Status
);
826 Status
= gBS
->InstallProtocolInterface (
827 &mPrivateData
.Handle
,
828 &gEfiFormBrowserExProtocolGuid
,
829 EFI_NATIVE_INTERFACE
,
830 &mPrivateData
.FormBrowserEx
832 ASSERT_EFI_ERROR (Status
);
834 InitializeDisplayFormData ();
836 Status
= gBS
->LocateProtocol (
837 &gEdkiiFormDisplayEngineProtocolGuid
,
839 (VOID
**) &mFormDisplay
842 if (EFI_ERROR (Status
)) {
843 EfiCreateProtocolNotifyEvent (
844 &gEdkiiFormDisplayEngineProtocolGuid
,
857 Create a new string in HII Package List.
859 @param String The String to be added
860 @param HiiHandle The package list in the HII database to insert the
863 @return The output string.
869 IN EFI_HII_HANDLE HiiHandle
872 EFI_STRING_ID StringId
;
874 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
875 ASSERT (StringId
!= 0);
882 Delete a string from HII Package List.
884 @param StringId Id of the string in HII database.
885 @param HiiHandle The HII package list handle.
887 @retval EFI_SUCCESS The string was deleted successfully.
892 IN EFI_STRING_ID StringId
,
893 IN EFI_HII_HANDLE HiiHandle
898 NullChar
= CHAR_NULL
;
899 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
905 Get the string based on the StringId and HII Package List Handle.
907 @param Token The String's ID.
908 @param HiiHandle The package list in the HII database to search for
909 the specified string.
911 @return The output string.
916 IN EFI_STRING_ID Token
,
917 IN EFI_HII_HANDLE HiiHandle
922 if (HiiHandle
== NULL
) {
926 String
= HiiGetString (HiiHandle
, Token
, NULL
);
927 if (String
== NULL
) {
928 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
929 ASSERT (String
!= NULL
);
931 return (CHAR16
*) String
;
936 Allocate new memory and then copy the Unicode string Source to Destination.
938 @param Dest Location to copy string
939 @param Src String to copy
944 IN OUT CHAR16
**Dest
,
951 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
952 ASSERT (*Dest
!= NULL
);
957 Allocate new memory and concatinate Source on the end of Destination.
959 @param Dest String to added to the end of.
960 @param Src String to concatinate.
965 IN OUT CHAR16
**Dest
,
973 NewStringCpy (Dest
, Src
);
977 TmpSize
= StrSize (*Dest
);
978 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
979 ASSERT (NewString
!= NULL
);
981 StrCpy (NewString
, *Dest
);
982 StrCat (NewString
, Src
);
989 Get Value for given Name from a NameValue Storage.
991 @param Storage The NameValue Storage.
992 @param Name The Name.
993 @param Value The retured Value.
994 @param GetValueFrom Where to get source value, from EditValue or Value.
996 @retval EFI_SUCCESS Value found for given Name.
997 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1002 IN BROWSER_STORAGE
*Storage
,
1004 IN OUT CHAR16
**Value
,
1005 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1009 NAME_VALUE_NODE
*Node
;
1011 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1012 return EFI_INVALID_PARAMETER
;
1017 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1018 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1019 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1021 if (StrCmp (Name
, Node
->Name
) == 0) {
1022 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1023 NewStringCpy (Value
, Node
->EditValue
);
1025 NewStringCpy (Value
, Node
->Value
);
1030 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1033 return EFI_NOT_FOUND
;
1038 Set Value of given Name in a NameValue Storage.
1040 @param Storage The NameValue Storage.
1041 @param Name The Name.
1042 @param Value The Value to set.
1043 @param SetValueTo Whether update editValue or Value.
1044 @param ReturnNode The node use the input name.
1046 @retval EFI_SUCCESS Value found for given Name.
1047 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1052 IN BROWSER_STORAGE
*Storage
,
1055 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1056 OUT NAME_VALUE_NODE
**ReturnNode
1060 NAME_VALUE_NODE
*Node
;
1063 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1064 return EFI_INVALID_PARAMETER
;
1067 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1068 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1069 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1071 if (StrCmp (Name
, Node
->Name
) == 0) {
1072 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1073 Buffer
= Node
->EditValue
;
1075 Buffer
= Node
->Value
;
1077 if (Buffer
!= NULL
) {
1080 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1081 ASSERT (Buffer
!= NULL
);
1082 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1083 Node
->EditValue
= Buffer
;
1085 Node
->Value
= Buffer
;
1088 if (ReturnNode
!= NULL
) {
1095 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1098 return EFI_NOT_FOUND
;
1103 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1105 @param Storage The Storage to be conveted.
1106 @param ConfigResp The returned <ConfigResp>.
1107 @param ConfigRequest The ConfigRequest string.
1108 @param GetEditBuf Get the data from editbuffer or buffer.
1110 @retval EFI_SUCCESS Convert success.
1111 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1115 StorageToConfigResp (
1116 IN BROWSER_STORAGE
*Storage
,
1117 IN CHAR16
**ConfigResp
,
1118 IN CHAR16
*ConfigRequest
,
1119 IN BOOLEAN GetEditBuf
1123 EFI_STRING Progress
;
1125 NAME_VALUE_NODE
*Node
;
1128 Status
= EFI_SUCCESS
;
1130 switch (Storage
->Type
) {
1131 case EFI_HII_VARSTORE_BUFFER
:
1132 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1133 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1134 Status
= mHiiConfigRouting
->BlockToConfig (
1144 case EFI_HII_VARSTORE_NAME_VALUE
:
1146 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1148 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1149 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1150 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1152 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1153 NewStringCat (ConfigResp
, L
"&");
1154 NewStringCat (ConfigResp
, Node
->Name
);
1155 NewStringCat (ConfigResp
, L
"=");
1157 NewStringCat (ConfigResp
, Node
->EditValue
);
1159 NewStringCat (ConfigResp
, Node
->Value
);
1162 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1166 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1168 Status
= EFI_INVALID_PARAMETER
;
1177 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1179 @param Storage The Storage to receive the settings.
1180 @param ConfigResp The <ConfigResp> to be converted.
1182 @retval EFI_SUCCESS Convert success.
1183 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1187 ConfigRespToStorage (
1188 IN BROWSER_STORAGE
*Storage
,
1189 IN CHAR16
*ConfigResp
1193 EFI_STRING Progress
;
1199 Status
= EFI_SUCCESS
;
1201 switch (Storage
->Type
) {
1202 case EFI_HII_VARSTORE_BUFFER
:
1203 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1204 BufferSize
= Storage
->Size
;
1205 Status
= mHiiConfigRouting
->ConfigToBlock (
1208 Storage
->EditBuffer
,
1214 case EFI_HII_VARSTORE_NAME_VALUE
:
1215 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1216 if (StrPtr
== NULL
) {
1219 StrPtr
= StrStr (ConfigResp
, L
"&");
1220 while (StrPtr
!= NULL
) {
1224 StrPtr
= StrPtr
+ 1;
1226 StrPtr
= StrStr (StrPtr
, L
"=");
1227 if (StrPtr
== NULL
) {
1235 StrPtr
= StrPtr
+ 1;
1237 StrPtr
= StrStr (StrPtr
, L
"&");
1238 if (StrPtr
!= NULL
) {
1241 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1245 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1247 Status
= EFI_INVALID_PARAMETER
;
1256 Get Question's current Value.
1258 @param FormSet FormSet data structure.
1259 @param Form Form data structure.
1260 @param Question Question to be initialized.
1261 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1263 @retval EFI_SUCCESS The function completed successfully.
1268 IN FORM_BROWSER_FORMSET
*FormSet
,
1269 IN FORM_BROWSER_FORM
*Form
,
1270 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1271 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1280 BROWSER_STORAGE
*Storage
;
1281 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1282 CHAR16
*ConfigRequest
;
1290 BOOLEAN IsBufferStorage
;
1295 Status
= EFI_SUCCESS
;
1299 if (GetValueFrom
>= GetSetValueWithMax
) {
1300 return EFI_INVALID_PARAMETER
;
1304 // Question value is provided by an Expression, evaluate it
1306 if (Question
->ValueExpression
!= NULL
) {
1307 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1308 if (!EFI_ERROR (Status
)) {
1309 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1310 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1311 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1312 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1313 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1315 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1316 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1318 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1320 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1321 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1327 // Get question value by read expression.
1329 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1330 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1331 if (!EFI_ERROR (Status
) &&
1332 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1334 // Only update question value to the valid result.
1336 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1337 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1338 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1339 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1340 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1342 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1343 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1345 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1347 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1348 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1354 // Question value is provided by RTC
1356 Storage
= Question
->Storage
;
1357 QuestionValue
= &Question
->HiiValue
.Value
;
1358 if (Storage
== NULL
) {
1360 // It's a Question without storage, or RTC date/time
1362 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1364 // Date and time define the same Flags bit
1366 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1367 case QF_DATE_STORAGE_TIME
:
1368 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1371 case QF_DATE_STORAGE_WAKEUP
:
1372 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1375 case QF_DATE_STORAGE_NORMAL
:
1378 // For date/time without storage
1383 if (EFI_ERROR (Status
)) {
1387 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1388 QuestionValue
->date
.Year
= EfiTime
.Year
;
1389 QuestionValue
->date
.Month
= EfiTime
.Month
;
1390 QuestionValue
->date
.Day
= EfiTime
.Day
;
1392 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1393 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1394 QuestionValue
->time
.Second
= EfiTime
.Second
;
1402 // Question value is provided by EFI variable
1404 StorageWidth
= Question
->StorageWidth
;
1405 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1406 if (Question
->BufferValue
!= NULL
) {
1407 Dst
= Question
->BufferValue
;
1409 Dst
= (UINT8
*) QuestionValue
;
1412 Status
= gRT
->GetVariable (
1413 Question
->VariableName
,
1420 // Always return success, even this EFI variable doesn't exist
1426 // Question Value is provided by Buffer Storage or NameValue Storage
1428 if (Question
->BufferValue
!= NULL
) {
1430 // This Question is password or orderedlist
1432 Dst
= Question
->BufferValue
;
1435 // Other type of Questions
1437 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1440 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1441 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1442 IsBufferStorage
= TRUE
;
1444 IsBufferStorage
= FALSE
;
1446 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1447 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1448 if (IsBufferStorage
) {
1449 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1451 // Copy from storage Edit buffer
1453 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1456 // Copy from storage Edit buffer
1458 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1462 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1463 if (EFI_ERROR (Status
)) {
1467 ASSERT (Value
!= NULL
);
1468 LengthStr
= StrLen (Value
);
1469 Status
= EFI_SUCCESS
;
1472 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1473 // Add string tail char L'\0' into Length
1475 Length
= StorageWidth
+ sizeof (CHAR16
);
1476 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1477 Status
= EFI_BUFFER_TOO_SMALL
;
1479 StringPtr
= (CHAR16
*) Dst
;
1480 ZeroMem (TemStr
, sizeof (TemStr
));
1481 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1482 StrnCpy (TemStr
, Value
+ Index
, 4);
1483 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1486 // Add tailing L'\0' character
1488 StringPtr
[Index
/4] = L
'\0';
1491 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1492 Status
= EFI_BUFFER_TOO_SMALL
;
1494 ZeroMem (TemStr
, sizeof (TemStr
));
1495 for (Index
= 0; Index
< LengthStr
; Index
++) {
1496 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1497 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1498 if ((Index
& 1) == 0) {
1499 Dst
[Index
/2] = DigitUint8
;
1501 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1511 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1512 // <ConfigHdr> + "&" + <VariableName>
1514 if (IsBufferStorage
) {
1515 Length
= StrLen (Storage
->ConfigHdr
);
1516 Length
+= StrLen (Question
->BlockName
);
1518 Length
= StrLen (Storage
->ConfigHdr
);
1519 Length
+= StrLen (Question
->VariableName
) + 1;
1521 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1522 ASSERT (ConfigRequest
!= NULL
);
1524 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1525 if (IsBufferStorage
) {
1526 StrCat (ConfigRequest
, Question
->BlockName
);
1528 StrCat (ConfigRequest
, L
"&");
1529 StrCat (ConfigRequest
, Question
->VariableName
);
1533 // Request current settings from Configuration Driver
1535 Status
= mHiiConfigRouting
->ExtractConfig (
1541 FreePool (ConfigRequest
);
1542 if (EFI_ERROR (Status
)) {
1547 // Skip <ConfigRequest>
1549 if (IsBufferStorage
) {
1550 Value
= StrStr (Result
, L
"&VALUE");
1551 if (Value
== NULL
) {
1553 return EFI_NOT_FOUND
;
1560 Value
= Result
+ Length
;
1562 if (*Value
!= '=') {
1564 return EFI_NOT_FOUND
;
1567 // Skip '=', point to value
1572 // Suppress <AltResp> if any
1575 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1580 LengthStr
= StrLen (Value
);
1581 Status
= EFI_SUCCESS
;
1582 if (!IsBufferStorage
&& IsString
) {
1584 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1585 // Add string tail char L'\0' into Length
1587 Length
= StorageWidth
+ sizeof (CHAR16
);
1588 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1589 Status
= EFI_BUFFER_TOO_SMALL
;
1591 StringPtr
= (CHAR16
*) Dst
;
1592 ZeroMem (TemStr
, sizeof (TemStr
));
1593 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1594 StrnCpy (TemStr
, Value
+ Index
, 4);
1595 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1598 // Add tailing L'\0' character
1600 StringPtr
[Index
/4] = L
'\0';
1603 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1604 Status
= EFI_BUFFER_TOO_SMALL
;
1606 ZeroMem (TemStr
, sizeof (TemStr
));
1607 for (Index
= 0; Index
< LengthStr
; Index
++) {
1608 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1609 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1610 if ((Index
& 1) == 0) {
1611 Dst
[Index
/2] = DigitUint8
;
1613 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1619 if (EFI_ERROR (Status
)) {
1625 // Synchronize Edit Buffer
1627 if (IsBufferStorage
) {
1628 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1630 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1633 if (Result
!= NULL
) {
1643 Save Question Value to edit copy(cached) or Storage(uncached).
1645 @param FormSet FormSet data structure.
1646 @param Form Form data structure.
1647 @param Question Pointer to the Question.
1648 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1650 @retval EFI_SUCCESS The function completed successfully.
1655 IN FORM_BROWSER_FORMSET
*FormSet
,
1656 IN FORM_BROWSER_FORM
*Form
,
1657 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1658 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1668 BROWSER_STORAGE
*Storage
;
1669 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1674 BOOLEAN IsBufferStorage
;
1680 NAME_VALUE_NODE
*Node
;
1682 Status
= EFI_SUCCESS
;
1685 if (SetValueTo
>= GetSetValueWithMax
) {
1686 return EFI_INVALID_PARAMETER
;
1690 // If Question value is provided by an Expression, then it is read only
1692 if (Question
->ValueExpression
!= NULL
) {
1697 // Before set question value, evaluate its write expression.
1699 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1700 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1701 if (EFI_ERROR (Status
)) {
1707 // Question value is provided by RTC
1709 Storage
= Question
->Storage
;
1710 QuestionValue
= &Question
->HiiValue
.Value
;
1711 if (Storage
== NULL
) {
1713 // It's a Question without storage, or RTC date/time
1715 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1717 // Date and time define the same Flags bit
1719 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1720 case QF_DATE_STORAGE_TIME
:
1721 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1724 case QF_DATE_STORAGE_WAKEUP
:
1725 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1728 case QF_DATE_STORAGE_NORMAL
:
1731 // For date/time without storage
1736 if (EFI_ERROR (Status
)) {
1740 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1741 EfiTime
.Year
= QuestionValue
->date
.Year
;
1742 EfiTime
.Month
= QuestionValue
->date
.Month
;
1743 EfiTime
.Day
= QuestionValue
->date
.Day
;
1745 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1746 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1747 EfiTime
.Second
= QuestionValue
->time
.Second
;
1750 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1751 Status
= gRT
->SetTime (&EfiTime
);
1753 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1761 // Question value is provided by EFI variable
1763 StorageWidth
= Question
->StorageWidth
;
1764 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1765 if (Question
->BufferValue
!= NULL
) {
1766 Src
= Question
->BufferValue
;
1768 Src
= (UINT8
*) QuestionValue
;
1771 Status
= gRT
->SetVariable (
1772 Question
->VariableName
,
1774 Storage
->Attributes
,
1782 // Question Value is provided by Buffer Storage or NameValue Storage
1784 if (Question
->BufferValue
!= NULL
) {
1785 Src
= Question
->BufferValue
;
1787 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1790 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1791 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1792 IsBufferStorage
= TRUE
;
1794 IsBufferStorage
= FALSE
;
1796 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1798 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1799 if (IsBufferStorage
) {
1800 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1802 // Copy to storage edit buffer
1804 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1805 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1807 // Copy to storage edit buffer
1809 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1814 // Allocate enough string buffer.
1817 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1818 Value
= AllocateZeroPool (BufferLen
);
1819 ASSERT (Value
!= NULL
);
1821 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1823 TemName
= (CHAR16
*) Src
;
1825 for (; *TemName
!= L
'\0'; TemName
++) {
1826 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1829 BufferLen
= StorageWidth
* 2 + 1;
1830 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1831 ASSERT (Value
!= NULL
);
1833 // Convert Buffer to Hex String
1835 TemBuffer
= Src
+ StorageWidth
- 1;
1837 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1838 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1842 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1844 if (EFI_ERROR (Status
)) {
1848 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1850 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1851 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1853 if (IsBufferStorage
) {
1854 Length
= StrLen (Question
->BlockName
) + 7;
1856 Length
= StrLen (Question
->VariableName
) + 2;
1858 if (!IsBufferStorage
&& IsString
) {
1859 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1861 Length
+= (StorageWidth
* 2);
1863 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1864 ASSERT (ConfigResp
!= NULL
);
1866 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1867 if (IsBufferStorage
) {
1868 StrCat (ConfigResp
, Question
->BlockName
);
1869 StrCat (ConfigResp
, L
"&VALUE=");
1871 StrCat (ConfigResp
, L
"&");
1872 StrCat (ConfigResp
, Question
->VariableName
);
1873 StrCat (ConfigResp
, L
"=");
1876 Value
= ConfigResp
+ StrLen (ConfigResp
);
1878 if (!IsBufferStorage
&& IsString
) {
1880 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1882 TemName
= (CHAR16
*) Src
;
1884 for (; *TemName
!= L
'\0'; TemName
++) {
1885 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1889 // Convert Buffer to Hex String
1891 TemBuffer
= Src
+ StorageWidth
- 1;
1893 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1894 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1899 // Convert to lower char.
1901 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1902 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1903 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1908 // Submit Question Value to Configuration Driver
1910 Status
= mHiiConfigRouting
->RouteConfig (
1915 if (EFI_ERROR (Status
)) {
1916 FreePool (ConfigResp
);
1919 FreePool (ConfigResp
);
1922 // Sync storage, from editbuffer to buffer.
1924 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1932 Perform nosubmitif check for a Form.
1934 @param FormSet FormSet data structure.
1935 @param Form Form data structure.
1936 @param Question The Question to be validated.
1937 @param Type Validation type: NoSubmit
1939 @retval EFI_SUCCESS Form validation pass.
1940 @retval other Form validation failed.
1945 IN FORM_BROWSER_FORMSET
*FormSet
,
1946 IN FORM_BROWSER_FORM
*Form
,
1947 IN FORM_BROWSER_STATEMENT
*Question
,
1953 LIST_ENTRY
*ListHead
;
1954 FORM_EXPRESSION
*Expression
;
1955 UINT32 BrowserStatus
;
1958 BrowserStatus
= BROWSER_SUCCESS
;
1962 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
1963 ListHead
= &Question
->InconsistentListHead
;
1966 case EFI_HII_EXPRESSION_WARNING_IF
:
1967 ListHead
= &Question
->WarningListHead
;
1970 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
1971 ListHead
= &Question
->NoSubmitListHead
;
1976 return EFI_UNSUPPORTED
;
1979 Link
= GetFirstNode (ListHead
);
1980 while (!IsNull (ListHead
, Link
)) {
1981 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1984 // Evaluate the expression
1986 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1987 if (EFI_ERROR (Status
)) {
1991 if (IsTrue (&Expression
->Result
)) {
1993 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
1994 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
1997 case EFI_HII_EXPRESSION_WARNING_IF
:
1998 BrowserStatus
= BROWSER_WARNING_IF
;
2001 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2002 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2004 // This code only used to compatible with old display engine,
2005 // New display engine will not use this field.
2007 if (Expression
->Error
!= 0) {
2008 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2017 PopupErrorMessage(BrowserStatus
, Expression
->OpCode
, ErrorStr
);
2019 if (ErrorStr
!= NULL
) {
2020 FreePool (ErrorStr
);
2023 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2026 return EFI_NOT_READY
;
2030 Link
= GetNextNode (ListHead
, Link
);
2037 Perform question check.
2039 If one question has more than one check, process form high priority to low.
2040 Only one error info will be popup.
2042 @param FormSet FormSet data structure.
2043 @param Form Form data structure.
2044 @param Question The Question to be validated.
2046 @retval EFI_SUCCESS Form validation pass.
2047 @retval other Form validation failed.
2051 ValueChangedValidation (
2052 IN FORM_BROWSER_FORMSET
*FormSet
,
2053 IN FORM_BROWSER_FORM
*Form
,
2054 IN FORM_BROWSER_STATEMENT
*Question
2059 Status
= EFI_SUCCESS
;
2062 // Do the inconsistentif check.
2064 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2065 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2066 if (EFI_ERROR (Status
)) {
2072 // Do the warningif check.
2074 if (!IsListEmpty (&Question
->WarningListHead
)) {
2075 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2082 Perform NoSubmit check for each Form in FormSet.
2084 @param FormSet FormSet data structure.
2085 @param CurrentForm Current input form data structure.
2087 @retval EFI_SUCCESS Form validation pass.
2088 @retval other Form validation failed.
2093 IN FORM_BROWSER_FORMSET
*FormSet
,
2094 IN FORM_BROWSER_FORM
*CurrentForm
2099 FORM_BROWSER_STATEMENT
*Question
;
2100 FORM_BROWSER_FORM
*Form
;
2101 LIST_ENTRY
*LinkForm
;
2103 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2104 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2105 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2106 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2108 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2112 Link
= GetFirstNode (&Form
->StatementListHead
);
2113 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2114 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2116 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2117 if (EFI_ERROR (Status
)) {
2121 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2129 Fill storage's edit copy with settings requested from Configuration Driver.
2131 @param FormSet FormSet data structure.
2132 @param Storage The storage which need to sync.
2133 @param ConfigRequest The config request string which used to sync storage.
2134 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2135 editbuffer to buffer
2136 if TRUE, copy the editbuffer to the buffer.
2137 if FALSE, copy the buffer to the editbuffer.
2139 @retval EFI_SUCCESS The function completed successfully.
2143 SynchronizeStorage (
2144 IN FORM_BROWSER_FORMSET
*FormSet
,
2145 OUT BROWSER_STORAGE
*Storage
,
2146 IN CHAR16
*ConfigRequest
,
2147 IN BOOLEAN SyncOrRestore
2151 EFI_STRING Progress
;
2155 NAME_VALUE_NODE
*Node
;
2159 Status
= EFI_SUCCESS
;
2162 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2163 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2164 BufferSize
= Storage
->Size
;
2166 if (SyncOrRestore
) {
2167 Src
= Storage
->EditBuffer
;
2168 Dst
= Storage
->Buffer
;
2170 Src
= Storage
->Buffer
;
2171 Dst
= Storage
->EditBuffer
;
2174 if (ConfigRequest
!= NULL
) {
2175 Status
= mHiiConfigRouting
->BlockToConfig(
2183 if (EFI_ERROR (Status
)) {
2187 Status
= mHiiConfigRouting
->ConfigToBlock (
2194 if (Result
!= NULL
) {
2198 CopyMem (Dst
, Src
, BufferSize
);
2200 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2201 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2202 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2203 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2205 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2206 (ConfigRequest
== NULL
)) {
2207 if (SyncOrRestore
) {
2208 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2210 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2214 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2222 When discard the question value, call the callback function with Changed type
2223 to inform the hii driver.
2225 @param FormSet FormSet data structure.
2226 @param Form Form data structure.
2230 SendDiscardInfoToDriver (
2231 IN FORM_BROWSER_FORMSET
*FormSet
,
2232 IN FORM_BROWSER_FORM
*Form
2236 FORM_BROWSER_STATEMENT
*Question
;
2237 EFI_IFR_TYPE_VALUE
*TypeValue
;
2238 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2240 if (FormSet
->ConfigAccess
== NULL
) {
2244 Link
= GetFirstNode (&Form
->StatementListHead
);
2245 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2246 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2247 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2249 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2253 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2257 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2261 if (!Question
->ValueChanged
) {
2266 // Restore the question value before call the CHANGED callback type.
2268 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2270 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2271 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2273 TypeValue
= &Question
->HiiValue
.Value
;
2276 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2277 FormSet
->ConfigAccess
->Callback (
2278 FormSet
->ConfigAccess
,
2279 EFI_BROWSER_ACTION_CHANGED
,
2280 Question
->QuestionId
,
2281 Question
->HiiValue
.Type
,
2289 Validate the FormSet. If the formset is not validate, remove it from the list.
2291 @param FormSet The input FormSet which need to validate.
2293 @retval TRUE The handle is validate.
2294 @retval FALSE The handle is invalidate.
2299 FORM_BROWSER_FORMSET
*FormSet
2302 EFI_HII_HANDLE
*HiiHandles
;
2306 ASSERT (FormSet
!= NULL
);
2309 // Get all the Hii handles
2311 HiiHandles
= HiiGetHiiHandles (NULL
);
2312 ASSERT (HiiHandles
!= NULL
);
2315 // Search for formset of each class type
2317 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2318 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2325 CleanBrowserStorage(FormSet
);
2326 RemoveEntryList (&FormSet
->Link
);
2327 DestroyFormSet (FormSet
);
2330 FreePool (HiiHandles
);
2335 Check whether need to enable the reset flag in form level.
2336 Also clean all ValueChanged flag in question.
2338 @param SetFlag Whether need to set the Reset Flag.
2339 @param Form Form data structure.
2345 IN FORM_BROWSER_FORM
*Form
2349 FORM_BROWSER_STATEMENT
*Question
;
2353 Link
= GetFirstNode (&Form
->StatementListHead
);
2354 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2355 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2357 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2358 gResetRequired
= TRUE
;
2361 if (Question
->ValueChanged
) {
2362 Question
->ValueChanged
= FALSE
;
2365 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2370 Check whether need to enable the reset flag.
2371 Also clean ValueChanged flag for all statements.
2373 Form level or formset level, only one.
2375 @param SetFlag Whether need to set the Reset Flag.
2376 @param FormSet FormSet data structure.
2377 @param Form Form data structure.
2381 ValueChangeResetFlagUpdate (
2383 IN FORM_BROWSER_FORMSET
*FormSet
,
2384 IN FORM_BROWSER_FORM
*Form
2387 FORM_BROWSER_FORM
*CurrentForm
;
2391 // Form != NULL means only check form level.
2394 UpdateFlagForForm(SetFlag
, Form
);
2398 Link
= GetFirstNode (&FormSet
->FormListHead
);
2399 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2400 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2401 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2403 UpdateFlagForForm(SetFlag
, CurrentForm
);
2408 Discard data based on the input setting scope (Form, FormSet or System).
2410 @param FormSet FormSet data structure.
2411 @param Form Form data structure.
2412 @param SettingScope Setting Scope for Discard action.
2414 @retval EFI_SUCCESS The function completed successfully.
2415 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2420 IN FORM_BROWSER_FORMSET
*FormSet
,
2421 IN FORM_BROWSER_FORM
*Form
,
2422 IN BROWSER_SETTING_SCOPE SettingScope
2426 FORMSET_STORAGE
*Storage
;
2427 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2428 FORM_BROWSER_FORMSET
*LocalFormSet
;
2429 FORM_BROWSER_FORMSET
*OldFormSet
;
2432 // Check the supported setting level.
2434 if (SettingScope
>= MaxLevel
) {
2435 return EFI_UNSUPPORTED
;
2438 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2440 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2441 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2442 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2443 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2445 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2450 // Skip if there is no RequestElement
2452 if (ConfigInfo
->ElementCount
== 0) {
2457 // Prepare <ConfigResp>
2459 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2462 // Call callback with Changed type to inform the driver.
2464 SendDiscardInfoToDriver (FormSet
, Form
);
2467 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2468 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2471 // Discard Buffer storage or Name/Value storage
2473 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2474 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2475 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2476 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2478 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2483 // Skip if there is no RequestElement
2485 if (Storage
->ElementCount
== 0) {
2489 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2492 Link
= GetFirstNode (&FormSet
->FormListHead
);
2493 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2494 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2495 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2498 // Call callback with Changed type to inform the driver.
2500 SendDiscardInfoToDriver (FormSet
, Form
);
2503 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2504 } else if (SettingScope
== SystemLevel
) {
2506 // System Level Discard.
2508 OldFormSet
= mSystemLevelFormSet
;
2511 // Discard changed value for each FormSet in the maintain list.
2513 Link
= GetFirstNode (&gBrowserFormSetList
);
2514 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2515 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2516 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2517 if (!ValidateFormSet(LocalFormSet
)) {
2521 mSystemLevelFormSet
= LocalFormSet
;
2523 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2524 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2526 // Remove maintain backup list after discard except for the current using FormSet.
2528 CleanBrowserStorage(LocalFormSet
);
2529 RemoveEntryList (&LocalFormSet
->Link
);
2530 DestroyFormSet (LocalFormSet
);
2534 mSystemLevelFormSet
= OldFormSet
;
2541 Submit data based on the input Setting level (Form, FormSet or System).
2543 @param FormSet FormSet data structure.
2544 @param Form Form data structure.
2545 @param SettingScope Setting Scope for Submit action.
2547 @retval EFI_SUCCESS The function completed successfully.
2548 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2553 IN FORM_BROWSER_FORMSET
*FormSet
,
2554 IN FORM_BROWSER_FORM
*Form
,
2555 IN BROWSER_SETTING_SCOPE SettingScope
2560 EFI_STRING ConfigResp
;
2561 EFI_STRING Progress
;
2562 BROWSER_STORAGE
*Storage
;
2563 FORMSET_STORAGE
*FormSetStorage
;
2564 FORM_BROWSER_FORMSET
*LocalFormSet
;
2565 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2568 // Check the supported setting level.
2570 if (SettingScope
>= MaxLevel
) {
2571 return EFI_UNSUPPORTED
;
2575 // Validate the Form by NoSubmit check
2577 Status
= EFI_SUCCESS
;
2578 if (SettingScope
== FormLevel
) {
2579 Status
= NoSubmitCheck (FormSet
, Form
);
2580 } else if (SettingScope
== FormSetLevel
) {
2581 Status
= NoSubmitCheck (FormSet
, NULL
);
2583 if (EFI_ERROR (Status
)) {
2587 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2589 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2590 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2591 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2592 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2594 Storage
= ConfigInfo
->Storage
;
2595 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2600 // Skip if there is no RequestElement
2602 if (ConfigInfo
->ElementCount
== 0) {
2607 // 1. Prepare <ConfigResp>
2609 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2610 if (EFI_ERROR (Status
)) {
2615 // 2. Set value to hii config routine protocol.
2617 Status
= mHiiConfigRouting
->RouteConfig (
2622 if (EFI_ERROR (Status
)) {
2623 FreePool (ConfigResp
);
2627 FreePool (ConfigResp
);
2629 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2631 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2635 // 4. Update the NV flag.
2637 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2638 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2640 // Submit Buffer storage or Name/Value storage
2642 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2643 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2644 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2645 Storage
= FormSetStorage
->BrowserStorage
;
2646 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2648 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2653 // Skip if there is no RequestElement
2655 if (FormSetStorage
->ElementCount
== 0) {
2660 // 1. Prepare <ConfigResp>
2662 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2663 if (EFI_ERROR (Status
)) {
2668 // 2. Send <ConfigResp> to Routine config Protocol.
2670 Status
= mHiiConfigRouting
->RouteConfig (
2675 if (EFI_ERROR (Status
)) {
2676 FreePool (ConfigResp
);
2680 FreePool (ConfigResp
);
2682 // 3. Config success, update storage shadow Buffer
2684 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2688 // 4. Update the NV flag.
2690 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2691 } else if (SettingScope
== SystemLevel
) {
2693 // System Level Save.
2697 // Save changed value for each FormSet in the maintain list.
2699 Link
= GetFirstNode (&gBrowserFormSetList
);
2700 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2701 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2702 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2703 if (!ValidateFormSet(LocalFormSet
)) {
2706 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2707 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2709 // Remove maintain backup list after save except for the current using FormSet.
2711 CleanBrowserStorage(LocalFormSet
);
2712 RemoveEntryList (&LocalFormSet
->Link
);
2713 DestroyFormSet (LocalFormSet
);
2722 Get Question default value from AltCfg string.
2724 @param FormSet The form set.
2725 @param Question The question.
2726 @param DefaultId The default Id.
2728 @retval EFI_SUCCESS Question is reset to default value.
2732 GetDefaultValueFromAltCfg (
2733 IN FORM_BROWSER_FORMSET
*FormSet
,
2734 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2738 BOOLEAN IsBufferStorage
;
2741 BROWSER_STORAGE
*Storage
;
2742 CHAR16
*ConfigRequest
;
2755 Status
= EFI_NOT_FOUND
;
2758 ConfigRequest
= NULL
;
2762 Storage
= Question
->Storage
;
2764 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2769 // Question Value is provided by Buffer Storage or NameValue Storage
2771 if (Question
->BufferValue
!= NULL
) {
2773 // This Question is password or orderedlist
2775 Dst
= Question
->BufferValue
;
2778 // Other type of Questions
2780 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2783 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2784 IsBufferStorage
= TRUE
;
2786 IsBufferStorage
= FALSE
;
2788 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2791 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2792 // <ConfigHdr> + "&" + <VariableName>
2794 if (IsBufferStorage
) {
2795 Length
= StrLen (Storage
->ConfigHdr
);
2796 Length
+= StrLen (Question
->BlockName
);
2798 Length
= StrLen (Storage
->ConfigHdr
);
2799 Length
+= StrLen (Question
->VariableName
) + 1;
2801 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2802 ASSERT (ConfigRequest
!= NULL
);
2804 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2805 if (IsBufferStorage
) {
2806 StrCat (ConfigRequest
, Question
->BlockName
);
2808 StrCat (ConfigRequest
, L
"&");
2809 StrCat (ConfigRequest
, Question
->VariableName
);
2812 Status
= mHiiConfigRouting
->ExtractConfig (
2818 if (EFI_ERROR (Status
)) {
2823 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2824 // Get the default configuration string according to the default ID.
2826 Status
= mHiiConfigRouting
->GetAltConfig (
2832 &DefaultId
, // it can be NULL to get the current setting.
2837 // The required setting can't be found. So, it is not required to be validated and set.
2839 if (EFI_ERROR (Status
)) {
2843 if (ConfigResp
== NULL
) {
2844 Status
= EFI_NOT_FOUND
;
2849 // Skip <ConfigRequest>
2851 if (IsBufferStorage
) {
2852 Value
= StrStr (ConfigResp
, L
"&VALUE");
2853 ASSERT (Value
!= NULL
);
2859 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2860 ASSERT (Value
!= NULL
);
2862 Value
= Value
+ StrLen (Question
->VariableName
);
2864 if (*Value
!= '=') {
2865 Status
= EFI_NOT_FOUND
;
2869 // Skip '=', point to value
2874 // Suppress <AltResp> if any
2877 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2882 LengthStr
= StrLen (Value
);
2883 if (!IsBufferStorage
&& IsString
) {
2884 StringPtr
= (CHAR16
*) Dst
;
2885 ZeroMem (TemStr
, sizeof (TemStr
));
2886 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2887 StrnCpy (TemStr
, Value
+ Index
, 4);
2888 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2891 // Add tailing L'\0' character
2893 StringPtr
[Index
/4] = L
'\0';
2895 ZeroMem (TemStr
, sizeof (TemStr
));
2896 for (Index
= 0; Index
< LengthStr
; Index
++) {
2897 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2898 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2899 if ((Index
& 1) == 0) {
2900 Dst
[Index
/2] = DigitUint8
;
2902 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2908 if (ConfigRequest
!= NULL
){
2909 FreePool (ConfigRequest
);
2912 if (ConfigResp
!= NULL
) {
2913 FreePool (ConfigResp
);
2916 if (Result
!= NULL
) {
2924 Get default Id value used for browser.
2926 @param DefaultId The default id value used by hii.
2928 @retval Browser used default value.
2932 GetDefaultIdForCallBack (
2936 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2937 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2938 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2939 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2940 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2941 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2942 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2943 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2944 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2945 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2946 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2947 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2956 Return data element in an Array by its Index.
2958 @param Array The data array.
2959 @param Type Type of the data in this array.
2960 @param Index Zero based index for data in this array.
2962 @retval Value The data to be returned
2974 ASSERT (Array
!= NULL
);
2978 case EFI_IFR_TYPE_NUM_SIZE_8
:
2979 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
2982 case EFI_IFR_TYPE_NUM_SIZE_16
:
2983 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
2986 case EFI_IFR_TYPE_NUM_SIZE_32
:
2987 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
2990 case EFI_IFR_TYPE_NUM_SIZE_64
:
2991 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3003 Set value of a data element in an Array by its Index.
3005 @param Array The data array.
3006 @param Type Type of the data in this array.
3007 @param Index Zero based index for data in this array.
3008 @param Value The value to be set.
3020 ASSERT (Array
!= NULL
);
3023 case EFI_IFR_TYPE_NUM_SIZE_8
:
3024 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3027 case EFI_IFR_TYPE_NUM_SIZE_16
:
3028 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3031 case EFI_IFR_TYPE_NUM_SIZE_32
:
3032 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3035 case EFI_IFR_TYPE_NUM_SIZE_64
:
3036 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3045 Search an Option of a Question by its value.
3047 @param Question The Question
3048 @param OptionValue Value for Option to be searched.
3050 @retval Pointer Pointer to the found Option.
3051 @retval NULL Option not found.
3056 IN FORM_BROWSER_STATEMENT
*Question
,
3057 IN EFI_HII_VALUE
*OptionValue
3061 QUESTION_OPTION
*Option
;
3064 Link
= GetFirstNode (&Question
->OptionListHead
);
3065 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3066 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3068 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3070 // Check the suppressif condition, only a valid option can be return.
3072 if ((Option
->SuppressExpression
== NULL
) ||
3073 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3078 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3086 Reset Question to its default value.
3088 @param FormSet The form set.
3089 @param Form The form.
3090 @param Question The question.
3091 @param DefaultId The Class of the default.
3093 @retval EFI_SUCCESS Question is reset to default value.
3097 GetQuestionDefault (
3098 IN FORM_BROWSER_FORMSET
*FormSet
,
3099 IN FORM_BROWSER_FORM
*Form
,
3100 IN FORM_BROWSER_STATEMENT
*Question
,
3106 QUESTION_DEFAULT
*Default
;
3107 QUESTION_OPTION
*Option
;
3108 EFI_HII_VALUE
*HiiValue
;
3110 EFI_STRING StrValue
;
3111 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3112 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3116 Status
= EFI_NOT_FOUND
;
3120 // Statement don't have storage, skip them
3122 if (Question
->QuestionId
== 0) {
3127 // There are Five ways to specify default value for a Question:
3128 // 1, use call back function (highest priority)
3129 // 2, use ExtractConfig function
3130 // 3, use nested EFI_IFR_DEFAULT
3131 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3132 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3134 HiiValue
= &Question
->HiiValue
;
3137 // Get Question defaut value from call back function.
3139 ConfigAccess
= FormSet
->ConfigAccess
;
3140 Action
= GetDefaultIdForCallBack (DefaultId
);
3141 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3142 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3143 Status
= ConfigAccess
->Callback (
3146 Question
->QuestionId
,
3151 if (!EFI_ERROR (Status
)) {
3152 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3153 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3154 ASSERT (NewString
!= NULL
);
3156 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3157 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3158 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3160 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3163 FreePool (NewString
);
3170 // Get default value from altcfg string.
3172 if (ConfigAccess
!= NULL
) {
3173 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3174 if (!EFI_ERROR (Status
)) {
3180 // EFI_IFR_DEFAULT has highest priority
3182 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3183 Link
= GetFirstNode (&Question
->DefaultListHead
);
3184 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3185 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3187 if (Default
->DefaultId
== DefaultId
) {
3188 if (Default
->ValueExpression
!= NULL
) {
3190 // Default is provided by an Expression, evaluate it
3192 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3193 if (EFI_ERROR (Status
)) {
3197 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3198 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3199 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3200 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3201 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3203 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3204 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3206 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3208 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3209 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3212 // Default value is embedded in EFI_IFR_DEFAULT
3214 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3217 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3218 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3219 if (StrValue
== NULL
) {
3220 return EFI_NOT_FOUND
;
3222 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3223 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3225 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3232 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3237 // EFI_ONE_OF_OPTION
3239 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3240 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3242 // OneOfOption could only provide Standard and Manufacturing default
3244 Link
= GetFirstNode (&Question
->OptionListHead
);
3245 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3246 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3247 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3249 if ((Option
->SuppressExpression
!= NULL
) &&
3250 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3254 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3255 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3257 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3266 // EFI_IFR_CHECKBOX - lowest priority
3268 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3269 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3271 // Checkbox could only provide Standard and Manufacturing default
3273 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3274 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3276 HiiValue
->Value
.b
= TRUE
;
3278 HiiValue
->Value
.b
= FALSE
;
3286 // For Questions without default
3288 Status
= EFI_NOT_FOUND
;
3289 switch (Question
->Operand
) {
3290 case EFI_IFR_NUMERIC_OP
:
3292 // Take minimum value as numeric default value
3294 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3295 HiiValue
->Value
.u64
= Question
->Minimum
;
3296 Status
= EFI_SUCCESS
;
3300 case EFI_IFR_ONE_OF_OP
:
3302 // Take first oneof option as oneof's default value
3304 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3305 Link
= GetFirstNode (&Question
->OptionListHead
);
3306 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3307 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3308 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3310 if ((Option
->SuppressExpression
!= NULL
) &&
3311 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3315 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3316 Status
= EFI_SUCCESS
;
3322 case EFI_IFR_ORDERED_LIST_OP
:
3324 // Take option sequence in IFR as ordered list's default value
3327 Link
= GetFirstNode (&Question
->OptionListHead
);
3328 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3329 Status
= EFI_SUCCESS
;
3330 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3331 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3333 if ((Option
->SuppressExpression
!= NULL
) &&
3334 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3338 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3341 if (Index
>= Question
->MaxContainers
) {
3356 Reset Questions to their initial value or default value in a Form, Formset or System.
3358 GetDefaultValueScope parameter decides which questions will reset
3359 to its default value.
3361 @param FormSet FormSet data structure.
3362 @param Form Form data structure.
3363 @param DefaultId The Class of the default.
3364 @param SettingScope Setting Scope for Default action.
3365 @param GetDefaultValueScope Get default value scope.
3366 @param Storage Get default value only for this storage.
3367 @param RetrieveValueFirst Whether call the retrieve call back to
3368 get the initial value before get default
3371 @retval EFI_SUCCESS The function completed successfully.
3372 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3377 IN FORM_BROWSER_FORMSET
*FormSet
,
3378 IN FORM_BROWSER_FORM
*Form
,
3379 IN UINT16 DefaultId
,
3380 IN BROWSER_SETTING_SCOPE SettingScope
,
3381 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3382 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3383 IN BOOLEAN RetrieveValueFirst
3387 LIST_ENTRY
*FormLink
;
3389 FORM_BROWSER_STATEMENT
*Question
;
3390 FORM_BROWSER_FORMSET
*LocalFormSet
;
3391 FORM_BROWSER_FORMSET
*OldFormSet
;
3393 Status
= EFI_SUCCESS
;
3396 // Check the supported setting level.
3398 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3399 return EFI_UNSUPPORTED
;
3402 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3403 return EFI_UNSUPPORTED
;
3406 if (SettingScope
== FormLevel
) {
3408 // Extract Form default
3410 Link
= GetFirstNode (&Form
->StatementListHead
);
3411 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3412 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3413 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3416 // If get default value only for this storage, check the storage first.
3418 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3423 // If get default value only for no storage question, just skip the question which has storage.
3425 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3430 // If Question is disabled, don't reset it to default
3432 if (Question
->Expression
!= NULL
) {
3433 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3438 if (RetrieveValueFirst
) {
3440 // Call the Retrieve call back to get the initial question value.
3442 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
3446 // If not request to get the initial value or get initial value fail, then get default value.
3448 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3449 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3450 if (EFI_ERROR (Status
)) {
3456 // Synchronize Buffer storage's Edit buffer
3458 if ((Question
->Storage
!= NULL
) &&
3459 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3460 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3463 } else if (SettingScope
== FormSetLevel
) {
3464 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3465 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3466 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3467 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3468 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3470 } else if (SettingScope
== SystemLevel
) {
3472 // Preload all Hii formset.
3474 LoadAllHiiFormset();
3476 OldFormSet
= mSystemLevelFormSet
;
3479 // Set Default Value for each FormSet in the maintain list.
3481 Link
= GetFirstNode (&gBrowserFormSetList
);
3482 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3483 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3484 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3485 if (!ValidateFormSet(LocalFormSet
)) {
3489 mSystemLevelFormSet
= LocalFormSet
;
3491 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3494 mSystemLevelFormSet
= OldFormSet
;
3502 Validate whether this question's value has changed.
3504 @param FormSet FormSet data structure.
3505 @param Form Form data structure.
3506 @param Question Question to be initialized.
3507 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3509 @retval TRUE Question's value has changed.
3510 @retval FALSE Question's value has not changed
3514 IsQuestionValueChanged (
3515 IN FORM_BROWSER_FORMSET
*FormSet
,
3516 IN FORM_BROWSER_FORM
*Form
,
3517 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3518 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3521 EFI_HII_VALUE BackUpValue
;
3522 CHAR8
*BackUpBuffer
;
3524 BOOLEAN ValueChanged
;
3528 // For quetion without storage, always mark it as data not changed.
3530 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3534 BackUpBuffer
= NULL
;
3535 ValueChanged
= FALSE
;
3537 switch (Question
->Operand
) {
3538 case EFI_IFR_ORDERED_LIST_OP
:
3539 BufferWidth
= Question
->StorageWidth
;
3540 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3541 ASSERT (BackUpBuffer
!= NULL
);
3544 case EFI_IFR_STRING_OP
:
3545 case EFI_IFR_PASSWORD_OP
:
3546 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3547 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3548 ASSERT (BackUpBuffer
!= NULL
);
3555 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3557 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3558 ASSERT_EFI_ERROR(Status
);
3560 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3561 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3562 ValueChanged
= TRUE
;
3565 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3566 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3568 if (BackUpBuffer
!= NULL
) {
3569 FreePool (BackUpBuffer
);
3572 Question
->ValueChanged
= ValueChanged
;
3574 return ValueChanged
;
3578 Initialize Question's Edit copy from Storage.
3580 @param Selection Selection contains the information about
3581 the Selection, form and formset to be displayed.
3582 Selection action may be updated in retrieve callback.
3583 If Selection is NULL, only initialize Question value.
3584 @param FormSet FormSet data structure.
3585 @param Form Form data structure.
3587 @retval EFI_SUCCESS The function completed successfully.
3592 IN OUT UI_MENU_SELECTION
*Selection
,
3593 IN FORM_BROWSER_FORMSET
*FormSet
,
3594 IN FORM_BROWSER_FORM
*Form
3599 FORM_BROWSER_STATEMENT
*Question
;
3601 Link
= GetFirstNode (&Form
->StatementListHead
);
3602 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3603 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3606 // Initialize local copy of Value for each Question
3608 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3609 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3611 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3613 if (EFI_ERROR (Status
)) {
3617 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3618 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3621 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3628 Initialize Question's Edit copy from Storage for the whole Formset.
3630 @param Selection Selection contains the information about
3631 the Selection, form and formset to be displayed.
3632 Selection action may be updated in retrieve callback.
3633 If Selection is NULL, only initialize Question value.
3634 @param FormSet FormSet data structure.
3636 @retval EFI_SUCCESS The function completed successfully.
3641 IN OUT UI_MENU_SELECTION
*Selection
,
3642 IN FORM_BROWSER_FORMSET
*FormSet
3647 FORM_BROWSER_FORM
*Form
;
3649 Link
= GetFirstNode (&FormSet
->FormListHead
);
3650 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3651 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3654 // Initialize local copy of Value for each Form
3656 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3657 if (EFI_ERROR (Status
)) {
3661 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3665 // Finished question initialization.
3667 FormSet
->QuestionInited
= TRUE
;
3673 Remove the Request element from the Config Request.
3675 @param Storage Pointer to the browser storage.
3676 @param RequestElement The pointer to the Request element.
3681 IN OUT BROWSER_STORAGE
*Storage
,
3682 IN CHAR16
*RequestElement
3688 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3690 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3692 if (NewStr
== NULL
) {
3697 // Remove this element from this ConfigRequest.
3700 NewStr
+= StrLen (RequestElement
);
3701 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3703 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3707 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3709 @param Storage Pointer to the browser storage.
3710 @param ConfigRequest The pointer to the Request element.
3714 RemoveConfigRequest (
3715 BROWSER_STORAGE
*Storage
,
3716 CHAR16
*ConfigRequest
3719 CHAR16
*RequestElement
;
3720 CHAR16
*NextRequestElement
;
3724 // No request element in it, just return.
3726 if (ConfigRequest
== NULL
) {
3730 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3732 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3737 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3739 SearchKey
= L
"&OFFSET";
3743 // Find SearchKey storage
3745 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3746 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3747 ASSERT (RequestElement
!= NULL
);
3748 RequestElement
= StrStr (RequestElement
, SearchKey
);
3750 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3753 while (RequestElement
!= NULL
) {
3755 // +1 to avoid find header itself.
3757 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3760 // The last Request element in configRequest string.
3762 if (NextRequestElement
!= NULL
) {
3764 // Replace "&" with '\0'.
3766 *NextRequestElement
= L
'\0';
3769 RemoveElement (Storage
, RequestElement
);
3771 if (NextRequestElement
!= NULL
) {
3773 // Restore '&' with '\0' for later used.
3775 *NextRequestElement
= L
'&';
3778 RequestElement
= NextRequestElement
;
3782 // If no request element remain, just remove the ConfigRequest string.
3784 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3785 FreePool (Storage
->ConfigRequest
);
3786 Storage
->ConfigRequest
= NULL
;
3787 Storage
->SpareStrLen
= 0;
3792 Base on the current formset info, clean the ConfigRequest string in browser storage.
3794 @param FormSet Pointer of the FormSet
3798 CleanBrowserStorage (
3799 IN OUT FORM_BROWSER_FORMSET
*FormSet
3803 FORMSET_STORAGE
*Storage
;
3805 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3806 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3807 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3808 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3810 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3811 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3815 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
3816 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3817 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3818 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
3819 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
3820 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
3822 Storage
->BrowserStorage
->Initialized
= FALSE
;
3828 Check whether current element in the ConfigReqeust string.
3830 @param BrowserStorage Storage which includes ConfigReqeust.
3831 @param RequestElement New element need to check.
3833 @retval TRUE The Element is in the ConfigReqeust string.
3834 @retval FALSE The Element not in the configReqeust String.
3839 BROWSER_STORAGE
*BrowserStorage
,
3840 CHAR16
*RequestElement
3843 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3847 Append the Request element to the Config Request.
3849 @param ConfigRequest Current ConfigRequest info.
3850 @param SpareStrLen Current remain free buffer for config reqeust.
3851 @param RequestElement New Request element.
3855 AppendConfigRequest (
3856 IN OUT CHAR16
**ConfigRequest
,
3857 IN OUT UINTN
*SpareStrLen
,
3858 IN CHAR16
*RequestElement
3865 StrLength
= StrLen (RequestElement
);
3868 // Append <RequestElement> to <ConfigRequest>
3870 if (StrLength
> *SpareStrLen
) {
3872 // Old String buffer is not sufficient for RequestElement, allocate a new one
3874 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3875 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3876 ASSERT (NewStr
!= NULL
);
3878 if (*ConfigRequest
!= NULL
) {
3879 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3880 FreePool (*ConfigRequest
);
3882 *ConfigRequest
= NewStr
;
3883 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3886 StrCat (*ConfigRequest
, RequestElement
);
3887 *SpareStrLen
-= StrLength
;
3891 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3893 @param Storage Form set Storage.
3894 @param Request The input request string.
3895 @param RespString Whether the input is ConfigRequest or ConfigResp format.
3897 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3898 @retval FALSE All elements covered by current used elements.
3902 ConfigRequestAdjust (
3903 IN BROWSER_STORAGE
*Storage
,
3905 IN BOOLEAN RespString
3908 CHAR16
*RequestElement
;
3909 CHAR16
*NextRequestElement
;
3910 CHAR16
*NextElementBakup
;
3915 CHAR16
*ConfigRequest
;
3919 NextElementBakup
= NULL
;
3922 if (Request
!= NULL
) {
3923 ConfigRequest
= Request
;
3925 ConfigRequest
= Storage
->ConfigRequest
;
3928 if (Storage
->ConfigRequest
== NULL
) {
3929 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3933 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3935 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3940 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3942 SearchKey
= L
"&OFFSET";
3943 ValueKey
= L
"&VALUE";
3947 // Find SearchKey storage
3949 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3950 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3951 ASSERT (RequestElement
!= NULL
);
3952 RequestElement
= StrStr (RequestElement
, SearchKey
);
3954 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3957 while (RequestElement
!= NULL
) {
3960 // +1 to avoid find header itself.
3962 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3965 // The last Request element in configRequest string.
3967 if (NextRequestElement
!= NULL
) {
3968 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3969 NextElementBakup
= NextRequestElement
;
3970 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3971 ASSERT (NextRequestElement
!= NULL
);
3974 // Replace "&" with '\0'.
3976 *NextRequestElement
= L
'\0';
3978 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3979 NextElementBakup
= NextRequestElement
;
3980 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3981 ASSERT (NextRequestElement
!= NULL
);
3983 // Replace "&" with '\0'.
3985 *NextRequestElement
= L
'\0';
3989 if (!ElementValidation (Storage
, RequestElement
)) {
3991 // Add this element to the Storage->BrowserStorage->AllRequestElement.
3993 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
3997 if (NextRequestElement
!= NULL
) {
3999 // Restore '&' with '\0' for later used.
4001 *NextRequestElement
= L
'&';
4004 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4005 RequestElement
= NextElementBakup
;
4007 RequestElement
= NextRequestElement
;
4016 Base on ConfigRequest info to get default value for current formset.
4018 ConfigRequest info include the info about which questions in current formset need to
4019 get default value. This function only get these questions default value.
4021 @param FormSet FormSet data structure.
4022 @param Storage Storage need to update value.
4023 @param ConfigRequest The config request string.
4027 GetDefaultForFormset (
4028 IN FORM_BROWSER_FORMSET
*FormSet
,
4029 IN BROWSER_STORAGE
*Storage
,
4030 IN CHAR16
*ConfigRequest
4035 LIST_ENTRY BackUpList
;
4036 NAME_VALUE_NODE
*Node
;
4038 LIST_ENTRY
*NodeLink
;
4039 NAME_VALUE_NODE
*TmpNode
;
4041 EFI_STRING Progress
;
4045 InitializeListHead(&BackUpList
);
4048 // Back update the edit buffer.
4050 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4051 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4052 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4053 ASSERT (BackUpBuf
!= NULL
);
4054 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4055 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4056 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4057 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4058 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4061 // Only back Node belong to this formset.
4063 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4067 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4068 ASSERT (TmpNode
!= NULL
);
4069 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4070 ASSERT (TmpNode
->Name
!= NULL
);
4071 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4072 ASSERT (TmpNode
->EditValue
!= NULL
);
4074 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4079 // Get default value.
4081 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4084 // Update the question value based on the input ConfigRequest.
4086 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4087 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4088 ASSERT (BackUpBuf
!= NULL
);
4089 BufferSize
= Storage
->Size
;
4090 Status
= mHiiConfigRouting
->BlockToConfig(
4093 Storage
->EditBuffer
,
4098 ASSERT_EFI_ERROR (Status
);
4100 Status
= mHiiConfigRouting
->ConfigToBlock (
4107 ASSERT_EFI_ERROR (Status
);
4109 if (Result
!= NULL
) {
4113 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4114 FreePool (BackUpBuf
);
4115 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4117 // Update question value, only element in ConfigReqeust will be update.
4119 Link
= GetFirstNode (&BackUpList
);
4120 while (!IsNull (&BackUpList
, Link
)) {
4121 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4122 Link
= GetNextNode (&BackUpList
, Link
);
4124 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4128 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4129 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4130 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4131 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4133 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4137 FreePool (TmpNode
->EditValue
);
4138 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4140 RemoveEntryList (&Node
->Link
);
4141 FreePool (Node
->EditValue
);
4142 FreePool (Node
->Name
);
4148 // Restore the Name/Value node.
4150 Link
= GetFirstNode (&BackUpList
);
4151 while (!IsNull (&BackUpList
, Link
)) {
4152 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4153 Link
= GetNextNode (&BackUpList
, Link
);
4158 RemoveEntryList (&Node
->Link
);
4159 FreePool (Node
->EditValue
);
4160 FreePool (Node
->Name
);
4167 Fill storage's edit copy with settings requested from Configuration Driver.
4169 @param FormSet FormSet data structure.
4170 @param Storage Buffer Storage.
4175 IN FORM_BROWSER_FORMSET
*FormSet
,
4176 IN FORMSET_STORAGE
*Storage
4180 EFI_STRING Progress
;
4183 EFI_STRING ConfigRequest
;
4186 ConfigRequest
= NULL
;
4188 switch (Storage
->BrowserStorage
->Type
) {
4189 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4192 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4193 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4194 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4199 case EFI_HII_VARSTORE_BUFFER
:
4200 case EFI_HII_VARSTORE_NAME_VALUE
:
4202 // Skip if there is no RequestElement.
4204 if (Storage
->ElementCount
== 0) {
4209 // Just update the ConfigRequest, if storage already initialized.
4211 if (Storage
->BrowserStorage
->Initialized
) {
4212 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4216 Storage
->BrowserStorage
->Initialized
= TRUE
;
4223 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4225 // Create the config request string to get all fields for this storage.
4226 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4227 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4229 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4230 ConfigRequest
= AllocateZeroPool (StrLen
);
4231 ASSERT (ConfigRequest
!= NULL
);
4235 L
"%s&OFFSET=0&WIDTH=%04x",
4236 Storage
->BrowserStorage
->ConfigHdr
,
4237 Storage
->BrowserStorage
->Size
);
4239 ConfigRequest
= Storage
->ConfigRequest
;
4243 // Request current settings from Configuration Driver
4245 Status
= mHiiConfigRouting
->ExtractConfig (
4253 // If get value fail, extract default from IFR binary
4255 if (EFI_ERROR (Status
)) {
4256 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4259 // Convert Result from <ConfigAltResp> to <ConfigResp>
4261 StrPtr
= StrStr (Result
, L
"&GUID=");
4262 if (StrPtr
!= NULL
) {
4266 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4270 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4273 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4275 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4277 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4278 if (ConfigRequest
!= NULL
) {
4279 FreePool (ConfigRequest
);
4285 Get Value changed status from old question.
4287 @param NewFormSet FormSet data structure.
4288 @param OldQuestion Old question which has value changed.
4292 SyncStatusForQuestion (
4293 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4294 IN FORM_BROWSER_STATEMENT
*OldQuestion
4298 LIST_ENTRY
*QuestionLink
;
4299 FORM_BROWSER_FORM
*Form
;
4300 FORM_BROWSER_STATEMENT
*Question
;
4303 // For each form in one formset.
4305 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4306 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4307 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4308 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
4311 // for each question in one form.
4313 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4314 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4315 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4316 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4318 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
4319 Question
->ValueChanged
= TRUE
;
4327 Get Value changed status from old formset.
4329 @param NewFormSet FormSet data structure.
4330 @param OldFormSet FormSet data structure.
4334 SyncStatusForFormSet (
4335 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4336 IN FORM_BROWSER_FORMSET
*OldFormSet
4340 LIST_ENTRY
*QuestionLink
;
4341 FORM_BROWSER_FORM
*Form
;
4342 FORM_BROWSER_STATEMENT
*Question
;
4345 // For each form in one formset.
4347 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
4348 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
4349 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4350 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
4353 // for each question in one form.
4355 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4356 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4357 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4358 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4360 if (!Question
->ValueChanged
) {
4365 // Find the same question in new formset and update the value changed flag.
4367 SyncStatusForQuestion (NewFormSet
, Question
);
4373 Get current setting of Questions.
4375 @param FormSet FormSet data structure.
4379 InitializeCurrentSetting (
4380 IN OUT FORM_BROWSER_FORMSET
*FormSet
4384 FORMSET_STORAGE
*Storage
;
4385 FORM_BROWSER_FORMSET
*OldFormSet
;
4388 // Try to find pre FormSet in the maintain backup list.
4389 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4391 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4392 if (OldFormSet
!= NULL
) {
4393 SyncStatusForFormSet (FormSet
, OldFormSet
);
4394 RemoveEntryList (&OldFormSet
->Link
);
4395 DestroyFormSet (OldFormSet
);
4397 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4400 // Extract default from IFR binary for no storage questions.
4402 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4405 // Request current settings from Configuration Driver
4407 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4408 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4409 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4411 LoadStorage (FormSet
, Storage
);
4413 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4419 Fetch the Ifr binary data of a FormSet.
4421 @param Handle PackageList Handle
4422 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4423 specified (NULL or zero GUID), take the first
4424 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4425 found in package list.
4426 On output, GUID of the formset found(if not NULL).
4427 @param BinaryLength The length of the FormSet IFR binary.
4428 @param BinaryData The buffer designed to receive the FormSet.
4430 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4431 BufferLength was updated.
4432 @retval EFI_INVALID_PARAMETER The handle is unknown.
4433 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4434 be found with the requested FormId.
4439 IN EFI_HII_HANDLE Handle
,
4440 IN OUT EFI_GUID
*FormSetGuid
,
4441 OUT UINTN
*BinaryLength
,
4442 OUT UINT8
**BinaryData
4446 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4452 UINT32 PackageListLength
;
4453 EFI_HII_PACKAGE_HEADER PackageHeader
;
4455 UINT8 NumberOfClassGuid
;
4456 BOOLEAN ClassGuidMatch
;
4457 EFI_GUID
*ClassGuid
;
4458 EFI_GUID
*ComparingGuid
;
4462 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4465 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4467 if (FormSetGuid
== NULL
) {
4468 ComparingGuid
= &gZeroGuid
;
4470 ComparingGuid
= FormSetGuid
;
4474 // Get HII PackageList
4477 HiiPackageList
= NULL
;
4478 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4479 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4480 HiiPackageList
= AllocatePool (BufferSize
);
4481 ASSERT (HiiPackageList
!= NULL
);
4483 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4485 if (EFI_ERROR (Status
)) {
4488 ASSERT (HiiPackageList
!= NULL
);
4491 // Get Form package from this HII package List
4493 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4495 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4497 ClassGuidMatch
= FALSE
;
4498 while (Offset
< PackageListLength
) {
4499 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4500 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4502 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4504 // Search FormSet in this Form Package
4506 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4507 while (Offset2
< PackageHeader
.Length
) {
4508 OpCodeData
= Package
+ Offset2
;
4510 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4512 // Try to compare against formset GUID
4514 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4515 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4519 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4521 // Try to compare against formset class GUID
4523 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4524 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4525 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4526 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4527 ClassGuidMatch
= TRUE
;
4531 if (ClassGuidMatch
) {
4534 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4535 ClassGuidMatch
= TRUE
;
4540 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4543 if (Offset2
< PackageHeader
.Length
) {
4545 // Target formset found
4551 Offset
+= PackageHeader
.Length
;
4554 if (Offset
>= PackageListLength
) {
4556 // Form package not found in this Package List
4558 FreePool (HiiPackageList
);
4559 return EFI_NOT_FOUND
;
4562 if (FormSetGuid
!= NULL
) {
4564 // Return the FormSet GUID
4566 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4570 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4571 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4572 // of the Form Package.
4574 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4575 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4577 FreePool (HiiPackageList
);
4579 if (*BinaryData
== NULL
) {
4580 return EFI_OUT_OF_RESOURCES
;
4588 Initialize the internal data structure of a FormSet.
4590 @param Handle PackageList Handle
4591 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4592 specified (NULL or zero GUID), take the first
4593 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4594 found in package list.
4595 On output, GUID of the formset found(if not NULL).
4596 @param FormSet FormSet data structure.
4598 @retval EFI_SUCCESS The function completed successfully.
4599 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4604 IN EFI_HII_HANDLE Handle
,
4605 IN OUT EFI_GUID
*FormSetGuid
,
4606 OUT FORM_BROWSER_FORMSET
*FormSet
4610 EFI_HANDLE DriverHandle
;
4612 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4613 if (EFI_ERROR (Status
)) {
4617 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4618 FormSet
->HiiHandle
= Handle
;
4619 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4620 FormSet
->QuestionInited
= FALSE
;
4623 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4625 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4626 if (EFI_ERROR (Status
)) {
4629 FormSet
->DriverHandle
= DriverHandle
;
4630 Status
= gBS
->HandleProtocol (
4632 &gEfiHiiConfigAccessProtocolGuid
,
4633 (VOID
**) &FormSet
->ConfigAccess
4635 if (EFI_ERROR (Status
)) {
4637 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4638 // list, then there will be no configuration action required
4640 FormSet
->ConfigAccess
= NULL
;
4644 // Parse the IFR binary OpCodes
4646 Status
= ParseOpCodes (FormSet
);
4653 Save globals used by previous call to SendForm(). SendForm() may be called from
4654 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4655 So, save globals of previous call to SendForm() and restore them upon exit.
4659 SaveBrowserContext (
4663 BROWSER_CONTEXT
*Context
;
4664 FORM_ENTRY_INFO
*MenuList
;
4666 gBrowserContextCount
++;
4667 if (gBrowserContextCount
== 1) {
4669 // This is not reentry of SendForm(), no context to save
4674 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4675 ASSERT (Context
!= NULL
);
4677 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4680 // Save FormBrowser context
4682 Context
->Selection
= gCurrentSelection
;
4683 Context
->ResetRequired
= gResetRequired
;
4684 Context
->ExitRequired
= gExitRequired
;
4685 Context
->HiiHandle
= mCurrentHiiHandle
;
4686 Context
->FormId
= mCurrentFormId
;
4687 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4690 // Save the menu history data.
4692 InitializeListHead(&Context
->FormHistoryList
);
4693 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4694 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4695 RemoveEntryList (&MenuList
->Link
);
4697 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4701 // Insert to FormBrowser context list
4703 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4708 Restore globals used by previous call to SendForm().
4712 RestoreBrowserContext (
4717 BROWSER_CONTEXT
*Context
;
4718 FORM_ENTRY_INFO
*MenuList
;
4720 ASSERT (gBrowserContextCount
!= 0);
4721 gBrowserContextCount
--;
4722 if (gBrowserContextCount
== 0) {
4724 // This is not reentry of SendForm(), no context to restore
4729 ASSERT (!IsListEmpty (&gBrowserContextList
));
4731 Link
= GetFirstNode (&gBrowserContextList
);
4732 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4735 // Restore FormBrowser context
4737 gCurrentSelection
= Context
->Selection
;
4738 gResetRequired
= Context
->ResetRequired
;
4739 gExitRequired
= Context
->ExitRequired
;
4740 mCurrentHiiHandle
= Context
->HiiHandle
;
4741 mCurrentFormId
= Context
->FormId
;
4742 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4745 // Restore the menu history data.
4747 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4748 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4749 RemoveEntryList (&MenuList
->Link
);
4751 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4755 // Remove from FormBrowser context list
4757 RemoveEntryList (&Context
->Link
);
4758 gBS
->FreePool (Context
);
4762 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4764 @param Handle The Hii Handle.
4766 @return the found FormSet context. If no found, NULL will return.
4769 FORM_BROWSER_FORMSET
*
4770 GetFormSetFromHiiHandle (
4771 EFI_HII_HANDLE Handle
4775 FORM_BROWSER_FORMSET
*FormSet
;
4777 Link
= GetFirstNode (&gBrowserFormSetList
);
4778 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4779 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4780 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4781 if (!ValidateFormSet(FormSet
)) {
4784 if (FormSet
->HiiHandle
== Handle
) {
4793 Check whether the input HII handle is the FormSet that is being used.
4795 @param Handle The Hii Handle.
4797 @retval TRUE HII handle is being used.
4798 @retval FALSE HII handle is not being used.
4802 IsHiiHandleInBrowserContext (
4803 EFI_HII_HANDLE Handle
4807 BROWSER_CONTEXT
*Context
;
4810 // HiiHandle is Current FormSet.
4812 if (mCurrentHiiHandle
== Handle
) {
4817 // Check whether HiiHandle is in BrowserContext.
4819 Link
= GetFirstNode (&gBrowserContextList
);
4820 while (!IsNull (&gBrowserContextList
, Link
)) {
4821 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4822 if (Context
->HiiHandle
== Handle
) {
4824 // HiiHandle is in BrowserContext
4828 Link
= GetNextNode (&gBrowserContextList
, Link
);
4835 Perform Password check.
4836 Passwork may be encrypted by driver that requires the specific check.
4838 @param Form Form where Password Statement is in.
4839 @param Statement Password statement
4840 @param PasswordString Password string to be checked. It may be NULL.
4841 NULL means to restore password.
4842 "" string can be used to checked whether old password does exist.
4844 @return Status Status of Password check.
4849 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4850 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4851 IN EFI_STRING PasswordString OPTIONAL
4855 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4856 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4857 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4858 FORM_BROWSER_STATEMENT
*Question
;
4860 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4861 Question
= GetBrowserStatement(Statement
);
4862 ASSERT (Question
!= NULL
);
4864 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4865 if (ConfigAccess
== NULL
) {
4866 return EFI_UNSUPPORTED
;
4869 if (PasswordString
== NULL
) {
4874 // Check whether has preexisted password.
4876 if (PasswordString
[0] == 0) {
4877 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
4880 return EFI_NOT_READY
;
4885 // Check whether the input password is same as preexisted password.
4887 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4890 return EFI_NOT_READY
;
4895 // Prepare password string in HII database
4897 if (PasswordString
!= NULL
) {
4898 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4900 IfrTypeValue
.string
= 0;
4904 // Send password to Configuration Driver for validation
4906 Status
= ConfigAccess
->Callback (
4908 EFI_BROWSER_ACTION_CHANGING
,
4909 Question
->QuestionId
,
4910 Question
->HiiValue
.Type
,
4916 // Remove password string from HII database
4918 if (PasswordString
!= NULL
) {
4919 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4926 Find the registered HotKey based on KeyData.
4928 @param[in] KeyData A pointer to a buffer that describes the keystroke
4929 information for the hot key.
4931 @return The registered HotKey context. If no found, NULL will return.
4934 GetHotKeyFromRegisterList (
4935 IN EFI_INPUT_KEY
*KeyData
4939 BROWSER_HOT_KEY
*HotKey
;
4941 Link
= GetFirstNode (&gBrowserHotKeyList
);
4942 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4943 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4944 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4947 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4954 Configure what scope the hot key will impact.
4955 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4956 If no scope is set, the default scope will be FormSet level.
4957 After all registered hot keys are removed, previous Scope can reset to another level.
4959 @param[in] Scope Scope level to be set.
4961 @retval EFI_SUCCESS Scope is set correctly.
4962 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4963 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4969 IN BROWSER_SETTING_SCOPE Scope
4972 if (Scope
>= MaxLevel
) {
4973 return EFI_INVALID_PARAMETER
;
4977 // When no hot key registered in system or on the first setting,
4978 // Scope can be set.
4980 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4981 gBrowserSettingScope
= Scope
;
4982 mBrowserScopeFirstSet
= FALSE
;
4983 } else if (Scope
!= gBrowserSettingScope
) {
4984 return EFI_UNSUPPORTED
;
4991 Register the hot key with its browser action, or unregistered the hot key.
4992 Only support hot key that is not printable character (control key, function key, etc.).
4993 If the action value is zero, the hot key will be unregistered if it has been registered.
4994 If the same hot key has been registered, the new action and help string will override the previous ones.
4996 @param[in] KeyData A pointer to a buffer that describes the keystroke
4997 information for the hot key. Its type is EFI_INPUT_KEY to
4998 be supported by all ConsoleIn devices.
4999 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5000 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5001 @param[in] HelpString Help string that describes the hot key information.
5002 Its value may be NULL for the unregistered hot key.
5004 @retval EFI_SUCCESS Hot key is registered or unregistered.
5005 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5006 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5007 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5012 IN EFI_INPUT_KEY
*KeyData
,
5014 IN UINT16 DefaultId
,
5015 IN EFI_STRING HelpString OPTIONAL
5018 BROWSER_HOT_KEY
*HotKey
;
5021 // Check input parameters.
5023 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5024 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5025 return EFI_INVALID_PARAMETER
;
5029 // Check whether the input KeyData is in BrowserHotKeyList.
5031 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5034 // Unregister HotKey
5036 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5037 if (HotKey
!= NULL
) {
5039 // The registered HotKey is found.
5040 // Remove it from List, and free its resource.
5042 RemoveEntryList (&HotKey
->Link
);
5043 FreePool (HotKey
->KeyData
);
5044 FreePool (HotKey
->HelpString
);
5048 // The registered HotKey is not found.
5050 return EFI_NOT_FOUND
;
5055 // Register HotKey into List.
5057 if (HotKey
== NULL
) {
5059 // Create new Key, and add it into List.
5061 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5062 ASSERT (HotKey
!= NULL
);
5063 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5064 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5065 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5069 // Fill HotKey information.
5071 HotKey
->Action
= Action
;
5072 HotKey
->DefaultId
= DefaultId
;
5073 if (HotKey
->HelpString
!= NULL
) {
5074 FreePool (HotKey
->HelpString
);
5076 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5082 Register Exit handler function.
5083 When more than one handler function is registered, the latter one will override the previous one.
5084 When NULL handler is specified, the previous Exit handler will be unregistered.
5086 @param[in] Handler Pointer to handler function.
5091 RegiserExitHandler (
5092 IN EXIT_HANDLER Handler
5095 ExitHandlerFunction
= Handler
;
5100 Check whether the browser data has been modified.
5102 @retval TRUE Browser data is modified.
5103 @retval FALSE No browser data is modified.
5108 IsBrowserDataModified (
5113 FORM_BROWSER_FORMSET
*FormSet
;
5115 switch (gBrowserSettingScope
) {
5117 if (gCurrentSelection
== NULL
) {
5120 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5123 if (gCurrentSelection
== NULL
) {
5126 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5129 Link
= GetFirstNode (&gBrowserFormSetList
);
5130 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5131 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5132 if (!ValidateFormSet(FormSet
)) {
5136 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5139 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5149 Execute the action requested by the Action parameter.
5151 @param[in] Action Execute the request action.
5152 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5154 @retval EFI_SUCCESS Execute the request action succss.
5155 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5166 FORM_BROWSER_FORMSET
*FormSet
;
5167 FORM_BROWSER_FORM
*Form
;
5169 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5170 return EFI_NOT_READY
;
5173 Status
= EFI_SUCCESS
;
5176 if (gBrowserSettingScope
< SystemLevel
) {
5177 FormSet
= gCurrentSelection
->FormSet
;
5178 Form
= gCurrentSelection
->Form
;
5182 // Executet the discard action.
5184 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5185 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5186 if (EFI_ERROR (Status
)) {
5192 // Executet the difault action.
5194 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5195 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5196 if (EFI_ERROR (Status
)) {
5199 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5203 // Executet the submit action.
5205 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5206 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5207 if (EFI_ERROR (Status
)) {
5213 // Executet the reset action.
5215 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5216 gResetRequired
= TRUE
;
5220 // Executet the exit action.
5222 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5223 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5224 if (gBrowserSettingScope
== SystemLevel
) {
5225 if (ExitHandlerFunction
!= NULL
) {
5226 ExitHandlerFunction ();
5230 gExitRequired
= TRUE
;
5237 Create reminder to let user to choose save or discard the changed browser data.
5238 Caller can use it to actively check the changed browser data.
5240 @retval BROWSER_NO_CHANGES No browser data is changed.
5241 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5242 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5243 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5253 FORM_BROWSER_FORMSET
*FormSet
;
5254 BOOLEAN IsDataChanged
;
5255 UINT32 DataSavedAction
;
5258 DataSavedAction
= BROWSER_NO_CHANGES
;
5259 IsDataChanged
= FALSE
;
5260 Link
= GetFirstNode (&gBrowserFormSetList
);
5261 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5262 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5263 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5264 if (!ValidateFormSet(FormSet
)) {
5267 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5268 IsDataChanged
= TRUE
;
5274 // No data is changed. No save is required.
5276 if (!IsDataChanged
) {
5277 return DataSavedAction
;
5281 // If data is changed, prompt user to save or discard it.
5284 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5286 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5287 SubmitForm (NULL
, NULL
, SystemLevel
);
5288 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5290 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5291 DiscardForm (NULL
, NULL
, SystemLevel
);
5292 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5294 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5295 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5300 return DataSavedAction
;
5304 Check whether the Reset Required for the browser
5306 @retval TRUE Browser required to reset after exit.
5307 @retval FALSE Browser not need to reset after exit.
5316 return gResetRequired
;