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
,
35 IsBrowserDataModified
,
40 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
41 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
42 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
43 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
45 UINTN gBrowserContextCount
= 0;
46 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
47 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
48 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
49 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
51 BOOLEAN gFinishRetrieveCall
;
52 BOOLEAN gResetRequired
;
53 BOOLEAN gExitRequired
;
54 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
55 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
56 EXIT_HANDLER ExitHandlerFunction
= NULL
;
57 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
60 // Browser Global Strings
63 CHAR16
*mUnknownString
= L
"!";
65 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
67 extern UINT32 gBrowserStatus
;
68 extern CHAR16
*gErrorInfo
;
69 extern EFI_GUID mCurrentFormSetGuid
;
70 extern EFI_HII_HANDLE mCurrentHiiHandle
;
71 extern UINT16 mCurrentFormId
;
72 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
75 Create a menu with specified formset GUID and form ID, and add it as a child
76 of the given parent menu.
78 @param HiiHandle Hii handle related to this formset.
79 @param FormSetGuid The Formset Guid of menu to be added.
80 @param FormId The Form ID of menu to be added.
81 @param QuestionId The question id of this menu to be added.
83 @return A pointer to the newly added menu or NULL if memory is insufficient.
88 IN EFI_HII_HANDLE HiiHandle
,
89 IN EFI_GUID
*FormSetGuid
,
94 FORM_ENTRY_INFO
*MenuList
;
96 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
97 if (MenuList
== NULL
) {
101 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
103 MenuList
->HiiHandle
= HiiHandle
;
104 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
105 MenuList
->FormId
= FormId
;
106 MenuList
->QuestionId
= QuestionId
;
109 // If parent is not specified, it is the root Form of a Formset
111 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
117 Return the form id for the input hiihandle and formset.
119 @param HiiHandle HiiHandle for FormSet.
120 @param FormSetGuid The Formset GUID of the menu to search.
122 @return First form's id for this form set.
127 IN EFI_HII_HANDLE HiiHandle
,
128 IN EFI_GUID
*FormSetGuid
132 FORM_BROWSER_FORM
*Form
;
134 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
135 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
141 Search Menu with given FormSetGuid and FormId in all cached menu list.
143 @param HiiHandle HiiHandle for FormSet.
144 @param FormSetGuid The Formset GUID of the menu to search.
145 @param FormId The Form ID of menu to search.
147 @return A pointer to menu found or NULL if not found.
152 IN EFI_HII_HANDLE HiiHandle
,
153 IN EFI_GUID
*FormSetGuid
,
158 FORM_ENTRY_INFO
*MenuList
;
159 FORM_ENTRY_INFO
*RetMenu
;
160 EFI_FORM_ID FirstFormId
;
164 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
165 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
166 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
167 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
170 // If already find the menu, free the menus behind it.
172 if (RetMenu
!= NULL
) {
173 RemoveEntryList (&MenuList
->Link
);
179 // Find the same FromSet.
181 if (MenuList
->HiiHandle
== HiiHandle
) {
182 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
184 // FormSetGuid is not specified.
187 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
188 if (MenuList
->FormId
== FormId
) {
190 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
191 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
192 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
204 Find parent menu for current menu.
206 @param CurrentMenu Current Menu
208 @retval The parent menu for current menu.
212 IN FORM_ENTRY_INFO
*CurrentMenu
215 FORM_ENTRY_INFO
*ParentMenu
;
218 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
219 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
226 Free Menu list linked list.
228 @param MenuListHead One Menu list point in the menu list.
233 LIST_ENTRY
*MenuListHead
236 FORM_ENTRY_INFO
*MenuList
;
238 while (!IsListEmpty (MenuListHead
)) {
239 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
240 RemoveEntryList (&MenuList
->Link
);
247 Load all hii formset to the browser.
255 FORM_BROWSER_FORMSET
*LocalFormSet
;
256 EFI_HII_HANDLE
*HiiHandles
;
260 FORM_BROWSER_FORMSET
*OldFormset
;
261 BOOLEAN OldRetrieveValue
;
263 OldFormset
= mSystemLevelFormSet
;
264 OldRetrieveValue
= gFinishRetrieveCall
;
265 gFinishRetrieveCall
= FALSE
;
268 // Get all the Hii handles
270 HiiHandles
= HiiGetHiiHandles (NULL
);
271 ASSERT (HiiHandles
!= NULL
);
274 // Search for formset of each class type
276 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
278 // Check HiiHandles[Index] does exist in global maintain list.
280 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
285 // Initilize FormSet Setting
287 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
288 ASSERT (LocalFormSet
!= NULL
);
289 mSystemLevelFormSet
= LocalFormSet
;
291 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
292 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
293 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
294 DestroyFormSet (LocalFormSet
);
297 InitializeCurrentSetting (LocalFormSet
);
300 // Initilize Questions' Value
302 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
303 if (EFI_ERROR (Status
)) {
304 DestroyFormSet (LocalFormSet
);
310 // Free resources, and restore gOldFormSet and gClassOfVfr
312 FreePool (HiiHandles
);
314 gFinishRetrieveCall
= OldRetrieveValue
;
315 mSystemLevelFormSet
= OldFormset
;
319 This is the routine which an external caller uses to direct the browser
320 where to obtain it's information.
323 @param This The Form Browser protocol instanse.
324 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
325 display a list of the formsets for the handles specified.
326 @param HandleCount The number of Handles specified in Handle.
327 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
328 field in the EFI_IFR_FORM_SET op-code for the specified
329 forms-based package. If FormSetGuid is NULL, then this
330 function will display the first found forms package.
331 @param FormId This field specifies which EFI_IFR_FORM to render as the first
332 displayable page. If this field has a value of 0x0000, then
333 the forms browser will render the specified forms in their encoded order.
334 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
336 @param ActionRequest Points to the action recommended by the form.
338 @retval EFI_SUCCESS The function completed successfully.
339 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
340 @retval EFI_NOT_FOUND No valid forms could be found to display.
346 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
347 IN EFI_HII_HANDLE
*Handles
,
348 IN UINTN HandleCount
,
349 IN EFI_GUID
*FormSetGuid
, OPTIONAL
350 IN UINT16 FormId
, OPTIONAL
351 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
352 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
356 UI_MENU_SELECTION
*Selection
;
358 FORM_BROWSER_FORMSET
*FormSet
;
359 FORM_ENTRY_INFO
*MenuList
;
362 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
364 if (mFormDisplay
== NULL
) {
365 return EFI_UNSUPPORTED
;
369 // Save globals used by SendForm()
371 SaveBrowserContext ();
373 gFinishRetrieveCall
= FALSE
;
374 gResetRequired
= FALSE
;
375 gExitRequired
= FALSE
;
376 Status
= EFI_SUCCESS
;
378 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
380 for (Index
= 0; Index
< HandleCount
; Index
++) {
381 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
382 ASSERT (Selection
!= NULL
);
384 Selection
->Handle
= Handles
[Index
];
385 if (FormSetGuid
!= NULL
) {
386 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
387 Selection
->FormId
= FormId
;
389 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
393 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
394 ASSERT (FormSet
!= NULL
);
397 // Initialize internal data structures of FormSet
399 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
400 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
401 DestroyFormSet (FormSet
);
404 Selection
->FormSet
= FormSet
;
405 mSystemLevelFormSet
= FormSet
;
408 // Display this formset
410 gCurrentSelection
= Selection
;
412 Status
= SetupBrowser (Selection
);
414 gCurrentSelection
= NULL
;
415 mSystemLevelFormSet
= NULL
;
418 // If no data is changed, don't need to save current FormSet into the maintain list.
420 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
421 CleanBrowserStorage(FormSet
);
422 RemoveEntryList (&FormSet
->Link
);
423 DestroyFormSet (FormSet
);
426 if (EFI_ERROR (Status
)) {
429 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
431 FreePool (Selection
);
435 // Still has error info, pop up a message.
437 if (gBrowserStatus
!= BROWSER_SUCCESS
) {
438 gDisplayFormData
.BrowserStatus
= gBrowserStatus
;
439 gDisplayFormData
.ErrorString
= gErrorInfo
;
441 gBrowserStatus
= BROWSER_SUCCESS
;
444 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
447 if (ActionRequest
!= NULL
) {
448 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
449 if (gResetRequired
) {
450 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
454 mFormDisplay
->ExitDisplay();
457 // Clear the menu history data.
459 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
460 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
461 RemoveEntryList (&MenuList
->Link
);
466 // Restore globals used by SendForm()
468 RestoreBrowserContext ();
474 Get or set data to the storage.
476 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
477 @param ResultsData A string returned from an IFR browser or
478 equivalent. The results string will have no
479 routing information in them.
480 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
481 (if RetrieveData = TRUE) data from the uncommitted
482 browser state information or set (if RetrieveData
483 = FALSE) data in the uncommitted browser state
485 @param Storage The pointer to the storage.
487 @retval EFI_SUCCESS The results have been distributed or are awaiting
493 IN OUT UINTN
*ResultsDataSize
,
494 IN OUT EFI_STRING
*ResultsData
,
495 IN BOOLEAN RetrieveData
,
496 IN BROWSER_STORAGE
*Storage
507 // Generate <ConfigResp>
509 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
510 if (EFI_ERROR (Status
)) {
515 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
516 // Also need to consider add "\0" at first time.
518 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
519 BufferSize
= StrSize (StrPtr
);
523 // Copy the data if the input buffer is bigger enough.
525 if (*ResultsDataSize
>= BufferSize
) {
526 StrCpy (*ResultsData
, StrPtr
);
529 *ResultsDataSize
= BufferSize
;
530 FreePool (ConfigResp
);
533 // Prepare <ConfigResp>
535 TmpSize
= StrLen (*ResultsData
);
536 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
537 ConfigResp
= AllocateZeroPool (BufferSize
);
538 ASSERT (ConfigResp
!= NULL
);
540 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
541 StrCat (ConfigResp
, L
"&");
542 StrCat (ConfigResp
, *ResultsData
);
545 // Update Browser uncommited data
547 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
548 FreePool (ConfigResp
);
549 if (EFI_ERROR (Status
)) {
558 This routine called this service in the browser to retrieve or set certain uncommitted
559 state information that resides in the open formsets.
561 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
563 @param ResultsDataSize A pointer to the size of the buffer associated
565 @param ResultsData A string returned from an IFR browser or
566 equivalent. The results string will have no
567 routing information in them.
568 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
569 (if RetrieveData = TRUE) data from the uncommitted
570 browser state information or set (if RetrieveData
571 = FALSE) data in the uncommitted browser state
573 @param VariableGuid An optional field to indicate the target variable
575 @param VariableName An optional field to indicate the target
576 human-readable variable name.
578 @retval EFI_SUCCESS The results have been distributed or are awaiting
580 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
581 contain the results data.
587 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
588 IN OUT UINTN
*ResultsDataSize
,
589 IN OUT EFI_STRING ResultsData
,
590 IN BOOLEAN RetrieveData
,
591 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
592 IN CONST CHAR16
*VariableName OPTIONAL
597 BROWSER_STORAGE
*Storage
;
598 FORMSET_STORAGE
*FormsetStorage
;
602 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
603 return EFI_INVALID_PARAMETER
;
606 TotalSize
= *ResultsDataSize
;
609 Status
= EFI_SUCCESS
;
611 if (VariableGuid
!= NULL
) {
613 // Try to find target storage in the current formset.
615 Link
= GetFirstNode (&gBrowserStorageList
);
616 while (!IsNull (&gBrowserStorageList
, Link
)) {
617 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
618 Link
= GetNextNode (&gBrowserStorageList
, Link
);
620 // Check the current storage.
622 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
626 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
627 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
629 // Buffer storage require both GUID and Name
631 if (VariableName
== NULL
) {
632 return EFI_NOT_FOUND
;
635 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
640 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
641 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
642 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
643 return EFI_NOT_FOUND
;
646 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
651 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
652 if (EFI_ERROR (Status
)) {
656 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
657 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
661 // Different formsets may have same varstore, so here just set the flag
662 // not exit the circle.
669 return EFI_NOT_FOUND
;
673 // GUID/Name is not specified, take the first storage in FormSet
675 if (mSystemLevelFormSet
== NULL
) {
676 return EFI_NOT_READY
;
680 // Generate <ConfigResp>
682 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
683 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
684 return EFI_UNSUPPORTED
;
687 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
689 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
690 if (EFI_ERROR (Status
)) {
696 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
697 *ResultsDataSize
= TotalSize
;
706 Callback function for SimpleTextInEx protocol install events
708 @param Event the event that is signaled.
709 @param Context not used here.
714 FormDisplayCallback (
721 if (mFormDisplay
!= NULL
) {
725 Status
= gBS
->LocateProtocol (
726 &gEdkiiFormDisplayEngineProtocolGuid
,
728 (VOID
**) &mFormDisplay
733 Initialize Setup Browser driver.
735 @param ImageHandle The image handle.
736 @param SystemTable The system table.
738 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
739 @return Other value if failed to initialize the Setup Browser module.
745 IN EFI_HANDLE ImageHandle
,
746 IN EFI_SYSTEM_TABLE
*SystemTable
753 // Locate required Hii relative protocols
755 Status
= gBS
->LocateProtocol (
756 &gEfiHiiDatabaseProtocolGuid
,
758 (VOID
**) &mHiiDatabase
760 ASSERT_EFI_ERROR (Status
);
762 Status
= gBS
->LocateProtocol (
763 &gEfiHiiConfigRoutingProtocolGuid
,
765 (VOID
**) &mHiiConfigRouting
767 ASSERT_EFI_ERROR (Status
);
769 Status
= gBS
->LocateProtocol (
770 &gEfiDevicePathFromTextProtocolGuid
,
772 (VOID
**) &mPathFromText
776 // Install FormBrowser2 protocol
778 mPrivateData
.Handle
= NULL
;
779 Status
= gBS
->InstallProtocolInterface (
780 &mPrivateData
.Handle
,
781 &gEfiFormBrowser2ProtocolGuid
,
782 EFI_NATIVE_INTERFACE
,
783 &mPrivateData
.FormBrowser2
785 ASSERT_EFI_ERROR (Status
);
788 // Install FormBrowserEx2 protocol
790 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
791 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
792 mPrivateData
.Handle
= NULL
;
793 Status
= gBS
->InstallProtocolInterface (
794 &mPrivateData
.Handle
,
795 &gEdkiiFormBrowserEx2ProtocolGuid
,
796 EFI_NATIVE_INTERFACE
,
797 &mPrivateData
.FormBrowserEx2
799 ASSERT_EFI_ERROR (Status
);
801 Status
= gBS
->InstallProtocolInterface (
802 &mPrivateData
.Handle
,
803 &gEfiFormBrowserExProtocolGuid
,
804 EFI_NATIVE_INTERFACE
,
805 &mPrivateData
.FormBrowserEx
807 ASSERT_EFI_ERROR (Status
);
809 InitializeDisplayFormData ();
811 Status
= gBS
->LocateProtocol (
812 &gEdkiiFormDisplayEngineProtocolGuid
,
814 (VOID
**) &mFormDisplay
817 if (EFI_ERROR (Status
)) {
818 EfiCreateProtocolNotifyEvent (
819 &gEdkiiFormDisplayEngineProtocolGuid
,
832 Create a new string in HII Package List.
834 @param String The String to be added
835 @param HiiHandle The package list in the HII database to insert the
838 @return The output string.
844 IN EFI_HII_HANDLE HiiHandle
847 EFI_STRING_ID StringId
;
849 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
850 ASSERT (StringId
!= 0);
857 Delete a string from HII Package List.
859 @param StringId Id of the string in HII database.
860 @param HiiHandle The HII package list handle.
862 @retval EFI_SUCCESS The string was deleted successfully.
867 IN EFI_STRING_ID StringId
,
868 IN EFI_HII_HANDLE HiiHandle
873 NullChar
= CHAR_NULL
;
874 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
880 Get the string based on the StringId and HII Package List Handle.
882 @param Token The String's ID.
883 @param HiiHandle The package list in the HII database to search for
884 the specified string.
886 @return The output string.
891 IN EFI_STRING_ID Token
,
892 IN EFI_HII_HANDLE HiiHandle
897 if (HiiHandle
== NULL
) {
901 String
= HiiGetString (HiiHandle
, Token
, NULL
);
902 if (String
== NULL
) {
903 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
904 ASSERT (String
!= NULL
);
906 return (CHAR16
*) String
;
911 Allocate new memory and then copy the Unicode string Source to Destination.
913 @param Dest Location to copy string
914 @param Src String to copy
919 IN OUT CHAR16
**Dest
,
926 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
927 ASSERT (*Dest
!= NULL
);
932 Allocate new memory and concatinate Source on the end of Destination.
934 @param Dest String to added to the end of.
935 @param Src String to concatinate.
940 IN OUT CHAR16
**Dest
,
948 NewStringCpy (Dest
, Src
);
952 TmpSize
= StrSize (*Dest
);
953 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
954 ASSERT (NewString
!= NULL
);
956 StrCpy (NewString
, *Dest
);
957 StrCat (NewString
, Src
);
964 Get Value for given Name from a NameValue Storage.
966 @param Storage The NameValue Storage.
967 @param Name The Name.
968 @param Value The retured Value.
969 @param GetValueFrom Where to get source value, from EditValue or Value.
971 @retval EFI_SUCCESS Value found for given Name.
972 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
977 IN BROWSER_STORAGE
*Storage
,
979 IN OUT CHAR16
**Value
,
980 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
984 NAME_VALUE_NODE
*Node
;
986 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
987 return EFI_INVALID_PARAMETER
;
992 Link
= GetFirstNode (&Storage
->NameValueListHead
);
993 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
994 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
996 if (StrCmp (Name
, Node
->Name
) == 0) {
997 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
998 NewStringCpy (Value
, Node
->EditValue
);
1000 NewStringCpy (Value
, Node
->Value
);
1005 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1008 return EFI_NOT_FOUND
;
1013 Set Value of given Name in a NameValue Storage.
1015 @param Storage The NameValue Storage.
1016 @param Name The Name.
1017 @param Value The Value to set.
1018 @param SetValueTo Whether update editValue or Value.
1019 @param ReturnNode The node use the input name.
1021 @retval EFI_SUCCESS Value found for given Name.
1022 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1027 IN BROWSER_STORAGE
*Storage
,
1030 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1031 OUT NAME_VALUE_NODE
**ReturnNode
1035 NAME_VALUE_NODE
*Node
;
1038 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1039 return EFI_INVALID_PARAMETER
;
1042 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1043 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1044 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1046 if (StrCmp (Name
, Node
->Name
) == 0) {
1047 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1048 Buffer
= Node
->EditValue
;
1050 Buffer
= Node
->Value
;
1052 if (Buffer
!= NULL
) {
1055 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1056 ASSERT (Buffer
!= NULL
);
1057 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1058 Node
->EditValue
= Buffer
;
1060 Node
->Value
= Buffer
;
1063 if (ReturnNode
!= NULL
) {
1070 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1073 return EFI_NOT_FOUND
;
1078 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1080 @param Storage The Storage to be conveted.
1081 @param ConfigResp The returned <ConfigResp>.
1082 @param ConfigRequest The ConfigRequest string.
1083 @param GetEditBuf Get the data from editbuffer or buffer.
1085 @retval EFI_SUCCESS Convert success.
1086 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1090 StorageToConfigResp (
1091 IN BROWSER_STORAGE
*Storage
,
1092 IN CHAR16
**ConfigResp
,
1093 IN CHAR16
*ConfigRequest
,
1094 IN BOOLEAN GetEditBuf
1098 EFI_STRING Progress
;
1100 NAME_VALUE_NODE
*Node
;
1103 Status
= EFI_SUCCESS
;
1105 switch (Storage
->Type
) {
1106 case EFI_HII_VARSTORE_BUFFER
:
1107 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1108 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1109 Status
= mHiiConfigRouting
->BlockToConfig (
1119 case EFI_HII_VARSTORE_NAME_VALUE
:
1121 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1123 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1124 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1125 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1127 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1128 NewStringCat (ConfigResp
, L
"&");
1129 NewStringCat (ConfigResp
, Node
->Name
);
1130 NewStringCat (ConfigResp
, L
"=");
1132 NewStringCat (ConfigResp
, Node
->EditValue
);
1134 NewStringCat (ConfigResp
, Node
->Value
);
1137 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1141 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1143 Status
= EFI_INVALID_PARAMETER
;
1152 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1154 @param Storage The Storage to receive the settings.
1155 @param ConfigResp The <ConfigResp> to be converted.
1157 @retval EFI_SUCCESS Convert success.
1158 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1162 ConfigRespToStorage (
1163 IN BROWSER_STORAGE
*Storage
,
1164 IN CHAR16
*ConfigResp
1168 EFI_STRING Progress
;
1174 Status
= EFI_SUCCESS
;
1176 switch (Storage
->Type
) {
1177 case EFI_HII_VARSTORE_BUFFER
:
1178 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1179 BufferSize
= Storage
->Size
;
1180 Status
= mHiiConfigRouting
->ConfigToBlock (
1183 Storage
->EditBuffer
,
1189 case EFI_HII_VARSTORE_NAME_VALUE
:
1190 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1191 if (StrPtr
== NULL
) {
1194 StrPtr
= StrStr (ConfigResp
, L
"&");
1195 while (StrPtr
!= NULL
) {
1199 StrPtr
= StrPtr
+ 1;
1201 StrPtr
= StrStr (StrPtr
, L
"=");
1202 if (StrPtr
== NULL
) {
1210 StrPtr
= StrPtr
+ 1;
1212 StrPtr
= StrStr (StrPtr
, L
"&");
1213 if (StrPtr
!= NULL
) {
1216 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1220 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1222 Status
= EFI_INVALID_PARAMETER
;
1231 Get Question's current Value.
1233 @param FormSet FormSet data structure.
1234 @param Form Form data structure.
1235 @param Question Question to be initialized.
1236 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1238 @retval EFI_SUCCESS The function completed successfully.
1243 IN FORM_BROWSER_FORMSET
*FormSet
,
1244 IN FORM_BROWSER_FORM
*Form
,
1245 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1246 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1255 BROWSER_STORAGE
*Storage
;
1256 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1257 CHAR16
*ConfigRequest
;
1265 BOOLEAN IsBufferStorage
;
1270 Status
= EFI_SUCCESS
;
1274 if (GetValueFrom
>= GetSetValueWithMax
) {
1275 return EFI_INVALID_PARAMETER
;
1279 // Question value is provided by an Expression, evaluate it
1281 if (Question
->ValueExpression
!= NULL
) {
1282 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1283 if (!EFI_ERROR (Status
)) {
1284 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1285 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1286 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1287 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1288 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1290 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1291 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1293 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1295 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1296 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1302 // Get question value by read expression.
1304 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1305 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1306 if (!EFI_ERROR (Status
) &&
1307 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1309 // Only update question value to the valid result.
1311 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1312 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1313 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1314 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1315 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1317 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1318 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1320 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1322 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1323 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1329 // Question value is provided by RTC
1331 Storage
= Question
->Storage
;
1332 QuestionValue
= &Question
->HiiValue
.Value
;
1333 if (Storage
== NULL
) {
1335 // It's a Question without storage, or RTC date/time
1337 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1339 // Date and time define the same Flags bit
1341 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1342 case QF_DATE_STORAGE_TIME
:
1343 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1346 case QF_DATE_STORAGE_WAKEUP
:
1347 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1350 case QF_DATE_STORAGE_NORMAL
:
1353 // For date/time without storage
1358 if (EFI_ERROR (Status
)) {
1362 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1363 QuestionValue
->date
.Year
= EfiTime
.Year
;
1364 QuestionValue
->date
.Month
= EfiTime
.Month
;
1365 QuestionValue
->date
.Day
= EfiTime
.Day
;
1367 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1368 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1369 QuestionValue
->time
.Second
= EfiTime
.Second
;
1377 // Question value is provided by EFI variable
1379 StorageWidth
= Question
->StorageWidth
;
1380 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1381 if (Question
->BufferValue
!= NULL
) {
1382 Dst
= Question
->BufferValue
;
1384 Dst
= (UINT8
*) QuestionValue
;
1387 Status
= gRT
->GetVariable (
1388 Question
->VariableName
,
1395 // Always return success, even this EFI variable doesn't exist
1401 // Question Value is provided by Buffer Storage or NameValue Storage
1403 if (Question
->BufferValue
!= NULL
) {
1405 // This Question is password or orderedlist
1407 Dst
= Question
->BufferValue
;
1410 // Other type of Questions
1412 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1415 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1416 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1417 IsBufferStorage
= TRUE
;
1419 IsBufferStorage
= FALSE
;
1421 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1422 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1423 if (IsBufferStorage
) {
1424 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1426 // Copy from storage Edit buffer
1428 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1431 // Copy from storage Edit buffer
1433 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1437 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1438 if (EFI_ERROR (Status
)) {
1442 ASSERT (Value
!= NULL
);
1443 LengthStr
= StrLen (Value
);
1444 Status
= EFI_SUCCESS
;
1447 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1448 // Add string tail char L'\0' into Length
1450 Length
= StorageWidth
+ sizeof (CHAR16
);
1451 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1452 Status
= EFI_BUFFER_TOO_SMALL
;
1454 StringPtr
= (CHAR16
*) Dst
;
1455 ZeroMem (TemStr
, sizeof (TemStr
));
1456 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1457 StrnCpy (TemStr
, Value
+ Index
, 4);
1458 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1461 // Add tailing L'\0' character
1463 StringPtr
[Index
/4] = L
'\0';
1466 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1467 Status
= EFI_BUFFER_TOO_SMALL
;
1469 ZeroMem (TemStr
, sizeof (TemStr
));
1470 for (Index
= 0; Index
< LengthStr
; Index
++) {
1471 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1472 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1473 if ((Index
& 1) == 0) {
1474 Dst
[Index
/2] = DigitUint8
;
1476 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1486 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1487 // <ConfigHdr> + "&" + <VariableName>
1489 if (IsBufferStorage
) {
1490 Length
= StrLen (Storage
->ConfigHdr
);
1491 Length
+= StrLen (Question
->BlockName
);
1493 Length
= StrLen (Storage
->ConfigHdr
);
1494 Length
+= StrLen (Question
->VariableName
) + 1;
1496 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1497 ASSERT (ConfigRequest
!= NULL
);
1499 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1500 if (IsBufferStorage
) {
1501 StrCat (ConfigRequest
, Question
->BlockName
);
1503 StrCat (ConfigRequest
, L
"&");
1504 StrCat (ConfigRequest
, Question
->VariableName
);
1508 // Request current settings from Configuration Driver
1510 Status
= mHiiConfigRouting
->ExtractConfig (
1516 FreePool (ConfigRequest
);
1517 if (EFI_ERROR (Status
)) {
1522 // Skip <ConfigRequest>
1524 if (IsBufferStorage
) {
1525 Value
= StrStr (Result
, L
"&VALUE");
1526 if (Value
== NULL
) {
1528 return EFI_NOT_FOUND
;
1535 Value
= Result
+ Length
;
1537 if (*Value
!= '=') {
1539 return EFI_NOT_FOUND
;
1542 // Skip '=', point to value
1547 // Suppress <AltResp> if any
1550 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1555 LengthStr
= StrLen (Value
);
1556 Status
= EFI_SUCCESS
;
1557 if (!IsBufferStorage
&& IsString
) {
1559 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1560 // Add string tail char L'\0' into Length
1562 Length
= StorageWidth
+ sizeof (CHAR16
);
1563 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1564 Status
= EFI_BUFFER_TOO_SMALL
;
1566 StringPtr
= (CHAR16
*) Dst
;
1567 ZeroMem (TemStr
, sizeof (TemStr
));
1568 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1569 StrnCpy (TemStr
, Value
+ Index
, 4);
1570 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1573 // Add tailing L'\0' character
1575 StringPtr
[Index
/4] = L
'\0';
1578 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1579 Status
= EFI_BUFFER_TOO_SMALL
;
1581 ZeroMem (TemStr
, sizeof (TemStr
));
1582 for (Index
= 0; Index
< LengthStr
; Index
++) {
1583 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1584 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1585 if ((Index
& 1) == 0) {
1586 Dst
[Index
/2] = DigitUint8
;
1588 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1594 if (EFI_ERROR (Status
)) {
1600 // Synchronize Edit Buffer
1602 if (IsBufferStorage
) {
1603 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1605 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1608 if (Result
!= NULL
) {
1618 Save Question Value to edit copy(cached) or Storage(uncached).
1620 @param FormSet FormSet data structure.
1621 @param Form Form data structure.
1622 @param Question Pointer to the Question.
1623 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1625 @retval EFI_SUCCESS The function completed successfully.
1630 IN FORM_BROWSER_FORMSET
*FormSet
,
1631 IN FORM_BROWSER_FORM
*Form
,
1632 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1633 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1643 BROWSER_STORAGE
*Storage
;
1644 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1649 BOOLEAN IsBufferStorage
;
1655 NAME_VALUE_NODE
*Node
;
1657 Status
= EFI_SUCCESS
;
1660 if (SetValueTo
>= GetSetValueWithMax
) {
1661 return EFI_INVALID_PARAMETER
;
1665 // If Question value is provided by an Expression, then it is read only
1667 if (Question
->ValueExpression
!= NULL
) {
1672 // Before set question value, evaluate its write expression.
1674 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1675 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1676 if (EFI_ERROR (Status
)) {
1682 // Question value is provided by RTC
1684 Storage
= Question
->Storage
;
1685 QuestionValue
= &Question
->HiiValue
.Value
;
1686 if (Storage
== NULL
) {
1688 // It's a Question without storage, or RTC date/time
1690 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1692 // Date and time define the same Flags bit
1694 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1695 case QF_DATE_STORAGE_TIME
:
1696 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1699 case QF_DATE_STORAGE_WAKEUP
:
1700 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1703 case QF_DATE_STORAGE_NORMAL
:
1706 // For date/time without storage
1711 if (EFI_ERROR (Status
)) {
1715 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1716 EfiTime
.Year
= QuestionValue
->date
.Year
;
1717 EfiTime
.Month
= QuestionValue
->date
.Month
;
1718 EfiTime
.Day
= QuestionValue
->date
.Day
;
1720 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1721 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1722 EfiTime
.Second
= QuestionValue
->time
.Second
;
1725 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1726 Status
= gRT
->SetTime (&EfiTime
);
1728 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1736 // Question value is provided by EFI variable
1738 StorageWidth
= Question
->StorageWidth
;
1739 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1740 if (Question
->BufferValue
!= NULL
) {
1741 Src
= Question
->BufferValue
;
1743 Src
= (UINT8
*) QuestionValue
;
1746 Status
= gRT
->SetVariable (
1747 Question
->VariableName
,
1749 Storage
->Attributes
,
1757 // Question Value is provided by Buffer Storage or NameValue Storage
1759 if (Question
->BufferValue
!= NULL
) {
1760 Src
= Question
->BufferValue
;
1762 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1765 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1766 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1767 IsBufferStorage
= TRUE
;
1769 IsBufferStorage
= FALSE
;
1771 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1773 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1774 if (IsBufferStorage
) {
1775 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1777 // Copy to storage edit buffer
1779 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1780 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1782 // Copy to storage edit buffer
1784 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1789 // Allocate enough string buffer.
1792 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1793 Value
= AllocateZeroPool (BufferLen
);
1794 ASSERT (Value
!= NULL
);
1796 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1798 TemName
= (CHAR16
*) Src
;
1800 for (; *TemName
!= L
'\0'; TemName
++) {
1801 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1804 BufferLen
= StorageWidth
* 2 + 1;
1805 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1806 ASSERT (Value
!= NULL
);
1808 // Convert Buffer to Hex String
1810 TemBuffer
= Src
+ StorageWidth
- 1;
1812 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1813 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1817 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1819 if (EFI_ERROR (Status
)) {
1823 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1825 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1826 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1828 if (IsBufferStorage
) {
1829 Length
= StrLen (Question
->BlockName
) + 7;
1831 Length
= StrLen (Question
->VariableName
) + 2;
1833 if (!IsBufferStorage
&& IsString
) {
1834 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1836 Length
+= (StorageWidth
* 2);
1838 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1839 ASSERT (ConfigResp
!= NULL
);
1841 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1842 if (IsBufferStorage
) {
1843 StrCat (ConfigResp
, Question
->BlockName
);
1844 StrCat (ConfigResp
, L
"&VALUE=");
1846 StrCat (ConfigResp
, L
"&");
1847 StrCat (ConfigResp
, Question
->VariableName
);
1848 StrCat (ConfigResp
, L
"=");
1851 Value
= ConfigResp
+ StrLen (ConfigResp
);
1853 if (!IsBufferStorage
&& IsString
) {
1855 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1857 TemName
= (CHAR16
*) Src
;
1859 for (; *TemName
!= L
'\0'; TemName
++) {
1860 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1864 // Convert Buffer to Hex String
1866 TemBuffer
= Src
+ StorageWidth
- 1;
1868 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1869 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1874 // Convert to lower char.
1876 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1877 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1878 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1883 // Submit Question Value to Configuration Driver
1885 Status
= mHiiConfigRouting
->RouteConfig (
1890 if (EFI_ERROR (Status
)) {
1891 FreePool (ConfigResp
);
1894 FreePool (ConfigResp
);
1897 // Sync storage, from editbuffer to buffer.
1899 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1907 Perform nosubmitif check for a Form.
1909 @param FormSet FormSet data structure.
1910 @param Form Form data structure.
1911 @param Question The Question to be validated.
1912 @param Type Validation type: NoSubmit
1914 @retval EFI_SUCCESS Form validation pass.
1915 @retval other Form validation failed.
1920 IN FORM_BROWSER_FORMSET
*FormSet
,
1921 IN FORM_BROWSER_FORM
*Form
,
1922 IN FORM_BROWSER_STATEMENT
*Question
,
1928 LIST_ENTRY
*ListHead
;
1930 FORM_EXPRESSION
*Expression
;
1932 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1933 ListHead
= &Question
->NoSubmitListHead
;
1935 return EFI_UNSUPPORTED
;
1938 Link
= GetFirstNode (ListHead
);
1939 while (!IsNull (ListHead
, Link
)) {
1940 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1943 // Evaluate the expression
1945 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1946 if (EFI_ERROR (Status
)) {
1950 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1952 // Condition meet, show up error message
1954 if (Expression
->Error
!= 0) {
1955 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1956 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1957 gBrowserStatus
= BROWSER_NO_SUBMIT_IF
;
1962 return EFI_NOT_READY
;
1965 Link
= GetNextNode (ListHead
, Link
);
1973 Perform NoSubmit check for each Form in FormSet.
1975 @param FormSet FormSet data structure.
1976 @param CurrentForm Current input form data structure.
1978 @retval EFI_SUCCESS Form validation pass.
1979 @retval other Form validation failed.
1984 IN FORM_BROWSER_FORMSET
*FormSet
,
1985 IN FORM_BROWSER_FORM
*CurrentForm
1990 FORM_BROWSER_STATEMENT
*Question
;
1991 FORM_BROWSER_FORM
*Form
;
1992 LIST_ENTRY
*LinkForm
;
1994 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1995 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1996 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1997 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1999 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2003 Link
= GetFirstNode (&Form
->StatementListHead
);
2004 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2005 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2007 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2008 if (EFI_ERROR (Status
)) {
2012 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2020 Fill storage's edit copy with settings requested from Configuration Driver.
2022 @param FormSet FormSet data structure.
2023 @param Storage The storage which need to sync.
2024 @param ConfigRequest The config request string which used to sync storage.
2025 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2026 editbuffer to buffer
2027 if TRUE, copy the editbuffer to the buffer.
2028 if FALSE, copy the buffer to the editbuffer.
2030 @retval EFI_SUCCESS The function completed successfully.
2034 SynchronizeStorage (
2035 IN FORM_BROWSER_FORMSET
*FormSet
,
2036 OUT BROWSER_STORAGE
*Storage
,
2037 IN CHAR16
*ConfigRequest
,
2038 IN BOOLEAN SyncOrRestore
2042 EFI_STRING Progress
;
2046 NAME_VALUE_NODE
*Node
;
2050 Status
= EFI_SUCCESS
;
2053 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2054 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2055 BufferSize
= Storage
->Size
;
2057 if (SyncOrRestore
) {
2058 Src
= Storage
->EditBuffer
;
2059 Dst
= Storage
->Buffer
;
2061 Src
= Storage
->Buffer
;
2062 Dst
= Storage
->EditBuffer
;
2065 if (ConfigRequest
!= NULL
) {
2066 Status
= mHiiConfigRouting
->BlockToConfig(
2074 if (EFI_ERROR (Status
)) {
2078 Status
= mHiiConfigRouting
->ConfigToBlock (
2085 if (Result
!= NULL
) {
2089 CopyMem (Dst
, Src
, BufferSize
);
2091 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2092 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2093 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2094 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2096 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2097 (ConfigRequest
== NULL
)) {
2098 if (SyncOrRestore
) {
2099 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2101 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2105 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2113 When discard the question value, call the callback function with Changed type
2114 to inform the hii driver.
2116 @param FormSet FormSet data structure.
2117 @param Form Form data structure.
2121 SendDiscardInfoToDriver (
2122 IN FORM_BROWSER_FORMSET
*FormSet
,
2123 IN FORM_BROWSER_FORM
*Form
2127 FORM_BROWSER_STATEMENT
*Question
;
2128 EFI_IFR_TYPE_VALUE
*TypeValue
;
2129 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2131 if (FormSet
->ConfigAccess
== NULL
) {
2135 Link
= GetFirstNode (&Form
->StatementListHead
);
2136 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2137 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2138 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2140 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2144 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2148 if (!Question
->ValueChanged
) {
2152 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2153 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2155 TypeValue
= &Question
->HiiValue
.Value
;
2158 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2159 FormSet
->ConfigAccess
->Callback (
2160 FormSet
->ConfigAccess
,
2161 EFI_BROWSER_ACTION_CHANGED
,
2162 Question
->QuestionId
,
2163 Question
->HiiValue
.Type
,
2171 Validate the FormSet. If the formset is not validate, remove it from the list.
2173 @param FormSet The input FormSet which need to validate.
2175 @retval TRUE The handle is validate.
2176 @retval FALSE The handle is invalidate.
2181 FORM_BROWSER_FORMSET
*FormSet
2184 EFI_HII_HANDLE
*HiiHandles
;
2188 ASSERT (FormSet
!= NULL
);
2191 // Get all the Hii handles
2193 HiiHandles
= HiiGetHiiHandles (NULL
);
2194 ASSERT (HiiHandles
!= NULL
);
2197 // Search for formset of each class type
2199 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2200 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2207 CleanBrowserStorage(FormSet
);
2208 RemoveEntryList (&FormSet
->Link
);
2209 DestroyFormSet (FormSet
);
2212 FreePool (HiiHandles
);
2217 Check whether need to enable the reset flag in form level.
2218 Also clean all ValueChanged flag in question.
2220 @param SetFlag Whether need to set the Reset Flag.
2221 @param Form Form data structure.
2227 IN FORM_BROWSER_FORM
*Form
2231 FORM_BROWSER_STATEMENT
*Question
;
2235 Link
= GetFirstNode (&Form
->StatementListHead
);
2236 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2237 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2239 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2240 gResetRequired
= TRUE
;
2243 if (Question
->ValueChanged
) {
2244 Question
->ValueChanged
= FALSE
;
2247 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2252 Check whether need to enable the reset flag.
2253 Also clean ValueChanged flag for all statements.
2255 Form level or formset level, only one.
2257 @param SetFlag Whether need to set the Reset Flag.
2258 @param FormSet FormSet data structure.
2259 @param Form Form data structure.
2263 ValueChangeResetFlagUpdate (
2265 IN FORM_BROWSER_FORMSET
*FormSet
,
2266 IN FORM_BROWSER_FORM
*Form
2269 FORM_BROWSER_FORM
*CurrentForm
;
2273 // Form != NULL means only check form level.
2276 UpdateFlagForForm(SetFlag
, Form
);
2280 Link
= GetFirstNode (&FormSet
->FormListHead
);
2281 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2282 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2283 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2285 UpdateFlagForForm(SetFlag
, CurrentForm
);
2290 Discard data based on the input setting scope (Form, FormSet or System).
2292 @param FormSet FormSet data structure.
2293 @param Form Form data structure.
2294 @param SettingScope Setting Scope for Discard action.
2296 @retval EFI_SUCCESS The function completed successfully.
2297 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2302 IN FORM_BROWSER_FORMSET
*FormSet
,
2303 IN FORM_BROWSER_FORM
*Form
,
2304 IN BROWSER_SETTING_SCOPE SettingScope
2308 FORMSET_STORAGE
*Storage
;
2309 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2310 FORM_BROWSER_FORMSET
*LocalFormSet
;
2311 FORM_BROWSER_FORMSET
*OldFormSet
;
2314 // Check the supported setting level.
2316 if (SettingScope
>= MaxLevel
) {
2317 return EFI_UNSUPPORTED
;
2320 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2322 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2323 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2324 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2325 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2327 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2332 // Skip if there is no RequestElement
2334 if (ConfigInfo
->ElementCount
== 0) {
2339 // Prepare <ConfigResp>
2341 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2344 // Call callback with Changed type to inform the driver.
2346 SendDiscardInfoToDriver (FormSet
, Form
);
2349 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2350 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2353 // Discard Buffer storage or Name/Value storage
2355 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2356 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2357 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2358 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2360 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2365 // Skip if there is no RequestElement
2367 if (Storage
->ElementCount
== 0) {
2371 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2374 Link
= GetFirstNode (&FormSet
->FormListHead
);
2375 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2376 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2377 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2380 // Call callback with Changed type to inform the driver.
2382 SendDiscardInfoToDriver (FormSet
, Form
);
2385 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2386 } else if (SettingScope
== SystemLevel
) {
2388 // System Level Discard.
2390 OldFormSet
= mSystemLevelFormSet
;
2393 // Discard changed value for each FormSet in the maintain list.
2395 Link
= GetFirstNode (&gBrowserFormSetList
);
2396 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2397 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2398 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2399 if (!ValidateFormSet(LocalFormSet
)) {
2403 mSystemLevelFormSet
= LocalFormSet
;
2405 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2406 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2408 // Remove maintain backup list after discard except for the current using FormSet.
2410 CleanBrowserStorage(LocalFormSet
);
2411 RemoveEntryList (&LocalFormSet
->Link
);
2412 DestroyFormSet (LocalFormSet
);
2416 mSystemLevelFormSet
= OldFormSet
;
2423 Submit data based on the input Setting level (Form, FormSet or System).
2425 @param FormSet FormSet data structure.
2426 @param Form Form data structure.
2427 @param SettingScope Setting Scope for Submit action.
2429 @retval EFI_SUCCESS The function completed successfully.
2430 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2435 IN FORM_BROWSER_FORMSET
*FormSet
,
2436 IN FORM_BROWSER_FORM
*Form
,
2437 IN BROWSER_SETTING_SCOPE SettingScope
2442 EFI_STRING ConfigResp
;
2443 EFI_STRING Progress
;
2444 BROWSER_STORAGE
*Storage
;
2445 FORMSET_STORAGE
*FormSetStorage
;
2446 FORM_BROWSER_FORMSET
*LocalFormSet
;
2447 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2450 // Check the supported setting level.
2452 if (SettingScope
>= MaxLevel
) {
2453 return EFI_UNSUPPORTED
;
2457 // Validate the Form by NoSubmit check
2459 Status
= EFI_SUCCESS
;
2460 if (SettingScope
== FormLevel
) {
2461 Status
= NoSubmitCheck (FormSet
, Form
);
2462 } else if (SettingScope
== FormSetLevel
) {
2463 Status
= NoSubmitCheck (FormSet
, NULL
);
2465 if (EFI_ERROR (Status
)) {
2469 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2471 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2472 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2473 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2474 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2476 Storage
= ConfigInfo
->Storage
;
2477 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2482 // Skip if there is no RequestElement
2484 if (ConfigInfo
->ElementCount
== 0) {
2489 // 1. Prepare <ConfigResp>
2491 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2492 if (EFI_ERROR (Status
)) {
2497 // 2. Set value to hii config routine protocol.
2499 Status
= mHiiConfigRouting
->RouteConfig (
2504 if (EFI_ERROR (Status
)) {
2505 FreePool (ConfigResp
);
2509 FreePool (ConfigResp
);
2511 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2513 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2517 // 4. Update the NV flag.
2519 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2520 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2522 // Submit Buffer storage or Name/Value storage
2524 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2525 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2526 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2527 Storage
= FormSetStorage
->BrowserStorage
;
2528 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2530 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2535 // Skip if there is no RequestElement
2537 if (FormSetStorage
->ElementCount
== 0) {
2542 // 1. Prepare <ConfigResp>
2544 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2545 if (EFI_ERROR (Status
)) {
2550 // 2. Send <ConfigResp> to Routine config Protocol.
2552 Status
= mHiiConfigRouting
->RouteConfig (
2557 if (EFI_ERROR (Status
)) {
2558 FreePool (ConfigResp
);
2562 FreePool (ConfigResp
);
2564 // 3. Config success, update storage shadow Buffer
2566 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2570 // 4. Update the NV flag.
2572 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2573 } else if (SettingScope
== SystemLevel
) {
2575 // System Level Save.
2579 // Save changed value for each FormSet in the maintain list.
2581 Link
= GetFirstNode (&gBrowserFormSetList
);
2582 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2583 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2584 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2585 if (!ValidateFormSet(LocalFormSet
)) {
2588 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2589 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2591 // Remove maintain backup list after save except for the current using FormSet.
2593 CleanBrowserStorage(LocalFormSet
);
2594 RemoveEntryList (&LocalFormSet
->Link
);
2595 DestroyFormSet (LocalFormSet
);
2604 Get Question default value from AltCfg string.
2606 @param FormSet The form set.
2607 @param Question The question.
2608 @param DefaultId The default Id.
2610 @retval EFI_SUCCESS Question is reset to default value.
2614 GetDefaultValueFromAltCfg (
2615 IN FORM_BROWSER_FORMSET
*FormSet
,
2616 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2620 BOOLEAN IsBufferStorage
;
2623 BROWSER_STORAGE
*Storage
;
2624 CHAR16
*ConfigRequest
;
2637 Status
= EFI_NOT_FOUND
;
2640 ConfigRequest
= NULL
;
2644 Storage
= Question
->Storage
;
2646 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2651 // Question Value is provided by Buffer Storage or NameValue Storage
2653 if (Question
->BufferValue
!= NULL
) {
2655 // This Question is password or orderedlist
2657 Dst
= Question
->BufferValue
;
2660 // Other type of Questions
2662 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2665 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2666 IsBufferStorage
= TRUE
;
2668 IsBufferStorage
= FALSE
;
2670 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2673 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2674 // <ConfigHdr> + "&" + <VariableName>
2676 if (IsBufferStorage
) {
2677 Length
= StrLen (Storage
->ConfigHdr
);
2678 Length
+= StrLen (Question
->BlockName
);
2680 Length
= StrLen (Storage
->ConfigHdr
);
2681 Length
+= StrLen (Question
->VariableName
) + 1;
2683 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2684 ASSERT (ConfigRequest
!= NULL
);
2686 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2687 if (IsBufferStorage
) {
2688 StrCat (ConfigRequest
, Question
->BlockName
);
2690 StrCat (ConfigRequest
, L
"&");
2691 StrCat (ConfigRequest
, Question
->VariableName
);
2694 Status
= mHiiConfigRouting
->ExtractConfig (
2700 if (EFI_ERROR (Status
)) {
2705 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2706 // Get the default configuration string according to the default ID.
2708 Status
= mHiiConfigRouting
->GetAltConfig (
2714 &DefaultId
, // it can be NULL to get the current setting.
2719 // The required setting can't be found. So, it is not required to be validated and set.
2721 if (EFI_ERROR (Status
)) {
2725 if (ConfigResp
== NULL
) {
2726 Status
= EFI_NOT_FOUND
;
2731 // Skip <ConfigRequest>
2733 if (IsBufferStorage
) {
2734 Value
= StrStr (ConfigResp
, L
"&VALUE");
2735 ASSERT (Value
!= NULL
);
2741 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2742 ASSERT (Value
!= NULL
);
2744 Value
= Value
+ StrLen (Question
->VariableName
);
2746 if (*Value
!= '=') {
2747 Status
= EFI_NOT_FOUND
;
2751 // Skip '=', point to value
2756 // Suppress <AltResp> if any
2759 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2764 LengthStr
= StrLen (Value
);
2765 if (!IsBufferStorage
&& IsString
) {
2766 StringPtr
= (CHAR16
*) Dst
;
2767 ZeroMem (TemStr
, sizeof (TemStr
));
2768 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2769 StrnCpy (TemStr
, Value
+ Index
, 4);
2770 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2773 // Add tailing L'\0' character
2775 StringPtr
[Index
/4] = L
'\0';
2777 ZeroMem (TemStr
, sizeof (TemStr
));
2778 for (Index
= 0; Index
< LengthStr
; Index
++) {
2779 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2780 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2781 if ((Index
& 1) == 0) {
2782 Dst
[Index
/2] = DigitUint8
;
2784 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2790 if (ConfigRequest
!= NULL
){
2791 FreePool (ConfigRequest
);
2794 if (ConfigResp
!= NULL
) {
2795 FreePool (ConfigResp
);
2798 if (Result
!= NULL
) {
2806 Get default Id value used for browser.
2808 @param DefaultId The default id value used by hii.
2810 @retval Browser used default value.
2814 GetDefaultIdForCallBack (
2818 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2819 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2820 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2821 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2822 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2823 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2824 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2825 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2826 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2827 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2828 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2829 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2838 Return data element in an Array by its Index.
2840 @param Array The data array.
2841 @param Type Type of the data in this array.
2842 @param Index Zero based index for data in this array.
2844 @retval Value The data to be returned
2856 ASSERT (Array
!= NULL
);
2860 case EFI_IFR_TYPE_NUM_SIZE_8
:
2861 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
2864 case EFI_IFR_TYPE_NUM_SIZE_16
:
2865 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
2868 case EFI_IFR_TYPE_NUM_SIZE_32
:
2869 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
2872 case EFI_IFR_TYPE_NUM_SIZE_64
:
2873 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
2885 Set value of a data element in an Array by its Index.
2887 @param Array The data array.
2888 @param Type Type of the data in this array.
2889 @param Index Zero based index for data in this array.
2890 @param Value The value to be set.
2902 ASSERT (Array
!= NULL
);
2905 case EFI_IFR_TYPE_NUM_SIZE_8
:
2906 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
2909 case EFI_IFR_TYPE_NUM_SIZE_16
:
2910 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
2913 case EFI_IFR_TYPE_NUM_SIZE_32
:
2914 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
2917 case EFI_IFR_TYPE_NUM_SIZE_64
:
2918 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
2927 Search an Option of a Question by its value.
2929 @param Question The Question
2930 @param OptionValue Value for Option to be searched.
2932 @retval Pointer Pointer to the found Option.
2933 @retval NULL Option not found.
2938 IN FORM_BROWSER_STATEMENT
*Question
,
2939 IN EFI_HII_VALUE
*OptionValue
2943 QUESTION_OPTION
*Option
;
2946 Link
= GetFirstNode (&Question
->OptionListHead
);
2947 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2948 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2950 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
2952 // Check the suppressif condition, only a valid option can be return.
2954 if ((Option
->SuppressExpression
== NULL
) ||
2955 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
2960 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2968 Reset Question to its default value.
2970 @param FormSet The form set.
2971 @param Form The form.
2972 @param Question The question.
2973 @param DefaultId The Class of the default.
2975 @retval EFI_SUCCESS Question is reset to default value.
2979 GetQuestionDefault (
2980 IN FORM_BROWSER_FORMSET
*FormSet
,
2981 IN FORM_BROWSER_FORM
*Form
,
2982 IN FORM_BROWSER_STATEMENT
*Question
,
2988 QUESTION_DEFAULT
*Default
;
2989 QUESTION_OPTION
*Option
;
2990 EFI_HII_VALUE
*HiiValue
;
2992 EFI_STRING StrValue
;
2993 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2994 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2998 Status
= EFI_NOT_FOUND
;
3002 // Statement don't have storage, skip them
3004 if (Question
->QuestionId
== 0) {
3009 // There are Five ways to specify default value for a Question:
3010 // 1, use call back function (highest priority)
3011 // 2, use ExtractConfig function
3012 // 3, use nested EFI_IFR_DEFAULT
3013 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3014 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3016 HiiValue
= &Question
->HiiValue
;
3019 // Get Question defaut value from call back function.
3021 ConfigAccess
= FormSet
->ConfigAccess
;
3022 Action
= GetDefaultIdForCallBack (DefaultId
);
3023 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3024 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3025 Status
= ConfigAccess
->Callback (
3028 Question
->QuestionId
,
3033 if (!EFI_ERROR (Status
)) {
3034 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3035 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3036 ASSERT (NewString
!= NULL
);
3038 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3039 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3040 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3042 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3045 FreePool (NewString
);
3052 // Get default value from altcfg string.
3054 if (ConfigAccess
!= NULL
) {
3055 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3056 if (!EFI_ERROR (Status
)) {
3062 // EFI_IFR_DEFAULT has highest priority
3064 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3065 Link
= GetFirstNode (&Question
->DefaultListHead
);
3066 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3067 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3069 if (Default
->DefaultId
== DefaultId
) {
3070 if (Default
->ValueExpression
!= NULL
) {
3072 // Default is provided by an Expression, evaluate it
3074 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3075 if (EFI_ERROR (Status
)) {
3079 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3080 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3081 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3082 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3083 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3085 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3086 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3088 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3090 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3091 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3094 // Default value is embedded in EFI_IFR_DEFAULT
3096 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3099 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3100 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3101 if (StrValue
== NULL
) {
3102 return EFI_NOT_FOUND
;
3104 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3105 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3107 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3114 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3119 // EFI_ONE_OF_OPTION
3121 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3122 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3124 // OneOfOption could only provide Standard and Manufacturing default
3126 Link
= GetFirstNode (&Question
->OptionListHead
);
3127 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3128 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3129 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3131 if ((Option
->SuppressExpression
!= NULL
) &&
3132 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3136 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3137 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3139 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3148 // EFI_IFR_CHECKBOX - lowest priority
3150 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3151 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3153 // Checkbox could only provide Standard and Manufacturing default
3155 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3156 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3158 HiiValue
->Value
.b
= TRUE
;
3160 HiiValue
->Value
.b
= FALSE
;
3168 // For Questions without default
3170 Status
= EFI_NOT_FOUND
;
3171 switch (Question
->Operand
) {
3172 case EFI_IFR_NUMERIC_OP
:
3174 // Take minimum value as numeric default value
3176 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3177 HiiValue
->Value
.u64
= Question
->Minimum
;
3178 Status
= EFI_SUCCESS
;
3182 case EFI_IFR_ONE_OF_OP
:
3184 // Take first oneof option as oneof's default value
3186 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3187 Link
= GetFirstNode (&Question
->OptionListHead
);
3188 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3189 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3190 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3192 if ((Option
->SuppressExpression
!= NULL
) &&
3193 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3197 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3198 Status
= EFI_SUCCESS
;
3204 case EFI_IFR_ORDERED_LIST_OP
:
3206 // Take option sequence in IFR as ordered list's default value
3209 Link
= GetFirstNode (&Question
->OptionListHead
);
3210 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3211 Status
= EFI_SUCCESS
;
3212 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3213 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3215 if ((Option
->SuppressExpression
!= NULL
) &&
3216 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3220 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3223 if (Index
>= Question
->MaxContainers
) {
3238 Reset Questions to their initial value or default value in a Form, Formset or System.
3240 GetDefaultValueScope parameter decides which questions will reset
3241 to its default value.
3243 @param FormSet FormSet data structure.
3244 @param Form Form data structure.
3245 @param DefaultId The Class of the default.
3246 @param SettingScope Setting Scope for Default action.
3247 @param GetDefaultValueScope Get default value scope.
3248 @param Storage Get default value only for this storage.
3249 @param RetrieveValueFirst Whether call the retrieve call back to
3250 get the initial value before get default
3253 @retval EFI_SUCCESS The function completed successfully.
3254 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3259 IN FORM_BROWSER_FORMSET
*FormSet
,
3260 IN FORM_BROWSER_FORM
*Form
,
3261 IN UINT16 DefaultId
,
3262 IN BROWSER_SETTING_SCOPE SettingScope
,
3263 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3264 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3265 IN BOOLEAN RetrieveValueFirst
3269 LIST_ENTRY
*FormLink
;
3271 FORM_BROWSER_STATEMENT
*Question
;
3272 FORM_BROWSER_FORMSET
*LocalFormSet
;
3273 FORM_BROWSER_FORMSET
*OldFormSet
;
3275 Status
= EFI_SUCCESS
;
3278 // Check the supported setting level.
3280 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3281 return EFI_UNSUPPORTED
;
3284 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3285 return EFI_UNSUPPORTED
;
3288 if (SettingScope
== FormLevel
) {
3290 // Extract Form default
3292 Link
= GetFirstNode (&Form
->StatementListHead
);
3293 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3294 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3295 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3298 // If get default value only for this storage, check the storage first.
3300 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3305 // If get default value only for no storage question, just skip the question which has storage.
3307 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3312 // If Question is disabled, don't reset it to default
3314 if (Question
->Expression
!= NULL
) {
3315 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3320 if (RetrieveValueFirst
) {
3322 // Call the Retrieve call back to get the initial question value.
3324 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
3328 // If not request to get the initial value or get initial value fail, then get default value.
3330 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3331 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3332 if (EFI_ERROR (Status
)) {
3338 // Synchronize Buffer storage's Edit buffer
3340 if ((Question
->Storage
!= NULL
) &&
3341 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3342 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3345 } else if (SettingScope
== FormSetLevel
) {
3346 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3347 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3348 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3349 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3350 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3352 } else if (SettingScope
== SystemLevel
) {
3354 // Preload all Hii formset.
3356 LoadAllHiiFormset();
3358 OldFormSet
= mSystemLevelFormSet
;
3361 // Set Default Value for each FormSet in the maintain list.
3363 Link
= GetFirstNode (&gBrowserFormSetList
);
3364 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3365 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3366 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3367 if (!ValidateFormSet(LocalFormSet
)) {
3371 mSystemLevelFormSet
= LocalFormSet
;
3373 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3376 mSystemLevelFormSet
= OldFormSet
;
3384 Validate whether this question's value has changed.
3386 @param FormSet FormSet data structure.
3387 @param Form Form data structure.
3388 @param Question Question to be initialized.
3389 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3391 @retval TRUE Question's value has changed.
3392 @retval FALSE Question's value has not changed
3396 IsQuestionValueChanged (
3397 IN FORM_BROWSER_FORMSET
*FormSet
,
3398 IN FORM_BROWSER_FORM
*Form
,
3399 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3400 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3403 EFI_HII_VALUE BackUpValue
;
3404 CHAR8
*BackUpBuffer
;
3406 BOOLEAN ValueChanged
;
3410 // For quetion without storage, always mark it as data not changed.
3412 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3416 BackUpBuffer
= NULL
;
3417 ValueChanged
= FALSE
;
3419 switch (Question
->Operand
) {
3420 case EFI_IFR_ORDERED_LIST_OP
:
3421 BufferWidth
= Question
->StorageWidth
;
3422 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3423 ASSERT (BackUpBuffer
!= NULL
);
3426 case EFI_IFR_STRING_OP
:
3427 case EFI_IFR_PASSWORD_OP
:
3428 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3429 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3430 ASSERT (BackUpBuffer
!= NULL
);
3437 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3439 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3440 ASSERT_EFI_ERROR(Status
);
3442 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3443 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3444 ValueChanged
= TRUE
;
3447 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3448 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3450 if (BackUpBuffer
!= NULL
) {
3451 FreePool (BackUpBuffer
);
3454 Question
->ValueChanged
= ValueChanged
;
3456 return ValueChanged
;
3460 Initialize Question's Edit copy from Storage.
3462 @param Selection Selection contains the information about
3463 the Selection, form and formset to be displayed.
3464 Selection action may be updated in retrieve callback.
3465 If Selection is NULL, only initialize Question value.
3466 @param FormSet FormSet data structure.
3467 @param Form Form data structure.
3469 @retval EFI_SUCCESS The function completed successfully.
3474 IN OUT UI_MENU_SELECTION
*Selection
,
3475 IN FORM_BROWSER_FORMSET
*FormSet
,
3476 IN FORM_BROWSER_FORM
*Form
3481 FORM_BROWSER_STATEMENT
*Question
;
3485 Link
= GetFirstNode (&Form
->StatementListHead
);
3486 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3487 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3490 // Initialize local copy of Value for each Question
3492 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3493 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3495 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3497 if (EFI_ERROR (Status
)) {
3501 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3502 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3506 // Call the Retrieve call back function for all questions.
3508 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3509 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
3510 !gFinishRetrieveCall
) {
3512 // Check QuestionValue does exist.
3514 StorageWidth
= Question
->StorageWidth
;
3515 if (Question
->BufferValue
!= NULL
) {
3516 BufferValue
= Question
->BufferValue
;
3518 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3522 // For efivarstore storage, initial question value first.
3524 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3525 Status
= gRT
->GetVariable (
3526 Question
->VariableName
,
3527 &Question
->Storage
->Guid
,
3534 Status
= ProcessCallBackFunction(Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3537 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3544 Initialize Question's Edit copy from Storage for the whole Formset.
3546 @param Selection Selection contains the information about
3547 the Selection, form and formset to be displayed.
3548 Selection action may be updated in retrieve callback.
3549 If Selection is NULL, only initialize Question value.
3550 @param FormSet FormSet data structure.
3552 @retval EFI_SUCCESS The function completed successfully.
3557 IN OUT UI_MENU_SELECTION
*Selection
,
3558 IN FORM_BROWSER_FORMSET
*FormSet
3563 FORM_BROWSER_FORM
*Form
;
3565 Link
= GetFirstNode (&FormSet
->FormListHead
);
3566 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3567 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3570 // Initialize local copy of Value for each Form
3572 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3573 if (EFI_ERROR (Status
)) {
3577 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3581 // Finished question initialization.
3583 FormSet
->QuestionInited
= TRUE
;
3589 Remove the Request element from the Config Request.
3591 @param Storage Pointer to the browser storage.
3592 @param RequestElement The pointer to the Request element.
3597 IN OUT BROWSER_STORAGE
*Storage
,
3598 IN CHAR16
*RequestElement
3604 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3606 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3608 if (NewStr
== NULL
) {
3613 // Remove this element from this ConfigRequest.
3616 NewStr
+= StrLen (RequestElement
);
3617 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3619 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3623 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3625 @param Storage Pointer to the browser storage.
3626 @param ConfigRequest The pointer to the Request element.
3630 RemoveConfigRequest (
3631 BROWSER_STORAGE
*Storage
,
3632 CHAR16
*ConfigRequest
3635 CHAR16
*RequestElement
;
3636 CHAR16
*NextRequestElement
;
3640 // No request element in it, just return.
3642 if (ConfigRequest
== NULL
) {
3646 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3648 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3653 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3655 SearchKey
= L
"&OFFSET";
3659 // Find SearchKey storage
3661 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3662 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3663 ASSERT (RequestElement
!= NULL
);
3664 RequestElement
= StrStr (RequestElement
, SearchKey
);
3666 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3669 while (RequestElement
!= NULL
) {
3671 // +1 to avoid find header itself.
3673 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3676 // The last Request element in configRequest string.
3678 if (NextRequestElement
!= NULL
) {
3680 // Replace "&" with '\0'.
3682 *NextRequestElement
= L
'\0';
3685 RemoveElement (Storage
, RequestElement
);
3687 if (NextRequestElement
!= NULL
) {
3689 // Restore '&' with '\0' for later used.
3691 *NextRequestElement
= L
'&';
3694 RequestElement
= NextRequestElement
;
3698 // If no request element remain, just remove the ConfigRequest string.
3700 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3701 FreePool (Storage
->ConfigRequest
);
3702 Storage
->ConfigRequest
= NULL
;
3703 Storage
->SpareStrLen
= 0;
3708 Base on the current formset info, clean the ConfigRequest string in browser storage.
3710 @param FormSet Pointer of the FormSet
3714 CleanBrowserStorage (
3715 IN OUT FORM_BROWSER_FORMSET
*FormSet
3719 FORMSET_STORAGE
*Storage
;
3721 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3722 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3723 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3724 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3726 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3727 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3731 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
3732 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3733 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3734 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
3735 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
3736 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
3738 Storage
->BrowserStorage
->Initialized
= FALSE
;
3744 Check whether current element in the ConfigReqeust string.
3746 @param BrowserStorage Storage which includes ConfigReqeust.
3747 @param RequestElement New element need to check.
3749 @retval TRUE The Element is in the ConfigReqeust string.
3750 @retval FALSE The Element not in the configReqeust String.
3755 BROWSER_STORAGE
*BrowserStorage
,
3756 CHAR16
*RequestElement
3759 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3763 Append the Request element to the Config Request.
3765 @param ConfigRequest Current ConfigRequest info.
3766 @param SpareStrLen Current remain free buffer for config reqeust.
3767 @param RequestElement New Request element.
3771 AppendConfigRequest (
3772 IN OUT CHAR16
**ConfigRequest
,
3773 IN OUT UINTN
*SpareStrLen
,
3774 IN CHAR16
*RequestElement
3781 StrLength
= StrLen (RequestElement
);
3784 // Append <RequestElement> to <ConfigRequest>
3786 if (StrLength
> *SpareStrLen
) {
3788 // Old String buffer is not sufficient for RequestElement, allocate a new one
3790 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3791 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3792 ASSERT (NewStr
!= NULL
);
3794 if (*ConfigRequest
!= NULL
) {
3795 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3796 FreePool (*ConfigRequest
);
3798 *ConfigRequest
= NewStr
;
3799 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3802 StrCat (*ConfigRequest
, RequestElement
);
3803 *SpareStrLen
-= StrLength
;
3807 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3809 @param Storage Form set Storage.
3810 @param Request The input request string.
3811 @param RespString Whether the input is ConfigRequest or ConfigResp format.
3813 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3814 @retval FALSE All elements covered by current used elements.
3818 ConfigRequestAdjust (
3819 IN BROWSER_STORAGE
*Storage
,
3821 IN BOOLEAN RespString
3824 CHAR16
*RequestElement
;
3825 CHAR16
*NextRequestElement
;
3826 CHAR16
*NextElementBakup
;
3831 CHAR16
*ConfigRequest
;
3835 NextElementBakup
= NULL
;
3838 if (Request
!= NULL
) {
3839 ConfigRequest
= Request
;
3841 ConfigRequest
= Storage
->ConfigRequest
;
3844 if (Storage
->ConfigRequest
== NULL
) {
3845 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3849 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3851 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3856 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3858 SearchKey
= L
"&OFFSET";
3859 ValueKey
= L
"&VALUE";
3863 // Find SearchKey storage
3865 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3866 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3867 ASSERT (RequestElement
!= NULL
);
3868 RequestElement
= StrStr (RequestElement
, SearchKey
);
3870 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3873 while (RequestElement
!= NULL
) {
3876 // +1 to avoid find header itself.
3878 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3881 // The last Request element in configRequest string.
3883 if (NextRequestElement
!= NULL
) {
3884 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3885 NextElementBakup
= NextRequestElement
;
3886 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3887 ASSERT (NextRequestElement
!= NULL
);
3890 // Replace "&" with '\0'.
3892 *NextRequestElement
= L
'\0';
3894 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3895 NextElementBakup
= NextRequestElement
;
3896 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3897 ASSERT (NextRequestElement
!= NULL
);
3899 // Replace "&" with '\0'.
3901 *NextRequestElement
= L
'\0';
3905 if (!ElementValidation (Storage
, RequestElement
)) {
3907 // Add this element to the Storage->BrowserStorage->AllRequestElement.
3909 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
3913 if (NextRequestElement
!= NULL
) {
3915 // Restore '&' with '\0' for later used.
3917 *NextRequestElement
= L
'&';
3920 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3921 RequestElement
= NextElementBakup
;
3923 RequestElement
= NextRequestElement
;
3932 Base on ConfigRequest info to get default value for current formset.
3934 ConfigRequest info include the info about which questions in current formset need to
3935 get default value. This function only get these questions default value.
3937 @param FormSet FormSet data structure.
3938 @param Storage Storage need to update value.
3939 @param ConfigRequest The config request string.
3943 GetDefaultForFormset (
3944 IN FORM_BROWSER_FORMSET
*FormSet
,
3945 IN BROWSER_STORAGE
*Storage
,
3946 IN CHAR16
*ConfigRequest
3951 LIST_ENTRY BackUpList
;
3952 NAME_VALUE_NODE
*Node
;
3954 LIST_ENTRY
*NodeLink
;
3955 NAME_VALUE_NODE
*TmpNode
;
3957 EFI_STRING Progress
;
3961 InitializeListHead(&BackUpList
);
3964 // Back update the edit buffer.
3966 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3967 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3968 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
3969 ASSERT (BackUpBuf
!= NULL
);
3970 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3971 Link
= GetFirstNode (&Storage
->NameValueListHead
);
3972 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
3973 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3974 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
3977 // Only back Node belong to this formset.
3979 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
3983 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
3984 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
3985 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
3987 InsertTailList(&BackUpList
, &TmpNode
->Link
);
3992 // Get default value.
3994 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3997 // Update the question value based on the input ConfigRequest.
3999 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4000 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4001 ASSERT (BackUpBuf
!= NULL
);
4002 BufferSize
= Storage
->Size
;
4003 Status
= mHiiConfigRouting
->BlockToConfig(
4006 Storage
->EditBuffer
,
4011 ASSERT_EFI_ERROR (Status
);
4013 Status
= mHiiConfigRouting
->ConfigToBlock (
4020 ASSERT_EFI_ERROR (Status
);
4022 if (Result
!= NULL
) {
4026 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4027 FreePool (BackUpBuf
);
4028 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4030 // Update question value, only element in ConfigReqeust will be update.
4032 Link
= GetFirstNode (&BackUpList
);
4033 while (!IsNull (&BackUpList
, Link
)) {
4034 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4035 Link
= GetNextNode (&BackUpList
, Link
);
4037 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4041 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4042 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4043 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4044 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4046 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4050 FreePool (TmpNode
->EditValue
);
4051 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4053 RemoveEntryList (&Node
->Link
);
4054 FreePool (Node
->EditValue
);
4055 FreePool (Node
->Name
);
4061 // Restore the Name/Value node.
4063 Link
= GetFirstNode (&BackUpList
);
4064 while (!IsNull (&BackUpList
, Link
)) {
4065 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4066 Link
= GetNextNode (&BackUpList
, Link
);
4071 RemoveEntryList (&Node
->Link
);
4072 FreePool (Node
->EditValue
);
4073 FreePool (Node
->Name
);
4080 Fill storage's edit copy with settings requested from Configuration Driver.
4082 @param FormSet FormSet data structure.
4083 @param Storage Buffer Storage.
4088 IN FORM_BROWSER_FORMSET
*FormSet
,
4089 IN FORMSET_STORAGE
*Storage
4093 EFI_STRING Progress
;
4096 EFI_STRING ConfigRequest
;
4099 ConfigRequest
= NULL
;
4101 switch (Storage
->BrowserStorage
->Type
) {
4102 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4105 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4106 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4107 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4112 case EFI_HII_VARSTORE_BUFFER
:
4113 case EFI_HII_VARSTORE_NAME_VALUE
:
4115 // Skip if there is no RequestElement.
4117 if (Storage
->ElementCount
== 0) {
4122 // Just update the ConfigRequest, if storage already initialized.
4124 if (Storage
->BrowserStorage
->Initialized
) {
4125 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4129 Storage
->BrowserStorage
->Initialized
= TRUE
;
4136 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4138 // Create the config request string to get all fields for this storage.
4139 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4140 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4142 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4143 ConfigRequest
= AllocateZeroPool (StrLen
);
4144 ASSERT (ConfigRequest
!= NULL
);
4148 L
"%s&OFFSET=0&WIDTH=%04x",
4149 Storage
->BrowserStorage
->ConfigHdr
,
4150 Storage
->BrowserStorage
->Size
);
4152 ConfigRequest
= Storage
->ConfigRequest
;
4156 // Request current settings from Configuration Driver
4158 Status
= mHiiConfigRouting
->ExtractConfig (
4166 // If get value fail, extract default from IFR binary
4168 if (EFI_ERROR (Status
)) {
4169 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4172 // Convert Result from <ConfigAltResp> to <ConfigResp>
4174 StrPtr
= StrStr (Result
, L
"&GUID=");
4175 if (StrPtr
!= NULL
) {
4179 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4183 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4186 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4188 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4190 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4191 if (ConfigRequest
!= NULL
) {
4192 FreePool (ConfigRequest
);
4198 Get Value changed status from old question.
4200 @param NewFormSet FormSet data structure.
4201 @param OldQuestion Old question which has value changed.
4205 SyncStatusForQuestion (
4206 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4207 IN FORM_BROWSER_STATEMENT
*OldQuestion
4211 LIST_ENTRY
*QuestionLink
;
4212 FORM_BROWSER_FORM
*Form
;
4213 FORM_BROWSER_STATEMENT
*Question
;
4216 // For each form in one formset.
4218 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4219 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4220 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4221 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
4224 // for each question in one form.
4226 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4227 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4228 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4229 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4231 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
4232 Question
->ValueChanged
= TRUE
;
4240 Get Value changed status from old formset.
4242 @param NewFormSet FormSet data structure.
4243 @param OldFormSet FormSet data structure.
4247 SyncStatusForFormSet (
4248 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4249 IN FORM_BROWSER_FORMSET
*OldFormSet
4253 LIST_ENTRY
*QuestionLink
;
4254 FORM_BROWSER_FORM
*Form
;
4255 FORM_BROWSER_STATEMENT
*Question
;
4258 // For each form in one formset.
4260 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
4261 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
4262 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4263 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
4266 // for each question in one form.
4268 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4269 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4270 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4271 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4273 if (!Question
->ValueChanged
) {
4278 // Find the same question in new formset and update the value changed flag.
4280 SyncStatusForQuestion (NewFormSet
, Question
);
4286 Get current setting of Questions.
4288 @param FormSet FormSet data structure.
4292 InitializeCurrentSetting (
4293 IN OUT FORM_BROWSER_FORMSET
*FormSet
4297 FORMSET_STORAGE
*Storage
;
4298 FORM_BROWSER_FORMSET
*OldFormSet
;
4301 // Try to find pre FormSet in the maintain backup list.
4302 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4304 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4305 if (OldFormSet
!= NULL
) {
4306 SyncStatusForFormSet (FormSet
, OldFormSet
);
4307 RemoveEntryList (&OldFormSet
->Link
);
4308 DestroyFormSet (OldFormSet
);
4310 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4313 // Extract default from IFR binary for no storage questions.
4315 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4318 // Request current settings from Configuration Driver
4320 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4321 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4322 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4324 LoadStorage (FormSet
, Storage
);
4326 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4332 Fetch the Ifr binary data of a FormSet.
4334 @param Handle PackageList Handle
4335 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4336 specified (NULL or zero GUID), take the first
4337 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4338 found in package list.
4339 On output, GUID of the formset found(if not NULL).
4340 @param BinaryLength The length of the FormSet IFR binary.
4341 @param BinaryData The buffer designed to receive the FormSet.
4343 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4344 BufferLength was updated.
4345 @retval EFI_INVALID_PARAMETER The handle is unknown.
4346 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4347 be found with the requested FormId.
4352 IN EFI_HII_HANDLE Handle
,
4353 IN OUT EFI_GUID
*FormSetGuid
,
4354 OUT UINTN
*BinaryLength
,
4355 OUT UINT8
**BinaryData
4359 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4365 UINT32 PackageListLength
;
4366 EFI_HII_PACKAGE_HEADER PackageHeader
;
4368 UINT8 NumberOfClassGuid
;
4369 BOOLEAN ClassGuidMatch
;
4370 EFI_GUID
*ClassGuid
;
4371 EFI_GUID
*ComparingGuid
;
4375 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4378 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4380 if (FormSetGuid
== NULL
) {
4381 ComparingGuid
= &gZeroGuid
;
4383 ComparingGuid
= FormSetGuid
;
4387 // Get HII PackageList
4390 HiiPackageList
= NULL
;
4391 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4392 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4393 HiiPackageList
= AllocatePool (BufferSize
);
4394 ASSERT (HiiPackageList
!= NULL
);
4396 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4398 if (EFI_ERROR (Status
)) {
4401 ASSERT (HiiPackageList
!= NULL
);
4404 // Get Form package from this HII package List
4406 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4408 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4410 ClassGuidMatch
= FALSE
;
4411 while (Offset
< PackageListLength
) {
4412 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4413 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4415 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4417 // Search FormSet in this Form Package
4419 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4420 while (Offset2
< PackageHeader
.Length
) {
4421 OpCodeData
= Package
+ Offset2
;
4423 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4425 // Try to compare against formset GUID
4427 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4428 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4432 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4434 // Try to compare against formset class GUID
4436 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4437 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4438 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4439 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4440 ClassGuidMatch
= TRUE
;
4444 if (ClassGuidMatch
) {
4447 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4448 ClassGuidMatch
= TRUE
;
4453 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4456 if (Offset2
< PackageHeader
.Length
) {
4458 // Target formset found
4464 Offset
+= PackageHeader
.Length
;
4467 if (Offset
>= PackageListLength
) {
4469 // Form package not found in this Package List
4471 FreePool (HiiPackageList
);
4472 return EFI_NOT_FOUND
;
4475 if (FormSetGuid
!= NULL
) {
4477 // Return the FormSet GUID
4479 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4483 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4484 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4485 // of the Form Package.
4487 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4488 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4490 FreePool (HiiPackageList
);
4492 if (*BinaryData
== NULL
) {
4493 return EFI_OUT_OF_RESOURCES
;
4501 Initialize the internal data structure of a FormSet.
4503 @param Handle PackageList Handle
4504 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4505 specified (NULL or zero GUID), take the first
4506 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4507 found in package list.
4508 On output, GUID of the formset found(if not NULL).
4509 @param FormSet FormSet data structure.
4511 @retval EFI_SUCCESS The function completed successfully.
4512 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4517 IN EFI_HII_HANDLE Handle
,
4518 IN OUT EFI_GUID
*FormSetGuid
,
4519 OUT FORM_BROWSER_FORMSET
*FormSet
4523 EFI_HANDLE DriverHandle
;
4525 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4526 if (EFI_ERROR (Status
)) {
4530 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4531 FormSet
->HiiHandle
= Handle
;
4532 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4533 FormSet
->QuestionInited
= FALSE
;
4536 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4538 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4539 if (EFI_ERROR (Status
)) {
4542 FormSet
->DriverHandle
= DriverHandle
;
4543 Status
= gBS
->HandleProtocol (
4545 &gEfiHiiConfigAccessProtocolGuid
,
4546 (VOID
**) &FormSet
->ConfigAccess
4548 if (EFI_ERROR (Status
)) {
4550 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4551 // list, then there will be no configuration action required
4553 FormSet
->ConfigAccess
= NULL
;
4557 // Parse the IFR binary OpCodes
4559 Status
= ParseOpCodes (FormSet
);
4566 Save globals used by previous call to SendForm(). SendForm() may be called from
4567 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4568 So, save globals of previous call to SendForm() and restore them upon exit.
4572 SaveBrowserContext (
4576 BROWSER_CONTEXT
*Context
;
4577 FORM_ENTRY_INFO
*MenuList
;
4579 gBrowserContextCount
++;
4580 if (gBrowserContextCount
== 1) {
4582 // This is not reentry of SendForm(), no context to save
4587 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4588 ASSERT (Context
!= NULL
);
4590 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4593 // Save FormBrowser context
4595 Context
->Selection
= gCurrentSelection
;
4596 Context
->ResetRequired
= gResetRequired
;
4597 Context
->ExitRequired
= gExitRequired
;
4598 Context
->HiiHandle
= mCurrentHiiHandle
;
4599 Context
->FormId
= mCurrentFormId
;
4600 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4603 // Save the menu history data.
4605 InitializeListHead(&Context
->FormHistoryList
);
4606 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4607 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4608 RemoveEntryList (&MenuList
->Link
);
4610 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4614 // Insert to FormBrowser context list
4616 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4621 Restore globals used by previous call to SendForm().
4625 RestoreBrowserContext (
4630 BROWSER_CONTEXT
*Context
;
4631 FORM_ENTRY_INFO
*MenuList
;
4633 ASSERT (gBrowserContextCount
!= 0);
4634 gBrowserContextCount
--;
4635 if (gBrowserContextCount
== 0) {
4637 // This is not reentry of SendForm(), no context to restore
4642 ASSERT (!IsListEmpty (&gBrowserContextList
));
4644 Link
= GetFirstNode (&gBrowserContextList
);
4645 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4648 // Restore FormBrowser context
4650 gCurrentSelection
= Context
->Selection
;
4651 gResetRequired
= Context
->ResetRequired
;
4652 gExitRequired
= Context
->ExitRequired
;
4653 mCurrentHiiHandle
= Context
->HiiHandle
;
4654 mCurrentFormId
= Context
->FormId
;
4655 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4658 // Restore the menu history data.
4660 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4661 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4662 RemoveEntryList (&MenuList
->Link
);
4664 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4668 // Remove from FormBrowser context list
4670 RemoveEntryList (&Context
->Link
);
4671 gBS
->FreePool (Context
);
4675 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4677 @param Handle The Hii Handle.
4679 @return the found FormSet context. If no found, NULL will return.
4682 FORM_BROWSER_FORMSET
*
4683 GetFormSetFromHiiHandle (
4684 EFI_HII_HANDLE Handle
4688 FORM_BROWSER_FORMSET
*FormSet
;
4690 Link
= GetFirstNode (&gBrowserFormSetList
);
4691 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4692 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4693 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4694 if (!ValidateFormSet(FormSet
)) {
4697 if (FormSet
->HiiHandle
== Handle
) {
4706 Check whether the input HII handle is the FormSet that is being used.
4708 @param Handle The Hii Handle.
4710 @retval TRUE HII handle is being used.
4711 @retval FALSE HII handle is not being used.
4715 IsHiiHandleInBrowserContext (
4716 EFI_HII_HANDLE Handle
4720 BROWSER_CONTEXT
*Context
;
4723 // HiiHandle is Current FormSet.
4725 if (mCurrentHiiHandle
== Handle
) {
4730 // Check whether HiiHandle is in BrowserContext.
4732 Link
= GetFirstNode (&gBrowserContextList
);
4733 while (!IsNull (&gBrowserContextList
, Link
)) {
4734 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4735 if (Context
->HiiHandle
== Handle
) {
4737 // HiiHandle is in BrowserContext
4741 Link
= GetNextNode (&gBrowserContextList
, Link
);
4748 Perform Password check.
4749 Passwork may be encrypted by driver that requires the specific check.
4751 @param Form Form where Password Statement is in.
4752 @param Statement Password statement
4753 @param PasswordString Password string to be checked. It may be NULL.
4754 NULL means to restore password.
4755 "" string can be used to checked whether old password does exist.
4757 @return Status Status of Password check.
4762 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4763 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4764 IN EFI_STRING PasswordString OPTIONAL
4768 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4769 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4770 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4771 FORM_BROWSER_STATEMENT
*Question
;
4773 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4774 Question
= GetBrowserStatement(Statement
);
4775 ASSERT (Question
!= NULL
);
4777 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4778 if (ConfigAccess
== NULL
) {
4779 return EFI_UNSUPPORTED
;
4782 if (PasswordString
== NULL
) {
4787 // Check whether has preexisted password.
4789 if (PasswordString
[0] == 0) {
4790 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
4793 return EFI_NOT_READY
;
4798 // Check whether the input password is same as preexisted password.
4800 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4803 return EFI_NOT_READY
;
4808 // Prepare password string in HII database
4810 if (PasswordString
!= NULL
) {
4811 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4813 IfrTypeValue
.string
= 0;
4817 // Send password to Configuration Driver for validation
4819 Status
= ConfigAccess
->Callback (
4821 EFI_BROWSER_ACTION_CHANGING
,
4822 Question
->QuestionId
,
4823 Question
->HiiValue
.Type
,
4829 // Remove password string from HII database
4831 if (PasswordString
!= NULL
) {
4832 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4839 Find the registered HotKey based on KeyData.
4841 @param[in] KeyData A pointer to a buffer that describes the keystroke
4842 information for the hot key.
4844 @return The registered HotKey context. If no found, NULL will return.
4847 GetHotKeyFromRegisterList (
4848 IN EFI_INPUT_KEY
*KeyData
4852 BROWSER_HOT_KEY
*HotKey
;
4854 Link
= GetFirstNode (&gBrowserHotKeyList
);
4855 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4856 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4857 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4860 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4867 Configure what scope the hot key will impact.
4868 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4869 If no scope is set, the default scope will be FormSet level.
4870 After all registered hot keys are removed, previous Scope can reset to another level.
4872 @param[in] Scope Scope level to be set.
4874 @retval EFI_SUCCESS Scope is set correctly.
4875 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4876 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4882 IN BROWSER_SETTING_SCOPE Scope
4885 if (Scope
>= MaxLevel
) {
4886 return EFI_INVALID_PARAMETER
;
4890 // When no hot key registered in system or on the first setting,
4891 // Scope can be set.
4893 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4894 gBrowserSettingScope
= Scope
;
4895 mBrowserScopeFirstSet
= FALSE
;
4896 } else if (Scope
!= gBrowserSettingScope
) {
4897 return EFI_UNSUPPORTED
;
4904 Register the hot key with its browser action, or unregistered the hot key.
4905 Only support hot key that is not printable character (control key, function key, etc.).
4906 If the action value is zero, the hot key will be unregistered if it has been registered.
4907 If the same hot key has been registered, the new action and help string will override the previous ones.
4909 @param[in] KeyData A pointer to a buffer that describes the keystroke
4910 information for the hot key. Its type is EFI_INPUT_KEY to
4911 be supported by all ConsoleIn devices.
4912 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4913 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4914 @param[in] HelpString Help string that describes the hot key information.
4915 Its value may be NULL for the unregistered hot key.
4917 @retval EFI_SUCCESS Hot key is registered or unregistered.
4918 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4919 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4920 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4925 IN EFI_INPUT_KEY
*KeyData
,
4927 IN UINT16 DefaultId
,
4928 IN EFI_STRING HelpString OPTIONAL
4931 BROWSER_HOT_KEY
*HotKey
;
4934 // Check input parameters.
4936 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4937 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4938 return EFI_INVALID_PARAMETER
;
4942 // Check whether the input KeyData is in BrowserHotKeyList.
4944 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4947 // Unregister HotKey
4949 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4950 if (HotKey
!= NULL
) {
4952 // The registered HotKey is found.
4953 // Remove it from List, and free its resource.
4955 RemoveEntryList (&HotKey
->Link
);
4956 FreePool (HotKey
->KeyData
);
4957 FreePool (HotKey
->HelpString
);
4961 // The registered HotKey is not found.
4963 return EFI_NOT_FOUND
;
4968 // Register HotKey into List.
4970 if (HotKey
== NULL
) {
4972 // Create new Key, and add it into List.
4974 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4975 ASSERT (HotKey
!= NULL
);
4976 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4977 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4978 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4982 // Fill HotKey information.
4984 HotKey
->Action
= Action
;
4985 HotKey
->DefaultId
= DefaultId
;
4986 if (HotKey
->HelpString
!= NULL
) {
4987 FreePool (HotKey
->HelpString
);
4989 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4995 Register Exit handler function.
4996 When more than one handler function is registered, the latter one will override the previous one.
4997 When NULL handler is specified, the previous Exit handler will be unregistered.
4999 @param[in] Handler Pointer to handler function.
5004 RegiserExitHandler (
5005 IN EXIT_HANDLER Handler
5008 ExitHandlerFunction
= Handler
;
5013 Check whether the browser data has been modified.
5015 @retval TRUE Browser data is modified.
5016 @retval FALSE No browser data is modified.
5021 IsBrowserDataModified (
5026 FORM_BROWSER_FORMSET
*FormSet
;
5028 switch (gBrowserSettingScope
) {
5030 if (gCurrentSelection
== NULL
) {
5033 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5036 if (gCurrentSelection
== NULL
) {
5039 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5042 Link
= GetFirstNode (&gBrowserFormSetList
);
5043 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5044 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5045 if (!ValidateFormSet(FormSet
)) {
5049 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5052 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5062 Execute the action requested by the Action parameter.
5064 @param[in] Action Execute the request action.
5065 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5067 @retval EFI_SUCCESS Execute the request action succss.
5068 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5079 FORM_BROWSER_FORMSET
*FormSet
;
5080 FORM_BROWSER_FORM
*Form
;
5082 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5083 return EFI_NOT_READY
;
5086 Status
= EFI_SUCCESS
;
5089 if (gBrowserSettingScope
< SystemLevel
) {
5090 FormSet
= gCurrentSelection
->FormSet
;
5091 Form
= gCurrentSelection
->Form
;
5095 // Executet the discard action.
5097 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5098 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5099 if (EFI_ERROR (Status
)) {
5105 // Executet the difault action.
5107 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5108 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5109 if (EFI_ERROR (Status
)) {
5112 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5116 // Executet the submit action.
5118 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5119 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5120 if (EFI_ERROR (Status
)) {
5126 // Executet the reset action.
5128 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5129 gResetRequired
= TRUE
;
5133 // Executet the exit action.
5135 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5136 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5137 if (gBrowserSettingScope
== SystemLevel
) {
5138 if (ExitHandlerFunction
!= NULL
) {
5139 ExitHandlerFunction ();
5143 gExitRequired
= TRUE
;
5150 Create reminder to let user to choose save or discard the changed browser data.
5151 Caller can use it to actively check the changed browser data.
5153 @retval BROWSER_NO_CHANGES No browser data is changed.
5154 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5155 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5156 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5166 FORM_BROWSER_FORMSET
*FormSet
;
5167 BOOLEAN IsDataChanged
;
5168 UINT32 DataSavedAction
;
5171 DataSavedAction
= BROWSER_NO_CHANGES
;
5172 IsDataChanged
= FALSE
;
5173 Link
= GetFirstNode (&gBrowserFormSetList
);
5174 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5175 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5176 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5177 if (!ValidateFormSet(FormSet
)) {
5180 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5181 IsDataChanged
= TRUE
;
5187 // No data is changed. No save is required.
5189 if (!IsDataChanged
) {
5190 return DataSavedAction
;
5194 // If data is changed, prompt user to save or discard it.
5197 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5199 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5200 SubmitForm (NULL
, NULL
, SystemLevel
);
5201 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5203 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5204 DiscardForm (NULL
, NULL
, SystemLevel
);
5205 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5207 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5208 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5213 return DataSavedAction
;