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
;
612 // If set browser data, pre load all hii formset to avoid set the varstore which is not
615 if (!RetrieveData
&& (gBrowserSettingScope
== SystemLevel
)) {
619 if (VariableGuid
!= NULL
) {
621 // Try to find target storage in the current formset.
623 Link
= GetFirstNode (&gBrowserStorageList
);
624 while (!IsNull (&gBrowserStorageList
, Link
)) {
625 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
626 Link
= GetNextNode (&gBrowserStorageList
, Link
);
628 // Check the current storage.
630 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
634 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
635 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
637 // Buffer storage require both GUID and Name
639 if (VariableName
== NULL
) {
640 return EFI_NOT_FOUND
;
643 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
648 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
649 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
650 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
651 return EFI_NOT_FOUND
;
654 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
659 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
660 if (EFI_ERROR (Status
)) {
665 // Different formsets may have same varstore, so here just set the flag
666 // not exit the circle.
673 return EFI_NOT_FOUND
;
677 // GUID/Name is not specified, take the first storage in FormSet
679 if (mSystemLevelFormSet
== NULL
) {
680 return EFI_NOT_READY
;
684 // Generate <ConfigResp>
686 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
687 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
688 return EFI_UNSUPPORTED
;
691 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
693 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
694 if (EFI_ERROR (Status
)) {
700 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
701 *ResultsDataSize
= TotalSize
;
710 Callback function for SimpleTextInEx protocol install events
712 @param Event the event that is signaled.
713 @param Context not used here.
718 FormDisplayCallback (
725 if (mFormDisplay
!= NULL
) {
729 Status
= gBS
->LocateProtocol (
730 &gEdkiiFormDisplayEngineProtocolGuid
,
732 (VOID
**) &mFormDisplay
737 Initialize Setup Browser driver.
739 @param ImageHandle The image handle.
740 @param SystemTable The system table.
742 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
743 @return Other value if failed to initialize the Setup Browser module.
749 IN EFI_HANDLE ImageHandle
,
750 IN EFI_SYSTEM_TABLE
*SystemTable
757 // Locate required Hii relative protocols
759 Status
= gBS
->LocateProtocol (
760 &gEfiHiiDatabaseProtocolGuid
,
762 (VOID
**) &mHiiDatabase
764 ASSERT_EFI_ERROR (Status
);
766 Status
= gBS
->LocateProtocol (
767 &gEfiHiiConfigRoutingProtocolGuid
,
769 (VOID
**) &mHiiConfigRouting
771 ASSERT_EFI_ERROR (Status
);
773 Status
= gBS
->LocateProtocol (
774 &gEfiDevicePathFromTextProtocolGuid
,
776 (VOID
**) &mPathFromText
780 // Install FormBrowser2 protocol
782 mPrivateData
.Handle
= NULL
;
783 Status
= gBS
->InstallProtocolInterface (
784 &mPrivateData
.Handle
,
785 &gEfiFormBrowser2ProtocolGuid
,
786 EFI_NATIVE_INTERFACE
,
787 &mPrivateData
.FormBrowser2
789 ASSERT_EFI_ERROR (Status
);
792 // Install FormBrowserEx2 protocol
794 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
795 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
796 mPrivateData
.Handle
= NULL
;
797 Status
= gBS
->InstallProtocolInterface (
798 &mPrivateData
.Handle
,
799 &gEdkiiFormBrowserEx2ProtocolGuid
,
800 EFI_NATIVE_INTERFACE
,
801 &mPrivateData
.FormBrowserEx2
803 ASSERT_EFI_ERROR (Status
);
805 Status
= gBS
->InstallProtocolInterface (
806 &mPrivateData
.Handle
,
807 &gEfiFormBrowserExProtocolGuid
,
808 EFI_NATIVE_INTERFACE
,
809 &mPrivateData
.FormBrowserEx
811 ASSERT_EFI_ERROR (Status
);
813 InitializeDisplayFormData ();
815 Status
= gBS
->LocateProtocol (
816 &gEdkiiFormDisplayEngineProtocolGuid
,
818 (VOID
**) &mFormDisplay
821 if (EFI_ERROR (Status
)) {
822 EfiCreateProtocolNotifyEvent (
823 &gEdkiiFormDisplayEngineProtocolGuid
,
836 Create a new string in HII Package List.
838 @param String The String to be added
839 @param HiiHandle The package list in the HII database to insert the
842 @return The output string.
848 IN EFI_HII_HANDLE HiiHandle
851 EFI_STRING_ID StringId
;
853 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
854 ASSERT (StringId
!= 0);
861 Delete a string from HII Package List.
863 @param StringId Id of the string in HII database.
864 @param HiiHandle The HII package list handle.
866 @retval EFI_SUCCESS The string was deleted successfully.
871 IN EFI_STRING_ID StringId
,
872 IN EFI_HII_HANDLE HiiHandle
877 NullChar
= CHAR_NULL
;
878 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
884 Get the string based on the StringId and HII Package List Handle.
886 @param Token The String's ID.
887 @param HiiHandle The package list in the HII database to search for
888 the specified string.
890 @return The output string.
895 IN EFI_STRING_ID Token
,
896 IN EFI_HII_HANDLE HiiHandle
901 if (HiiHandle
== NULL
) {
905 String
= HiiGetString (HiiHandle
, Token
, NULL
);
906 if (String
== NULL
) {
907 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
908 ASSERT (String
!= NULL
);
910 return (CHAR16
*) String
;
915 Allocate new memory and then copy the Unicode string Source to Destination.
917 @param Dest Location to copy string
918 @param Src String to copy
923 IN OUT CHAR16
**Dest
,
930 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
931 ASSERT (*Dest
!= NULL
);
936 Allocate new memory and concatinate Source on the end of Destination.
938 @param Dest String to added to the end of.
939 @param Src String to concatinate.
944 IN OUT CHAR16
**Dest
,
952 NewStringCpy (Dest
, Src
);
956 TmpSize
= StrSize (*Dest
);
957 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
958 ASSERT (NewString
!= NULL
);
960 StrCpy (NewString
, *Dest
);
961 StrCat (NewString
, Src
);
968 Get Value for given Name from a NameValue Storage.
970 @param Storage The NameValue Storage.
971 @param Name The Name.
972 @param Value The retured Value.
973 @param GetValueFrom Where to get source value, from EditValue or Value.
975 @retval EFI_SUCCESS Value found for given Name.
976 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
981 IN BROWSER_STORAGE
*Storage
,
983 IN OUT CHAR16
**Value
,
984 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
988 NAME_VALUE_NODE
*Node
;
990 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
991 return EFI_INVALID_PARAMETER
;
996 Link
= GetFirstNode (&Storage
->NameValueListHead
);
997 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
998 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1000 if (StrCmp (Name
, Node
->Name
) == 0) {
1001 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1002 NewStringCpy (Value
, Node
->EditValue
);
1004 NewStringCpy (Value
, Node
->Value
);
1009 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1012 return EFI_NOT_FOUND
;
1017 Set Value of given Name in a NameValue Storage.
1019 @param Storage The NameValue Storage.
1020 @param Name The Name.
1021 @param Value The Value to set.
1022 @param SetValueTo Whether update editValue or Value.
1023 @param ReturnNode The node use the input name.
1025 @retval EFI_SUCCESS Value found for given Name.
1026 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1031 IN BROWSER_STORAGE
*Storage
,
1034 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1035 OUT NAME_VALUE_NODE
**ReturnNode
1039 NAME_VALUE_NODE
*Node
;
1042 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1043 return EFI_INVALID_PARAMETER
;
1046 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1047 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1048 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1050 if (StrCmp (Name
, Node
->Name
) == 0) {
1051 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1052 Buffer
= Node
->EditValue
;
1054 Buffer
= Node
->Value
;
1056 if (Buffer
!= NULL
) {
1059 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1060 ASSERT (Buffer
!= NULL
);
1061 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1062 Node
->EditValue
= Buffer
;
1064 Node
->Value
= Buffer
;
1067 if (ReturnNode
!= NULL
) {
1074 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1077 return EFI_NOT_FOUND
;
1082 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1084 @param Storage The Storage to be conveted.
1085 @param ConfigResp The returned <ConfigResp>.
1086 @param ConfigRequest The ConfigRequest string.
1087 @param GetEditBuf Get the data from editbuffer or buffer.
1089 @retval EFI_SUCCESS Convert success.
1090 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1094 StorageToConfigResp (
1095 IN BROWSER_STORAGE
*Storage
,
1096 IN CHAR16
**ConfigResp
,
1097 IN CHAR16
*ConfigRequest
,
1098 IN BOOLEAN GetEditBuf
1102 EFI_STRING Progress
;
1104 NAME_VALUE_NODE
*Node
;
1107 Status
= EFI_SUCCESS
;
1109 switch (Storage
->Type
) {
1110 case EFI_HII_VARSTORE_BUFFER
:
1111 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1112 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1113 Status
= mHiiConfigRouting
->BlockToConfig (
1123 case EFI_HII_VARSTORE_NAME_VALUE
:
1125 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1127 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1128 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1129 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1131 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1132 NewStringCat (ConfigResp
, L
"&");
1133 NewStringCat (ConfigResp
, Node
->Name
);
1134 NewStringCat (ConfigResp
, L
"=");
1136 NewStringCat (ConfigResp
, Node
->EditValue
);
1138 NewStringCat (ConfigResp
, Node
->Value
);
1141 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1145 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1147 Status
= EFI_INVALID_PARAMETER
;
1156 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1158 @param Storage The Storage to receive the settings.
1159 @param ConfigResp The <ConfigResp> to be converted.
1161 @retval EFI_SUCCESS Convert success.
1162 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1166 ConfigRespToStorage (
1167 IN BROWSER_STORAGE
*Storage
,
1168 IN CHAR16
*ConfigResp
1172 EFI_STRING Progress
;
1178 Status
= EFI_SUCCESS
;
1180 switch (Storage
->Type
) {
1181 case EFI_HII_VARSTORE_BUFFER
:
1182 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1183 BufferSize
= Storage
->Size
;
1184 Status
= mHiiConfigRouting
->ConfigToBlock (
1187 Storage
->EditBuffer
,
1193 case EFI_HII_VARSTORE_NAME_VALUE
:
1194 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1195 if (StrPtr
== NULL
) {
1198 StrPtr
= StrStr (ConfigResp
, L
"&");
1199 while (StrPtr
!= NULL
) {
1203 StrPtr
= StrPtr
+ 1;
1205 StrPtr
= StrStr (StrPtr
, L
"=");
1206 if (StrPtr
== NULL
) {
1214 StrPtr
= StrPtr
+ 1;
1216 StrPtr
= StrStr (StrPtr
, L
"&");
1217 if (StrPtr
!= NULL
) {
1220 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1224 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1226 Status
= EFI_INVALID_PARAMETER
;
1235 Get Question's current Value.
1237 @param FormSet FormSet data structure.
1238 @param Form Form data structure.
1239 @param Question Question to be initialized.
1240 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1242 @retval EFI_SUCCESS The function completed successfully.
1247 IN FORM_BROWSER_FORMSET
*FormSet
,
1248 IN FORM_BROWSER_FORM
*Form
,
1249 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1250 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1259 BROWSER_STORAGE
*Storage
;
1260 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1261 CHAR16
*ConfigRequest
;
1269 BOOLEAN IsBufferStorage
;
1274 Status
= EFI_SUCCESS
;
1278 if (GetValueFrom
>= GetSetValueWithMax
) {
1279 return EFI_INVALID_PARAMETER
;
1283 // Question value is provided by an Expression, evaluate it
1285 if (Question
->ValueExpression
!= NULL
) {
1286 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1287 if (!EFI_ERROR (Status
)) {
1288 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1289 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1290 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1291 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1292 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1294 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1295 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1297 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1299 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1300 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1306 // Get question value by read expression.
1308 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1309 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1310 if (!EFI_ERROR (Status
) &&
1311 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1313 // Only update question value to the valid result.
1315 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1316 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1317 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1318 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1319 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1321 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1322 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1324 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1326 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1327 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1333 // Question value is provided by RTC
1335 Storage
= Question
->Storage
;
1336 QuestionValue
= &Question
->HiiValue
.Value
;
1337 if (Storage
== NULL
) {
1339 // It's a Question without storage, or RTC date/time
1341 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1343 // Date and time define the same Flags bit
1345 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1346 case QF_DATE_STORAGE_TIME
:
1347 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1350 case QF_DATE_STORAGE_WAKEUP
:
1351 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1354 case QF_DATE_STORAGE_NORMAL
:
1357 // For date/time without storage
1362 if (EFI_ERROR (Status
)) {
1366 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1367 QuestionValue
->date
.Year
= EfiTime
.Year
;
1368 QuestionValue
->date
.Month
= EfiTime
.Month
;
1369 QuestionValue
->date
.Day
= EfiTime
.Day
;
1371 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1372 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1373 QuestionValue
->time
.Second
= EfiTime
.Second
;
1381 // Question value is provided by EFI variable
1383 StorageWidth
= Question
->StorageWidth
;
1384 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1385 if (Question
->BufferValue
!= NULL
) {
1386 Dst
= Question
->BufferValue
;
1388 Dst
= (UINT8
*) QuestionValue
;
1391 Status
= gRT
->GetVariable (
1392 Question
->VariableName
,
1399 // Always return success, even this EFI variable doesn't exist
1405 // Question Value is provided by Buffer Storage or NameValue Storage
1407 if (Question
->BufferValue
!= NULL
) {
1409 // This Question is password or orderedlist
1411 Dst
= Question
->BufferValue
;
1414 // Other type of Questions
1416 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1419 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1420 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1421 IsBufferStorage
= TRUE
;
1423 IsBufferStorage
= FALSE
;
1425 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1426 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1427 if (IsBufferStorage
) {
1428 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1430 // Copy from storage Edit buffer
1432 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1435 // Copy from storage Edit buffer
1437 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1441 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1442 if (EFI_ERROR (Status
)) {
1446 ASSERT (Value
!= NULL
);
1447 LengthStr
= StrLen (Value
);
1448 Status
= EFI_SUCCESS
;
1451 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1452 // Add string tail char L'\0' into Length
1454 Length
= StorageWidth
+ sizeof (CHAR16
);
1455 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1456 Status
= EFI_BUFFER_TOO_SMALL
;
1458 StringPtr
= (CHAR16
*) Dst
;
1459 ZeroMem (TemStr
, sizeof (TemStr
));
1460 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1461 StrnCpy (TemStr
, Value
+ Index
, 4);
1462 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1465 // Add tailing L'\0' character
1467 StringPtr
[Index
/4] = L
'\0';
1470 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1471 Status
= EFI_BUFFER_TOO_SMALL
;
1473 ZeroMem (TemStr
, sizeof (TemStr
));
1474 for (Index
= 0; Index
< LengthStr
; Index
++) {
1475 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1476 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1477 if ((Index
& 1) == 0) {
1478 Dst
[Index
/2] = DigitUint8
;
1480 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1490 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1491 // <ConfigHdr> + "&" + <VariableName>
1493 if (IsBufferStorage
) {
1494 Length
= StrLen (Storage
->ConfigHdr
);
1495 Length
+= StrLen (Question
->BlockName
);
1497 Length
= StrLen (Storage
->ConfigHdr
);
1498 Length
+= StrLen (Question
->VariableName
) + 1;
1500 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1501 ASSERT (ConfigRequest
!= NULL
);
1503 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1504 if (IsBufferStorage
) {
1505 StrCat (ConfigRequest
, Question
->BlockName
);
1507 StrCat (ConfigRequest
, L
"&");
1508 StrCat (ConfigRequest
, Question
->VariableName
);
1512 // Request current settings from Configuration Driver
1514 Status
= mHiiConfigRouting
->ExtractConfig (
1520 FreePool (ConfigRequest
);
1521 if (EFI_ERROR (Status
)) {
1526 // Skip <ConfigRequest>
1528 if (IsBufferStorage
) {
1529 Value
= StrStr (Result
, L
"&VALUE");
1530 if (Value
== NULL
) {
1532 return EFI_NOT_FOUND
;
1539 Value
= Result
+ Length
;
1541 if (*Value
!= '=') {
1543 return EFI_NOT_FOUND
;
1546 // Skip '=', point to value
1551 // Suppress <AltResp> if any
1554 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1559 LengthStr
= StrLen (Value
);
1560 Status
= EFI_SUCCESS
;
1561 if (!IsBufferStorage
&& IsString
) {
1563 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1564 // Add string tail char L'\0' into Length
1566 Length
= StorageWidth
+ sizeof (CHAR16
);
1567 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1568 Status
= EFI_BUFFER_TOO_SMALL
;
1570 StringPtr
= (CHAR16
*) Dst
;
1571 ZeroMem (TemStr
, sizeof (TemStr
));
1572 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1573 StrnCpy (TemStr
, Value
+ Index
, 4);
1574 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1577 // Add tailing L'\0' character
1579 StringPtr
[Index
/4] = L
'\0';
1582 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1583 Status
= EFI_BUFFER_TOO_SMALL
;
1585 ZeroMem (TemStr
, sizeof (TemStr
));
1586 for (Index
= 0; Index
< LengthStr
; Index
++) {
1587 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1588 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1589 if ((Index
& 1) == 0) {
1590 Dst
[Index
/2] = DigitUint8
;
1592 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1598 if (EFI_ERROR (Status
)) {
1604 // Synchronize Edit Buffer
1606 if (IsBufferStorage
) {
1607 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1609 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1612 if (Result
!= NULL
) {
1622 Save Question Value to edit copy(cached) or Storage(uncached).
1624 @param FormSet FormSet data structure.
1625 @param Form Form data structure.
1626 @param Question Pointer to the Question.
1627 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1629 @retval EFI_SUCCESS The function completed successfully.
1634 IN FORM_BROWSER_FORMSET
*FormSet
,
1635 IN FORM_BROWSER_FORM
*Form
,
1636 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1637 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1647 BROWSER_STORAGE
*Storage
;
1648 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1653 BOOLEAN IsBufferStorage
;
1659 NAME_VALUE_NODE
*Node
;
1661 Status
= EFI_SUCCESS
;
1664 if (SetValueTo
>= GetSetValueWithMax
) {
1665 return EFI_INVALID_PARAMETER
;
1669 // If Question value is provided by an Expression, then it is read only
1671 if (Question
->ValueExpression
!= NULL
) {
1676 // Before set question value, evaluate its write expression.
1678 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1679 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1680 if (EFI_ERROR (Status
)) {
1686 // Question value is provided by RTC
1688 Storage
= Question
->Storage
;
1689 QuestionValue
= &Question
->HiiValue
.Value
;
1690 if (Storage
== NULL
) {
1692 // It's a Question without storage, or RTC date/time
1694 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1696 // Date and time define the same Flags bit
1698 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1699 case QF_DATE_STORAGE_TIME
:
1700 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1703 case QF_DATE_STORAGE_WAKEUP
:
1704 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1707 case QF_DATE_STORAGE_NORMAL
:
1710 // For date/time without storage
1715 if (EFI_ERROR (Status
)) {
1719 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1720 EfiTime
.Year
= QuestionValue
->date
.Year
;
1721 EfiTime
.Month
= QuestionValue
->date
.Month
;
1722 EfiTime
.Day
= QuestionValue
->date
.Day
;
1724 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1725 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1726 EfiTime
.Second
= QuestionValue
->time
.Second
;
1729 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1730 Status
= gRT
->SetTime (&EfiTime
);
1732 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1740 // Question value is provided by EFI variable
1742 StorageWidth
= Question
->StorageWidth
;
1743 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1744 if (Question
->BufferValue
!= NULL
) {
1745 Src
= Question
->BufferValue
;
1747 Src
= (UINT8
*) QuestionValue
;
1750 Status
= gRT
->SetVariable (
1751 Question
->VariableName
,
1753 Storage
->Attributes
,
1761 // Question Value is provided by Buffer Storage or NameValue Storage
1763 if (Question
->BufferValue
!= NULL
) {
1764 Src
= Question
->BufferValue
;
1766 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1769 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1770 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1771 IsBufferStorage
= TRUE
;
1773 IsBufferStorage
= FALSE
;
1775 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1777 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1778 if (IsBufferStorage
) {
1779 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1781 // Copy to storage edit buffer
1783 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1784 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1786 // Copy to storage edit buffer
1788 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1793 // Allocate enough string buffer.
1796 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1797 Value
= AllocateZeroPool (BufferLen
);
1798 ASSERT (Value
!= NULL
);
1800 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1802 TemName
= (CHAR16
*) Src
;
1804 for (; *TemName
!= L
'\0'; TemName
++) {
1805 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1808 BufferLen
= StorageWidth
* 2 + 1;
1809 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1810 ASSERT (Value
!= NULL
);
1812 // Convert Buffer to Hex String
1814 TemBuffer
= Src
+ StorageWidth
- 1;
1816 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1817 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1821 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1823 if (EFI_ERROR (Status
)) {
1827 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1829 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1830 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1832 if (IsBufferStorage
) {
1833 Length
= StrLen (Question
->BlockName
) + 7;
1835 Length
= StrLen (Question
->VariableName
) + 2;
1837 if (!IsBufferStorage
&& IsString
) {
1838 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1840 Length
+= (StorageWidth
* 2);
1842 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1843 ASSERT (ConfigResp
!= NULL
);
1845 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1846 if (IsBufferStorage
) {
1847 StrCat (ConfigResp
, Question
->BlockName
);
1848 StrCat (ConfigResp
, L
"&VALUE=");
1850 StrCat (ConfigResp
, L
"&");
1851 StrCat (ConfigResp
, Question
->VariableName
);
1852 StrCat (ConfigResp
, L
"=");
1855 Value
= ConfigResp
+ StrLen (ConfigResp
);
1857 if (!IsBufferStorage
&& IsString
) {
1859 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1861 TemName
= (CHAR16
*) Src
;
1863 for (; *TemName
!= L
'\0'; TemName
++) {
1864 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1868 // Convert Buffer to Hex String
1870 TemBuffer
= Src
+ StorageWidth
- 1;
1872 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1873 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1878 // Convert to lower char.
1880 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1881 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1882 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1887 // Submit Question Value to Configuration Driver
1889 Status
= mHiiConfigRouting
->RouteConfig (
1894 if (EFI_ERROR (Status
)) {
1895 FreePool (ConfigResp
);
1898 FreePool (ConfigResp
);
1901 // Sync storage, from editbuffer to buffer.
1903 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1911 Perform nosubmitif check for a Form.
1913 @param FormSet FormSet data structure.
1914 @param Form Form data structure.
1915 @param Question The Question to be validated.
1916 @param Type Validation type: NoSubmit
1918 @retval EFI_SUCCESS Form validation pass.
1919 @retval other Form validation failed.
1924 IN FORM_BROWSER_FORMSET
*FormSet
,
1925 IN FORM_BROWSER_FORM
*Form
,
1926 IN FORM_BROWSER_STATEMENT
*Question
,
1932 LIST_ENTRY
*ListHead
;
1934 FORM_EXPRESSION
*Expression
;
1936 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1937 ListHead
= &Question
->NoSubmitListHead
;
1939 return EFI_UNSUPPORTED
;
1942 Link
= GetFirstNode (ListHead
);
1943 while (!IsNull (ListHead
, Link
)) {
1944 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1947 // Evaluate the expression
1949 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1950 if (EFI_ERROR (Status
)) {
1954 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1956 // Condition meet, show up error message
1958 if (Expression
->Error
!= 0) {
1959 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1960 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1961 gBrowserStatus
= BROWSER_NO_SUBMIT_IF
;
1966 return EFI_NOT_READY
;
1969 Link
= GetNextNode (ListHead
, Link
);
1977 Perform NoSubmit check for each Form in FormSet.
1979 @param FormSet FormSet data structure.
1980 @param CurrentForm Current input form data structure.
1982 @retval EFI_SUCCESS Form validation pass.
1983 @retval other Form validation failed.
1988 IN FORM_BROWSER_FORMSET
*FormSet
,
1989 IN FORM_BROWSER_FORM
*CurrentForm
1994 FORM_BROWSER_STATEMENT
*Question
;
1995 FORM_BROWSER_FORM
*Form
;
1996 LIST_ENTRY
*LinkForm
;
1998 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1999 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2000 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2001 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2003 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2007 Link
= GetFirstNode (&Form
->StatementListHead
);
2008 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2009 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2011 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2012 if (EFI_ERROR (Status
)) {
2016 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2024 Fill storage's edit copy with settings requested from Configuration Driver.
2026 @param FormSet FormSet data structure.
2027 @param Storage The storage which need to sync.
2028 @param ConfigRequest The config request string which used to sync storage.
2029 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2030 editbuffer to buffer
2031 if TRUE, copy the editbuffer to the buffer.
2032 if FALSE, copy the buffer to the editbuffer.
2034 @retval EFI_SUCCESS The function completed successfully.
2038 SynchronizeStorage (
2039 IN FORM_BROWSER_FORMSET
*FormSet
,
2040 OUT BROWSER_STORAGE
*Storage
,
2041 IN CHAR16
*ConfigRequest
,
2042 IN BOOLEAN SyncOrRestore
2046 EFI_STRING Progress
;
2050 NAME_VALUE_NODE
*Node
;
2054 Status
= EFI_SUCCESS
;
2057 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2058 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2059 BufferSize
= Storage
->Size
;
2061 if (SyncOrRestore
) {
2062 Src
= Storage
->EditBuffer
;
2063 Dst
= Storage
->Buffer
;
2065 Src
= Storage
->Buffer
;
2066 Dst
= Storage
->EditBuffer
;
2069 if (ConfigRequest
!= NULL
) {
2070 Status
= mHiiConfigRouting
->BlockToConfig(
2078 if (EFI_ERROR (Status
)) {
2082 Status
= mHiiConfigRouting
->ConfigToBlock (
2089 if (Result
!= NULL
) {
2093 CopyMem (Dst
, Src
, BufferSize
);
2095 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2096 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2097 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2098 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2100 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2101 (ConfigRequest
== NULL
)) {
2102 if (SyncOrRestore
) {
2103 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2105 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2109 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2117 When discard the question value, call the callback function with Changed type
2118 to inform the hii driver.
2120 @param FormSet FormSet data structure.
2121 @param Form Form data structure.
2125 SendDiscardInfoToDriver (
2126 IN FORM_BROWSER_FORMSET
*FormSet
,
2127 IN FORM_BROWSER_FORM
*Form
2131 FORM_BROWSER_STATEMENT
*Question
;
2132 EFI_IFR_TYPE_VALUE
*TypeValue
;
2133 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2135 if (FormSet
->ConfigAccess
== NULL
) {
2139 Link
= GetFirstNode (&Form
->StatementListHead
);
2140 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2141 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2142 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2144 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2148 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2152 if (!Question
->ValueChanged
) {
2156 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2157 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2159 TypeValue
= &Question
->HiiValue
.Value
;
2162 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2163 FormSet
->ConfigAccess
->Callback (
2164 FormSet
->ConfigAccess
,
2165 EFI_BROWSER_ACTION_CHANGED
,
2166 Question
->QuestionId
,
2167 Question
->HiiValue
.Type
,
2175 Validate the FormSet. If the formset is not validate, remove it from the list.
2177 @param FormSet The input FormSet which need to validate.
2179 @retval TRUE The handle is validate.
2180 @retval FALSE The handle is invalidate.
2185 FORM_BROWSER_FORMSET
*FormSet
2188 EFI_HII_HANDLE
*HiiHandles
;
2192 ASSERT (FormSet
!= NULL
);
2195 // Get all the Hii handles
2197 HiiHandles
= HiiGetHiiHandles (NULL
);
2198 ASSERT (HiiHandles
!= NULL
);
2201 // Search for formset of each class type
2203 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2204 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2211 CleanBrowserStorage(FormSet
);
2212 RemoveEntryList (&FormSet
->Link
);
2213 DestroyFormSet (FormSet
);
2216 FreePool (HiiHandles
);
2221 Check whether need to enable the reset flag in form level.
2222 Also clean all ValueChanged flag in question.
2224 @param SetFlag Whether need to set the Reset Flag.
2225 @param Form Form data structure.
2231 IN FORM_BROWSER_FORM
*Form
2235 FORM_BROWSER_STATEMENT
*Question
;
2239 Link
= GetFirstNode (&Form
->StatementListHead
);
2240 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2241 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2243 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2244 gResetRequired
= TRUE
;
2247 if (Question
->ValueChanged
) {
2248 Question
->ValueChanged
= FALSE
;
2251 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2256 Check whether need to enable the reset flag.
2257 Also clean ValueChanged flag for all statements.
2259 Form level or formset level, only one.
2261 @param SetFlag Whether need to set the Reset Flag.
2262 @param FormSet FormSet data structure.
2263 @param Form Form data structure.
2267 ValueChangeResetFlagUpdate (
2269 IN FORM_BROWSER_FORMSET
*FormSet
,
2270 IN FORM_BROWSER_FORM
*Form
2273 FORM_BROWSER_FORM
*CurrentForm
;
2277 // Form != NULL means only check form level.
2280 UpdateFlagForForm(SetFlag
, Form
);
2284 Link
= GetFirstNode (&FormSet
->FormListHead
);
2285 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2286 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2287 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2289 UpdateFlagForForm(SetFlag
, CurrentForm
);
2294 Discard data based on the input setting scope (Form, FormSet or System).
2296 @param FormSet FormSet data structure.
2297 @param Form Form data structure.
2298 @param SettingScope Setting Scope for Discard action.
2300 @retval EFI_SUCCESS The function completed successfully.
2301 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2306 IN FORM_BROWSER_FORMSET
*FormSet
,
2307 IN FORM_BROWSER_FORM
*Form
,
2308 IN BROWSER_SETTING_SCOPE SettingScope
2312 FORMSET_STORAGE
*Storage
;
2313 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2314 FORM_BROWSER_FORMSET
*LocalFormSet
;
2315 FORM_BROWSER_FORMSET
*OldFormSet
;
2318 // Check the supported setting level.
2320 if (SettingScope
>= MaxLevel
) {
2321 return EFI_UNSUPPORTED
;
2324 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2326 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2327 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2328 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2329 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2331 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2336 // Skip if there is no RequestElement
2338 if (ConfigInfo
->ElementCount
== 0) {
2343 // Prepare <ConfigResp>
2345 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2348 // Call callback with Changed type to inform the driver.
2350 SendDiscardInfoToDriver (FormSet
, Form
);
2353 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2354 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2357 // Discard Buffer storage or Name/Value storage
2359 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2360 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2361 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2362 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2364 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2369 // Skip if there is no RequestElement
2371 if (Storage
->ElementCount
== 0) {
2375 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2378 Link
= GetFirstNode (&FormSet
->FormListHead
);
2379 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2380 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2381 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2384 // Call callback with Changed type to inform the driver.
2386 SendDiscardInfoToDriver (FormSet
, Form
);
2389 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2390 } else if (SettingScope
== SystemLevel
) {
2392 // System Level Discard.
2394 OldFormSet
= mSystemLevelFormSet
;
2397 // Discard changed value for each FormSet in the maintain list.
2399 Link
= GetFirstNode (&gBrowserFormSetList
);
2400 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2401 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2402 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2403 if (!ValidateFormSet(LocalFormSet
)) {
2407 mSystemLevelFormSet
= LocalFormSet
;
2409 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2410 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2412 // Remove maintain backup list after discard except for the current using FormSet.
2414 CleanBrowserStorage(LocalFormSet
);
2415 RemoveEntryList (&LocalFormSet
->Link
);
2416 DestroyFormSet (LocalFormSet
);
2420 mSystemLevelFormSet
= OldFormSet
;
2427 Submit data based on the input Setting level (Form, FormSet or System).
2429 @param FormSet FormSet data structure.
2430 @param Form Form data structure.
2431 @param SettingScope Setting Scope for Submit action.
2433 @retval EFI_SUCCESS The function completed successfully.
2434 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2439 IN FORM_BROWSER_FORMSET
*FormSet
,
2440 IN FORM_BROWSER_FORM
*Form
,
2441 IN BROWSER_SETTING_SCOPE SettingScope
2446 EFI_STRING ConfigResp
;
2447 EFI_STRING Progress
;
2448 BROWSER_STORAGE
*Storage
;
2449 FORMSET_STORAGE
*FormSetStorage
;
2450 FORM_BROWSER_FORMSET
*LocalFormSet
;
2451 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2454 // Check the supported setting level.
2456 if (SettingScope
>= MaxLevel
) {
2457 return EFI_UNSUPPORTED
;
2461 // Validate the Form by NoSubmit check
2463 Status
= EFI_SUCCESS
;
2464 if (SettingScope
== FormLevel
) {
2465 Status
= NoSubmitCheck (FormSet
, Form
);
2466 } else if (SettingScope
== FormSetLevel
) {
2467 Status
= NoSubmitCheck (FormSet
, NULL
);
2469 if (EFI_ERROR (Status
)) {
2473 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2475 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2476 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2477 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2478 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2480 Storage
= ConfigInfo
->Storage
;
2481 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2486 // Skip if there is no RequestElement
2488 if (ConfigInfo
->ElementCount
== 0) {
2493 // 1. Prepare <ConfigResp>
2495 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2496 if (EFI_ERROR (Status
)) {
2501 // 2. Set value to hii config routine protocol.
2503 Status
= mHiiConfigRouting
->RouteConfig (
2508 if (EFI_ERROR (Status
)) {
2509 FreePool (ConfigResp
);
2513 FreePool (ConfigResp
);
2515 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2517 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2521 // 4. Update the NV flag.
2523 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2524 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2526 // Submit Buffer storage or Name/Value storage
2528 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2529 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2530 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2531 Storage
= FormSetStorage
->BrowserStorage
;
2532 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2534 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2539 // Skip if there is no RequestElement
2541 if (FormSetStorage
->ElementCount
== 0) {
2546 // 1. Prepare <ConfigResp>
2548 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2549 if (EFI_ERROR (Status
)) {
2554 // 2. Send <ConfigResp> to Routine config Protocol.
2556 Status
= mHiiConfigRouting
->RouteConfig (
2561 if (EFI_ERROR (Status
)) {
2562 FreePool (ConfigResp
);
2566 FreePool (ConfigResp
);
2568 // 3. Config success, update storage shadow Buffer
2570 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2574 // 4. Update the NV flag.
2576 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2577 } else if (SettingScope
== SystemLevel
) {
2579 // System Level Save.
2583 // Save changed value for each FormSet in the maintain list.
2585 Link
= GetFirstNode (&gBrowserFormSetList
);
2586 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2587 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2588 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2589 if (!ValidateFormSet(LocalFormSet
)) {
2592 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2593 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2595 // Remove maintain backup list after save except for the current using FormSet.
2597 CleanBrowserStorage(LocalFormSet
);
2598 RemoveEntryList (&LocalFormSet
->Link
);
2599 DestroyFormSet (LocalFormSet
);
2608 Get Question default value from AltCfg string.
2610 @param FormSet The form set.
2611 @param Question The question.
2612 @param DefaultId The default Id.
2614 @retval EFI_SUCCESS Question is reset to default value.
2618 GetDefaultValueFromAltCfg (
2619 IN FORM_BROWSER_FORMSET
*FormSet
,
2620 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2624 BOOLEAN IsBufferStorage
;
2627 BROWSER_STORAGE
*Storage
;
2628 CHAR16
*ConfigRequest
;
2641 Status
= EFI_NOT_FOUND
;
2644 ConfigRequest
= NULL
;
2648 Storage
= Question
->Storage
;
2650 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2655 // Question Value is provided by Buffer Storage or NameValue Storage
2657 if (Question
->BufferValue
!= NULL
) {
2659 // This Question is password or orderedlist
2661 Dst
= Question
->BufferValue
;
2664 // Other type of Questions
2666 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2669 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2670 IsBufferStorage
= TRUE
;
2672 IsBufferStorage
= FALSE
;
2674 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2677 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2678 // <ConfigHdr> + "&" + <VariableName>
2680 if (IsBufferStorage
) {
2681 Length
= StrLen (Storage
->ConfigHdr
);
2682 Length
+= StrLen (Question
->BlockName
);
2684 Length
= StrLen (Storage
->ConfigHdr
);
2685 Length
+= StrLen (Question
->VariableName
) + 1;
2687 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2688 ASSERT (ConfigRequest
!= NULL
);
2690 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2691 if (IsBufferStorage
) {
2692 StrCat (ConfigRequest
, Question
->BlockName
);
2694 StrCat (ConfigRequest
, L
"&");
2695 StrCat (ConfigRequest
, Question
->VariableName
);
2698 Status
= mHiiConfigRouting
->ExtractConfig (
2704 if (EFI_ERROR (Status
)) {
2709 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2710 // Get the default configuration string according to the default ID.
2712 Status
= mHiiConfigRouting
->GetAltConfig (
2718 &DefaultId
, // it can be NULL to get the current setting.
2723 // The required setting can't be found. So, it is not required to be validated and set.
2725 if (EFI_ERROR (Status
)) {
2729 if (ConfigResp
== NULL
) {
2730 Status
= EFI_NOT_FOUND
;
2735 // Skip <ConfigRequest>
2737 if (IsBufferStorage
) {
2738 Value
= StrStr (ConfigResp
, L
"&VALUE");
2739 ASSERT (Value
!= NULL
);
2745 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2746 ASSERT (Value
!= NULL
);
2748 Value
= Value
+ StrLen (Question
->VariableName
);
2750 if (*Value
!= '=') {
2751 Status
= EFI_NOT_FOUND
;
2755 // Skip '=', point to value
2760 // Suppress <AltResp> if any
2763 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2768 LengthStr
= StrLen (Value
);
2769 if (!IsBufferStorage
&& IsString
) {
2770 StringPtr
= (CHAR16
*) Dst
;
2771 ZeroMem (TemStr
, sizeof (TemStr
));
2772 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2773 StrnCpy (TemStr
, Value
+ Index
, 4);
2774 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2777 // Add tailing L'\0' character
2779 StringPtr
[Index
/4] = L
'\0';
2781 ZeroMem (TemStr
, sizeof (TemStr
));
2782 for (Index
= 0; Index
< LengthStr
; Index
++) {
2783 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2784 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2785 if ((Index
& 1) == 0) {
2786 Dst
[Index
/2] = DigitUint8
;
2788 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2794 if (ConfigRequest
!= NULL
){
2795 FreePool (ConfigRequest
);
2798 if (ConfigResp
!= NULL
) {
2799 FreePool (ConfigResp
);
2802 if (Result
!= NULL
) {
2810 Get default Id value used for browser.
2812 @param DefaultId The default id value used by hii.
2814 @retval Browser used default value.
2818 GetDefaultIdForCallBack (
2822 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2823 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2824 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2825 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2826 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2827 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2828 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2829 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2830 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2831 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2832 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2833 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2842 Return data element in an Array by its Index.
2844 @param Array The data array.
2845 @param Type Type of the data in this array.
2846 @param Index Zero based index for data in this array.
2848 @retval Value The data to be returned
2860 ASSERT (Array
!= NULL
);
2864 case EFI_IFR_TYPE_NUM_SIZE_8
:
2865 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
2868 case EFI_IFR_TYPE_NUM_SIZE_16
:
2869 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
2872 case EFI_IFR_TYPE_NUM_SIZE_32
:
2873 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
2876 case EFI_IFR_TYPE_NUM_SIZE_64
:
2877 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
2889 Set value of a data element in an Array by its Index.
2891 @param Array The data array.
2892 @param Type Type of the data in this array.
2893 @param Index Zero based index for data in this array.
2894 @param Value The value to be set.
2906 ASSERT (Array
!= NULL
);
2909 case EFI_IFR_TYPE_NUM_SIZE_8
:
2910 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
2913 case EFI_IFR_TYPE_NUM_SIZE_16
:
2914 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
2917 case EFI_IFR_TYPE_NUM_SIZE_32
:
2918 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
2921 case EFI_IFR_TYPE_NUM_SIZE_64
:
2922 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
2931 Search an Option of a Question by its value.
2933 @param Question The Question
2934 @param OptionValue Value for Option to be searched.
2936 @retval Pointer Pointer to the found Option.
2937 @retval NULL Option not found.
2942 IN FORM_BROWSER_STATEMENT
*Question
,
2943 IN EFI_HII_VALUE
*OptionValue
2947 QUESTION_OPTION
*Option
;
2950 Link
= GetFirstNode (&Question
->OptionListHead
);
2951 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2952 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2954 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
2956 // Check the suppressif condition, only a valid option can be return.
2958 if ((Option
->SuppressExpression
== NULL
) ||
2959 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
2964 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2972 Reset Question to its default value.
2974 @param FormSet The form set.
2975 @param Form The form.
2976 @param Question The question.
2977 @param DefaultId The Class of the default.
2979 @retval EFI_SUCCESS Question is reset to default value.
2983 GetQuestionDefault (
2984 IN FORM_BROWSER_FORMSET
*FormSet
,
2985 IN FORM_BROWSER_FORM
*Form
,
2986 IN FORM_BROWSER_STATEMENT
*Question
,
2992 QUESTION_DEFAULT
*Default
;
2993 QUESTION_OPTION
*Option
;
2994 EFI_HII_VALUE
*HiiValue
;
2996 EFI_STRING StrValue
;
2997 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2998 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3001 Status
= EFI_NOT_FOUND
;
3005 // Statement don't have storage, skip them
3007 if (Question
->QuestionId
== 0) {
3012 // There are Five ways to specify default value for a Question:
3013 // 1, use call back function (highest priority)
3014 // 2, use ExtractConfig function
3015 // 3, use nested EFI_IFR_DEFAULT
3016 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3017 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3019 HiiValue
= &Question
->HiiValue
;
3022 // Get Question defaut value from call back function.
3024 ConfigAccess
= FormSet
->ConfigAccess
;
3025 Action
= GetDefaultIdForCallBack (DefaultId
);
3026 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3027 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3028 Status
= ConfigAccess
->Callback (
3031 Question
->QuestionId
,
3036 if (!EFI_ERROR (Status
)) {
3042 // Get default value from altcfg string.
3044 if (ConfigAccess
!= NULL
) {
3045 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3046 if (!EFI_ERROR (Status
)) {
3052 // EFI_IFR_DEFAULT has highest priority
3054 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3055 Link
= GetFirstNode (&Question
->DefaultListHead
);
3056 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3057 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3059 if (Default
->DefaultId
== DefaultId
) {
3060 if (Default
->ValueExpression
!= NULL
) {
3062 // Default is provided by an Expression, evaluate it
3064 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3065 if (EFI_ERROR (Status
)) {
3069 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3070 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3071 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3072 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3073 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3075 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3076 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3078 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3080 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3081 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3084 // Default value is embedded in EFI_IFR_DEFAULT
3086 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3089 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3090 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3091 if (StrValue
== NULL
) {
3092 return EFI_NOT_FOUND
;
3094 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3095 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3097 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3104 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3109 // EFI_ONE_OF_OPTION
3111 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3112 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3114 // OneOfOption could only provide Standard and Manufacturing default
3116 Link
= GetFirstNode (&Question
->OptionListHead
);
3117 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3118 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3119 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3121 if ((Option
->SuppressExpression
!= NULL
) &&
3122 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3126 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3127 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3129 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3138 // EFI_IFR_CHECKBOX - lowest priority
3140 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3141 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3143 // Checkbox could only provide Standard and Manufacturing default
3145 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3146 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3148 HiiValue
->Value
.b
= TRUE
;
3150 HiiValue
->Value
.b
= FALSE
;
3158 // For Questions without default
3160 Status
= EFI_NOT_FOUND
;
3161 switch (Question
->Operand
) {
3162 case EFI_IFR_NUMERIC_OP
:
3164 // Take minimum value as numeric default value
3166 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3167 HiiValue
->Value
.u64
= Question
->Minimum
;
3168 Status
= EFI_SUCCESS
;
3172 case EFI_IFR_ONE_OF_OP
:
3174 // Take first oneof option as oneof's default value
3176 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3177 Link
= GetFirstNode (&Question
->OptionListHead
);
3178 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3179 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3180 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3182 if ((Option
->SuppressExpression
!= NULL
) &&
3183 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3187 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3188 Status
= EFI_SUCCESS
;
3194 case EFI_IFR_ORDERED_LIST_OP
:
3196 // Take option sequence in IFR as ordered list's default value
3199 Link
= GetFirstNode (&Question
->OptionListHead
);
3200 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3201 Status
= EFI_SUCCESS
;
3202 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3203 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3205 if ((Option
->SuppressExpression
!= NULL
) &&
3206 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3210 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3213 if (Index
>= Question
->MaxContainers
) {
3228 Reset Questions to their initial value or default value in a Form, Formset or System.
3230 GetDefaultValueScope parameter decides which questions will reset
3231 to its default value.
3233 @param FormSet FormSet data structure.
3234 @param Form Form data structure.
3235 @param DefaultId The Class of the default.
3236 @param SettingScope Setting Scope for Default action.
3237 @param GetDefaultValueScope Get default value scope.
3238 @param Storage Get default value only for this storage.
3239 @param RetrieveValueFirst Whether call the retrieve call back to
3240 get the initial value before get default
3243 @retval EFI_SUCCESS The function completed successfully.
3244 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3249 IN FORM_BROWSER_FORMSET
*FormSet
,
3250 IN FORM_BROWSER_FORM
*Form
,
3251 IN UINT16 DefaultId
,
3252 IN BROWSER_SETTING_SCOPE SettingScope
,
3253 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3254 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3255 IN BOOLEAN RetrieveValueFirst
3259 LIST_ENTRY
*FormLink
;
3261 FORM_BROWSER_STATEMENT
*Question
;
3262 FORM_BROWSER_FORMSET
*LocalFormSet
;
3263 FORM_BROWSER_FORMSET
*OldFormSet
;
3265 Status
= EFI_SUCCESS
;
3268 // Check the supported setting level.
3270 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3271 return EFI_UNSUPPORTED
;
3274 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3275 return EFI_UNSUPPORTED
;
3278 if (SettingScope
== FormLevel
) {
3280 // Extract Form default
3282 Link
= GetFirstNode (&Form
->StatementListHead
);
3283 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3284 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3285 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3288 // If get default value only for this storage, check the storage first.
3290 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3295 // If get default value only for no storage question, just skip the question which has storage.
3297 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3302 // If Question is disabled, don't reset it to default
3304 if (Question
->Expression
!= NULL
) {
3305 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3310 if (RetrieveValueFirst
) {
3312 // Call the Retrieve call back to get the initial question value.
3314 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3318 // If not request to get the initial value or get initial value fail, then get default value.
3320 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3321 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3322 if (EFI_ERROR (Status
)) {
3328 // Synchronize Buffer storage's Edit buffer
3330 if ((Question
->Storage
!= NULL
) &&
3331 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3332 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3335 } else if (SettingScope
== FormSetLevel
) {
3336 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3337 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3338 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3339 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3340 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3342 } else if (SettingScope
== SystemLevel
) {
3344 // Preload all Hii formset.
3346 LoadAllHiiFormset();
3348 OldFormSet
= mSystemLevelFormSet
;
3351 // Set Default Value for each FormSet in the maintain list.
3353 Link
= GetFirstNode (&gBrowserFormSetList
);
3354 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3355 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3356 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3357 if (!ValidateFormSet(LocalFormSet
)) {
3361 mSystemLevelFormSet
= LocalFormSet
;
3363 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3366 mSystemLevelFormSet
= OldFormSet
;
3374 Validate whether this question's value has changed.
3376 @param FormSet FormSet data structure.
3377 @param Form Form data structure.
3378 @param Question Question to be initialized.
3379 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3381 @retval TRUE Question's value has changed.
3382 @retval FALSE Question's value has not changed
3386 IsQuestionValueChanged (
3387 IN FORM_BROWSER_FORMSET
*FormSet
,
3388 IN FORM_BROWSER_FORM
*Form
,
3389 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3390 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3393 EFI_HII_VALUE BackUpValue
;
3394 CHAR8
*BackUpBuffer
;
3396 BOOLEAN ValueChanged
;
3400 // For quetion without storage, always mark it as data not changed.
3402 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3406 BackUpBuffer
= NULL
;
3407 ValueChanged
= FALSE
;
3409 switch (Question
->Operand
) {
3410 case EFI_IFR_ORDERED_LIST_OP
:
3411 BufferWidth
= Question
->StorageWidth
;
3412 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3413 ASSERT (BackUpBuffer
!= NULL
);
3416 case EFI_IFR_STRING_OP
:
3417 case EFI_IFR_PASSWORD_OP
:
3418 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3419 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3420 ASSERT (BackUpBuffer
!= NULL
);
3427 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3429 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3430 ASSERT_EFI_ERROR(Status
);
3432 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3433 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3434 ValueChanged
= TRUE
;
3437 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3438 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3440 if (BackUpBuffer
!= NULL
) {
3441 FreePool (BackUpBuffer
);
3444 Question
->ValueChanged
= ValueChanged
;
3446 return ValueChanged
;
3450 Initialize Question's Edit copy from Storage.
3452 @param Selection Selection contains the information about
3453 the Selection, form and formset to be displayed.
3454 Selection action may be updated in retrieve callback.
3455 If Selection is NULL, only initialize Question value.
3456 @param FormSet FormSet data structure.
3457 @param Form Form data structure.
3459 @retval EFI_SUCCESS The function completed successfully.
3464 IN OUT UI_MENU_SELECTION
*Selection
,
3465 IN FORM_BROWSER_FORMSET
*FormSet
,
3466 IN FORM_BROWSER_FORM
*Form
3471 FORM_BROWSER_STATEMENT
*Question
;
3475 Link
= GetFirstNode (&Form
->StatementListHead
);
3476 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3477 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3480 // Initialize local copy of Value for each Question
3482 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3483 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3485 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3487 if (EFI_ERROR (Status
)) {
3491 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3492 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3496 // Call the Retrieve call back function for all questions.
3498 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3499 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
3500 !gFinishRetrieveCall
) {
3502 // Check QuestionValue does exist.
3504 StorageWidth
= Question
->StorageWidth
;
3505 if (Question
->BufferValue
!= NULL
) {
3506 BufferValue
= Question
->BufferValue
;
3508 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3512 // For efivarstore storage, initial question value first.
3514 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3515 Status
= gRT
->GetVariable (
3516 Question
->VariableName
,
3517 &Question
->Storage
->Guid
,
3524 Status
= ProcessCallBackFunction(Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3527 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3534 Initialize Question's Edit copy from Storage for the whole Formset.
3536 @param Selection Selection contains the information about
3537 the Selection, form and formset to be displayed.
3538 Selection action may be updated in retrieve callback.
3539 If Selection is NULL, only initialize Question value.
3540 @param FormSet FormSet data structure.
3542 @retval EFI_SUCCESS The function completed successfully.
3547 IN OUT UI_MENU_SELECTION
*Selection
,
3548 IN FORM_BROWSER_FORMSET
*FormSet
3553 FORM_BROWSER_FORM
*Form
;
3555 Link
= GetFirstNode (&FormSet
->FormListHead
);
3556 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3557 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3560 // Initialize local copy of Value for each Form
3562 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3563 if (EFI_ERROR (Status
)) {
3567 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3571 // Finished question initialization.
3573 FormSet
->QuestionInited
= TRUE
;
3579 Remove the Request element from the Config Request.
3581 @param Storage Pointer to the browser storage.
3582 @param RequestElement The pointer to the Request element.
3587 IN OUT BROWSER_STORAGE
*Storage
,
3588 IN CHAR16
*RequestElement
3594 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3596 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3598 if (NewStr
== NULL
) {
3603 // Remove this element from this ConfigRequest.
3606 NewStr
+= StrLen (RequestElement
);
3607 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3609 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3613 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3615 @param Storage Pointer to the browser storage.
3616 @param ConfigRequest The pointer to the Request element.
3620 RemoveConfigRequest (
3621 BROWSER_STORAGE
*Storage
,
3622 CHAR16
*ConfigRequest
3625 CHAR16
*RequestElement
;
3626 CHAR16
*NextRequestElement
;
3630 // No request element in it, just return.
3632 if (ConfigRequest
== NULL
) {
3636 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3638 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3643 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3645 SearchKey
= L
"&OFFSET";
3649 // Find SearchKey storage
3651 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3652 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3653 ASSERT (RequestElement
!= NULL
);
3654 RequestElement
= StrStr (RequestElement
, SearchKey
);
3656 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3659 while (RequestElement
!= NULL
) {
3661 // +1 to avoid find header itself.
3663 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3666 // The last Request element in configRequest string.
3668 if (NextRequestElement
!= NULL
) {
3670 // Replace "&" with '\0'.
3672 *NextRequestElement
= L
'\0';
3675 RemoveElement (Storage
, RequestElement
);
3677 if (NextRequestElement
!= NULL
) {
3679 // Restore '&' with '\0' for later used.
3681 *NextRequestElement
= L
'&';
3684 RequestElement
= NextRequestElement
;
3688 // If no request element remain, just remove the ConfigRequest string.
3690 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3691 FreePool (Storage
->ConfigRequest
);
3692 Storage
->ConfigRequest
= NULL
;
3693 Storage
->SpareStrLen
= 0;
3698 Base on the current formset info, clean the ConfigRequest string in browser storage.
3700 @param FormSet Pointer of the FormSet
3704 CleanBrowserStorage (
3705 IN OUT FORM_BROWSER_FORMSET
*FormSet
3709 FORMSET_STORAGE
*Storage
;
3710 CHAR16
*ConfigRequest
;
3712 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3713 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3714 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3715 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3717 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3718 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3722 ConfigRequest
= FormSet
->QuestionInited
? Storage
->ConfigRequest
: Storage
->ConfigElements
;
3723 RemoveConfigRequest (Storage
->BrowserStorage
, ConfigRequest
);
3724 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3725 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3726 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
3727 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
3728 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
3730 Storage
->BrowserStorage
->Initialized
= FALSE
;
3736 Check whether current element in the ConfigReqeust string.
3738 @param BrowserStorage Storage which includes ConfigReqeust.
3739 @param RequestElement New element need to check.
3741 @retval TRUE The Element is in the ConfigReqeust string.
3742 @retval FALSE The Element not in the configReqeust String.
3747 BROWSER_STORAGE
*BrowserStorage
,
3748 CHAR16
*RequestElement
3751 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3755 Append the Request element to the Config Request.
3757 @param ConfigRequest Current ConfigRequest info.
3758 @param SpareStrLen Current remain free buffer for config reqeust.
3759 @param RequestElement New Request element.
3763 AppendConfigRequest (
3764 IN OUT CHAR16
**ConfigRequest
,
3765 IN OUT UINTN
*SpareStrLen
,
3766 IN CHAR16
*RequestElement
3773 StrLength
= StrLen (RequestElement
);
3776 // Append <RequestElement> to <ConfigRequest>
3778 if (StrLength
> *SpareStrLen
) {
3780 // Old String buffer is not sufficient for RequestElement, allocate a new one
3782 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3783 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3784 ASSERT (NewStr
!= NULL
);
3786 if (*ConfigRequest
!= NULL
) {
3787 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3788 FreePool (*ConfigRequest
);
3790 *ConfigRequest
= NewStr
;
3791 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3794 StrCat (*ConfigRequest
, RequestElement
);
3795 *SpareStrLen
-= StrLength
;
3799 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3801 @param Storage Form set Storage.
3803 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3804 @retval FALSE All elements covered by current used elements.
3808 ConfigRequestAdjust (
3809 IN FORMSET_STORAGE
*Storage
3812 CHAR16
*RequestElement
;
3813 CHAR16
*NextRequestElement
;
3823 if (Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3824 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3825 if (Storage
->ConfigElements
!= NULL
) {
3826 FreePool (Storage
->ConfigElements
);
3828 Storage
->ConfigElements
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3832 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3834 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3839 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3841 SearchKey
= L
"&OFFSET";
3845 // Prepare the config header.
3847 RetBuf
= AllocateCopyPool(StrSize (Storage
->BrowserStorage
->ConfigHdr
), Storage
->BrowserStorage
->ConfigHdr
);
3848 ASSERT (RetBuf
!= NULL
);
3851 // Find SearchKey storage
3853 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3854 RequestElement
= StrStr (Storage
->ConfigRequest
, L
"PATH");
3855 ASSERT (RequestElement
!= NULL
);
3856 RequestElement
= StrStr (RequestElement
, SearchKey
);
3858 RequestElement
= StrStr (Storage
->ConfigRequest
, SearchKey
);
3861 while (RequestElement
!= NULL
) {
3863 // +1 to avoid find header itself.
3865 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3868 // The last Request element in configRequest string.
3870 if (NextRequestElement
!= NULL
) {
3872 // Replace "&" with '\0'.
3874 *NextRequestElement
= L
'\0';
3877 if (!ElementValidation (Storage
->BrowserStorage
, RequestElement
)) {
3879 // Add this element to the Storage->BrowserStorage->AllRequestElement.
3881 AppendConfigRequest(&Storage
->BrowserStorage
->ConfigRequest
, &Storage
->BrowserStorage
->SpareStrLen
, RequestElement
);
3882 AppendConfigRequest (&RetBuf
, &SpareBufLen
, RequestElement
);
3886 if (NextRequestElement
!= NULL
) {
3888 // Restore '&' with '\0' for later used.
3890 *NextRequestElement
= L
'&';
3893 RequestElement
= NextRequestElement
;
3897 if (Storage
->ConfigElements
!= NULL
) {
3898 FreePool (Storage
->ConfigElements
);
3900 Storage
->ConfigElements
= RetBuf
;
3910 Base on ConfigRequest info to get default value for current formset.
3912 ConfigRequest info include the info about which questions in current formset need to
3913 get default value. This function only get these questions default value.
3915 @param FormSet FormSet data structure.
3916 @param Storage Storage need to update value.
3917 @param ConfigRequest The config request string.
3921 GetDefaultForFormset (
3922 IN FORM_BROWSER_FORMSET
*FormSet
,
3923 IN BROWSER_STORAGE
*Storage
,
3924 IN CHAR16
*ConfigRequest
3929 LIST_ENTRY BackUpList
;
3930 NAME_VALUE_NODE
*Node
;
3932 LIST_ENTRY
*NodeLink
;
3933 NAME_VALUE_NODE
*TmpNode
;
3935 EFI_STRING Progress
;
3939 InitializeListHead(&BackUpList
);
3942 // Back update the edit buffer.
3944 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3945 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3946 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
3947 ASSERT (BackUpBuf
!= NULL
);
3948 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3949 Link
= GetFirstNode (&Storage
->NameValueListHead
);
3950 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
3951 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
3952 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
3955 // Only back Node belong to this formset.
3957 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
3961 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
3962 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
3963 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
3965 InsertTailList(&BackUpList
, &TmpNode
->Link
);
3970 // Get default value.
3972 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
3975 // Update the question value based on the input ConfigRequest.
3977 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3978 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3979 ASSERT (BackUpBuf
!= NULL
);
3980 BufferSize
= Storage
->Size
;
3981 Status
= mHiiConfigRouting
->BlockToConfig(
3984 Storage
->EditBuffer
,
3989 ASSERT_EFI_ERROR (Status
);
3991 Status
= mHiiConfigRouting
->ConfigToBlock (
3998 ASSERT_EFI_ERROR (Status
);
4000 if (Result
!= NULL
) {
4004 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4005 FreePool (BackUpBuf
);
4006 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4008 // Update question value, only element in ConfigReqeust will be update.
4010 Link
= GetFirstNode (&BackUpList
);
4011 while (!IsNull (&BackUpList
, Link
)) {
4012 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4013 Link
= GetNextNode (&BackUpList
, Link
);
4015 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4019 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4020 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4021 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4022 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4024 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4028 FreePool (TmpNode
->EditValue
);
4029 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4031 RemoveEntryList (&Node
->Link
);
4032 FreePool (Node
->EditValue
);
4033 FreePool (Node
->Name
);
4039 // Restore the Name/Value node.
4041 Link
= GetFirstNode (&BackUpList
);
4042 while (!IsNull (&BackUpList
, Link
)) {
4043 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4044 Link
= GetNextNode (&BackUpList
, Link
);
4049 RemoveEntryList (&Node
->Link
);
4050 FreePool (Node
->EditValue
);
4051 FreePool (Node
->Name
);
4058 Fill storage's edit copy with settings requested from Configuration Driver.
4060 @param FormSet FormSet data structure.
4061 @param Storage Buffer Storage.
4066 IN FORM_BROWSER_FORMSET
*FormSet
,
4067 IN FORMSET_STORAGE
*Storage
4071 EFI_STRING Progress
;
4074 EFI_STRING ConfigRequest
;
4077 ConfigRequest
= NULL
;
4079 switch (Storage
->BrowserStorage
->Type
) {
4080 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4083 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4084 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4085 ConfigRequestAdjust(Storage
);
4090 case EFI_HII_VARSTORE_BUFFER
:
4091 case EFI_HII_VARSTORE_NAME_VALUE
:
4093 // Skip if there is no RequestElement.
4095 if (Storage
->ElementCount
== 0) {
4100 // Just update the ConfigRequest, if storage already initialized.
4102 if (Storage
->BrowserStorage
->Initialized
) {
4103 ConfigRequestAdjust(Storage
);
4107 Storage
->BrowserStorage
->Initialized
= TRUE
;
4114 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4116 // Create the config request string to get all fields for this storage.
4117 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4118 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4120 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4121 ConfigRequest
= AllocateZeroPool (StrLen
);
4122 ASSERT (ConfigRequest
!= NULL
);
4126 L
"%s&OFFSET=0&WIDTH=%04x",
4127 Storage
->BrowserStorage
->ConfigHdr
,
4128 Storage
->BrowserStorage
->Size
);
4130 ConfigRequest
= Storage
->ConfigRequest
;
4134 // Request current settings from Configuration Driver
4136 Status
= mHiiConfigRouting
->ExtractConfig (
4144 // If get value fail, extract default from IFR binary
4146 if (EFI_ERROR (Status
)) {
4147 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4150 // Convert Result from <ConfigAltResp> to <ConfigResp>
4152 StrPtr
= StrStr (Result
, L
"&GUID=");
4153 if (StrPtr
!= NULL
) {
4157 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4161 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4164 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4166 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4168 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4169 if (ConfigRequest
!= NULL
) {
4170 FreePool (ConfigRequest
);
4176 Get Value changed status from old question.
4178 @param NewFormSet FormSet data structure.
4179 @param OldQuestion Old question which has value changed.
4183 SyncStatusForQuestion (
4184 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4185 IN FORM_BROWSER_STATEMENT
*OldQuestion
4189 LIST_ENTRY
*QuestionLink
;
4190 FORM_BROWSER_FORM
*Form
;
4191 FORM_BROWSER_STATEMENT
*Question
;
4194 // For each form in one formset.
4196 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4197 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4198 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4199 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
4202 // for each question in one form.
4204 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4205 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4206 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4207 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4209 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
4210 Question
->ValueChanged
= TRUE
;
4218 Get Value changed status from old formset.
4220 @param NewFormSet FormSet data structure.
4221 @param OldFormSet FormSet data structure.
4225 SyncStatusForFormSet (
4226 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4227 IN FORM_BROWSER_FORMSET
*OldFormSet
4231 LIST_ENTRY
*QuestionLink
;
4232 FORM_BROWSER_FORM
*Form
;
4233 FORM_BROWSER_STATEMENT
*Question
;
4236 // For each form in one formset.
4238 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
4239 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
4240 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4241 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
4244 // for each question in one form.
4246 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4247 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4248 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4249 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4251 if (!Question
->ValueChanged
) {
4256 // Find the same question in new formset and update the value changed flag.
4258 SyncStatusForQuestion (NewFormSet
, Question
);
4264 Get current setting of Questions.
4266 @param FormSet FormSet data structure.
4270 InitializeCurrentSetting (
4271 IN OUT FORM_BROWSER_FORMSET
*FormSet
4275 FORMSET_STORAGE
*Storage
;
4276 FORM_BROWSER_FORMSET
*OldFormSet
;
4279 // Try to find pre FormSet in the maintain backup list.
4280 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4282 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4283 if (OldFormSet
!= NULL
) {
4284 SyncStatusForFormSet (FormSet
, OldFormSet
);
4285 RemoveEntryList (&OldFormSet
->Link
);
4286 DestroyFormSet (OldFormSet
);
4288 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4291 // Extract default from IFR binary for no storage questions.
4293 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4296 // Request current settings from Configuration Driver
4298 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4299 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4300 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4302 LoadStorage (FormSet
, Storage
);
4304 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4310 Fetch the Ifr binary data of a FormSet.
4312 @param Handle PackageList Handle
4313 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4314 specified (NULL or zero GUID), take the first
4315 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4316 found in package list.
4317 On output, GUID of the formset found(if not NULL).
4318 @param BinaryLength The length of the FormSet IFR binary.
4319 @param BinaryData The buffer designed to receive the FormSet.
4321 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4322 BufferLength was updated.
4323 @retval EFI_INVALID_PARAMETER The handle is unknown.
4324 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4325 be found with the requested FormId.
4330 IN EFI_HII_HANDLE Handle
,
4331 IN OUT EFI_GUID
*FormSetGuid
,
4332 OUT UINTN
*BinaryLength
,
4333 OUT UINT8
**BinaryData
4337 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4343 UINT32 PackageListLength
;
4344 EFI_HII_PACKAGE_HEADER PackageHeader
;
4346 UINT8 NumberOfClassGuid
;
4347 BOOLEAN ClassGuidMatch
;
4348 EFI_GUID
*ClassGuid
;
4349 EFI_GUID
*ComparingGuid
;
4353 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4356 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4358 if (FormSetGuid
== NULL
) {
4359 ComparingGuid
= &gZeroGuid
;
4361 ComparingGuid
= FormSetGuid
;
4365 // Get HII PackageList
4368 HiiPackageList
= NULL
;
4369 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4370 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4371 HiiPackageList
= AllocatePool (BufferSize
);
4372 ASSERT (HiiPackageList
!= NULL
);
4374 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4376 if (EFI_ERROR (Status
)) {
4379 ASSERT (HiiPackageList
!= NULL
);
4382 // Get Form package from this HII package List
4384 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4386 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4388 ClassGuidMatch
= FALSE
;
4389 while (Offset
< PackageListLength
) {
4390 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4391 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4393 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4395 // Search FormSet in this Form Package
4397 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4398 while (Offset2
< PackageHeader
.Length
) {
4399 OpCodeData
= Package
+ Offset2
;
4401 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4403 // Try to compare against formset GUID
4405 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4406 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4410 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4412 // Try to compare against formset class GUID
4414 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4415 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4416 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4417 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4418 ClassGuidMatch
= TRUE
;
4422 if (ClassGuidMatch
) {
4425 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4426 ClassGuidMatch
= TRUE
;
4431 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4434 if (Offset2
< PackageHeader
.Length
) {
4436 // Target formset found
4442 Offset
+= PackageHeader
.Length
;
4445 if (Offset
>= PackageListLength
) {
4447 // Form package not found in this Package List
4449 FreePool (HiiPackageList
);
4450 return EFI_NOT_FOUND
;
4453 if (FormSetGuid
!= NULL
) {
4455 // Return the FormSet GUID
4457 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4461 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4462 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4463 // of the Form Package.
4465 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4466 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4468 FreePool (HiiPackageList
);
4470 if (*BinaryData
== NULL
) {
4471 return EFI_OUT_OF_RESOURCES
;
4479 Initialize the internal data structure of a FormSet.
4481 @param Handle PackageList Handle
4482 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4483 specified (NULL or zero GUID), take the first
4484 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4485 found in package list.
4486 On output, GUID of the formset found(if not NULL).
4487 @param FormSet FormSet data structure.
4489 @retval EFI_SUCCESS The function completed successfully.
4490 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4495 IN EFI_HII_HANDLE Handle
,
4496 IN OUT EFI_GUID
*FormSetGuid
,
4497 OUT FORM_BROWSER_FORMSET
*FormSet
4501 EFI_HANDLE DriverHandle
;
4503 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4504 if (EFI_ERROR (Status
)) {
4508 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4509 FormSet
->HiiHandle
= Handle
;
4510 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4511 FormSet
->QuestionInited
= FALSE
;
4514 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4516 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4517 if (EFI_ERROR (Status
)) {
4520 FormSet
->DriverHandle
= DriverHandle
;
4521 Status
= gBS
->HandleProtocol (
4523 &gEfiHiiConfigAccessProtocolGuid
,
4524 (VOID
**) &FormSet
->ConfigAccess
4526 if (EFI_ERROR (Status
)) {
4528 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4529 // list, then there will be no configuration action required
4531 FormSet
->ConfigAccess
= NULL
;
4535 // Parse the IFR binary OpCodes
4537 Status
= ParseOpCodes (FormSet
);
4544 Save globals used by previous call to SendForm(). SendForm() may be called from
4545 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4546 So, save globals of previous call to SendForm() and restore them upon exit.
4550 SaveBrowserContext (
4554 BROWSER_CONTEXT
*Context
;
4555 FORM_ENTRY_INFO
*MenuList
;
4557 gBrowserContextCount
++;
4558 if (gBrowserContextCount
== 1) {
4560 // This is not reentry of SendForm(), no context to save
4565 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4566 ASSERT (Context
!= NULL
);
4568 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4571 // Save FormBrowser context
4573 Context
->Selection
= gCurrentSelection
;
4574 Context
->ResetRequired
= gResetRequired
;
4575 Context
->ExitRequired
= gExitRequired
;
4576 Context
->HiiHandle
= mCurrentHiiHandle
;
4577 Context
->FormId
= mCurrentFormId
;
4578 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4581 // Save the menu history data.
4583 InitializeListHead(&Context
->FormHistoryList
);
4584 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4585 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4586 RemoveEntryList (&MenuList
->Link
);
4588 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4592 // Insert to FormBrowser context list
4594 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4599 Restore globals used by previous call to SendForm().
4603 RestoreBrowserContext (
4608 BROWSER_CONTEXT
*Context
;
4609 FORM_ENTRY_INFO
*MenuList
;
4611 ASSERT (gBrowserContextCount
!= 0);
4612 gBrowserContextCount
--;
4613 if (gBrowserContextCount
== 0) {
4615 // This is not reentry of SendForm(), no context to restore
4620 ASSERT (!IsListEmpty (&gBrowserContextList
));
4622 Link
= GetFirstNode (&gBrowserContextList
);
4623 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4626 // Restore FormBrowser context
4628 gCurrentSelection
= Context
->Selection
;
4629 gResetRequired
= Context
->ResetRequired
;
4630 gExitRequired
= Context
->ExitRequired
;
4631 mCurrentHiiHandle
= Context
->HiiHandle
;
4632 mCurrentFormId
= Context
->FormId
;
4633 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4636 // Restore the menu history data.
4638 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4639 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4640 RemoveEntryList (&MenuList
->Link
);
4642 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4646 // Remove from FormBrowser context list
4648 RemoveEntryList (&Context
->Link
);
4649 gBS
->FreePool (Context
);
4653 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4655 @param Handle The Hii Handle.
4657 @return the found FormSet context. If no found, NULL will return.
4660 FORM_BROWSER_FORMSET
*
4661 GetFormSetFromHiiHandle (
4662 EFI_HII_HANDLE Handle
4666 FORM_BROWSER_FORMSET
*FormSet
;
4668 Link
= GetFirstNode (&gBrowserFormSetList
);
4669 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4670 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4671 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4672 if (!ValidateFormSet(FormSet
)) {
4675 if (FormSet
->HiiHandle
== Handle
) {
4684 Check whether the input HII handle is the FormSet that is being used.
4686 @param Handle The Hii Handle.
4688 @retval TRUE HII handle is being used.
4689 @retval FALSE HII handle is not being used.
4693 IsHiiHandleInBrowserContext (
4694 EFI_HII_HANDLE Handle
4698 BROWSER_CONTEXT
*Context
;
4701 // HiiHandle is Current FormSet.
4703 if (mCurrentHiiHandle
== Handle
) {
4708 // Check whether HiiHandle is in BrowserContext.
4710 Link
= GetFirstNode (&gBrowserContextList
);
4711 while (!IsNull (&gBrowserContextList
, Link
)) {
4712 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4713 if (Context
->HiiHandle
== Handle
) {
4715 // HiiHandle is in BrowserContext
4719 Link
= GetNextNode (&gBrowserContextList
, Link
);
4726 Perform Password check.
4727 Passwork may be encrypted by driver that requires the specific check.
4729 @param Form Form where Password Statement is in.
4730 @param Statement Password statement
4731 @param PasswordString Password string to be checked. It may be NULL.
4732 NULL means to restore password.
4733 "" string can be used to checked whether old password does exist.
4735 @return Status Status of Password check.
4740 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4741 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4742 IN EFI_STRING PasswordString OPTIONAL
4746 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4747 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4748 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4749 FORM_BROWSER_STATEMENT
*Question
;
4751 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4752 Question
= GetBrowserStatement(Statement
);
4753 ASSERT (Question
!= NULL
);
4755 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4756 if (ConfigAccess
== NULL
) {
4757 return EFI_UNSUPPORTED
;
4760 if (PasswordString
== NULL
) {
4765 // Check whether has preexisted password.
4767 if (PasswordString
[0] == 0) {
4768 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
4771 return EFI_NOT_READY
;
4776 // Check whether the input password is same as preexisted password.
4778 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4781 return EFI_NOT_READY
;
4786 // Prepare password string in HII database
4788 if (PasswordString
!= NULL
) {
4789 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4791 IfrTypeValue
.string
= 0;
4795 // Send password to Configuration Driver for validation
4797 Status
= ConfigAccess
->Callback (
4799 EFI_BROWSER_ACTION_CHANGING
,
4800 Question
->QuestionId
,
4801 Question
->HiiValue
.Type
,
4807 // Remove password string from HII database
4809 if (PasswordString
!= NULL
) {
4810 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4817 Find the registered HotKey based on KeyData.
4819 @param[in] KeyData A pointer to a buffer that describes the keystroke
4820 information for the hot key.
4822 @return The registered HotKey context. If no found, NULL will return.
4825 GetHotKeyFromRegisterList (
4826 IN EFI_INPUT_KEY
*KeyData
4830 BROWSER_HOT_KEY
*HotKey
;
4832 Link
= GetFirstNode (&gBrowserHotKeyList
);
4833 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4834 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4835 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4838 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4845 Configure what scope the hot key will impact.
4846 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4847 If no scope is set, the default scope will be FormSet level.
4848 After all registered hot keys are removed, previous Scope can reset to another level.
4850 @param[in] Scope Scope level to be set.
4852 @retval EFI_SUCCESS Scope is set correctly.
4853 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4854 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4860 IN BROWSER_SETTING_SCOPE Scope
4863 if (Scope
>= MaxLevel
) {
4864 return EFI_INVALID_PARAMETER
;
4868 // When no hot key registered in system or on the first setting,
4869 // Scope can be set.
4871 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4872 gBrowserSettingScope
= Scope
;
4873 mBrowserScopeFirstSet
= FALSE
;
4874 } else if (Scope
!= gBrowserSettingScope
) {
4875 return EFI_UNSUPPORTED
;
4882 Register the hot key with its browser action, or unregistered the hot key.
4883 Only support hot key that is not printable character (control key, function key, etc.).
4884 If the action value is zero, the hot key will be unregistered if it has been registered.
4885 If the same hot key has been registered, the new action and help string will override the previous ones.
4887 @param[in] KeyData A pointer to a buffer that describes the keystroke
4888 information for the hot key. Its type is EFI_INPUT_KEY to
4889 be supported by all ConsoleIn devices.
4890 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4891 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4892 @param[in] HelpString Help string that describes the hot key information.
4893 Its value may be NULL for the unregistered hot key.
4895 @retval EFI_SUCCESS Hot key is registered or unregistered.
4896 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4897 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4898 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4903 IN EFI_INPUT_KEY
*KeyData
,
4905 IN UINT16 DefaultId
,
4906 IN EFI_STRING HelpString OPTIONAL
4909 BROWSER_HOT_KEY
*HotKey
;
4912 // Check input parameters.
4914 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4915 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4916 return EFI_INVALID_PARAMETER
;
4920 // Check whether the input KeyData is in BrowserHotKeyList.
4922 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4925 // Unregister HotKey
4927 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4928 if (HotKey
!= NULL
) {
4930 // The registered HotKey is found.
4931 // Remove it from List, and free its resource.
4933 RemoveEntryList (&HotKey
->Link
);
4934 FreePool (HotKey
->KeyData
);
4935 FreePool (HotKey
->HelpString
);
4939 // The registered HotKey is not found.
4941 return EFI_NOT_FOUND
;
4946 // Register HotKey into List.
4948 if (HotKey
== NULL
) {
4950 // Create new Key, and add it into List.
4952 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4953 ASSERT (HotKey
!= NULL
);
4954 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4955 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4956 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4960 // Fill HotKey information.
4962 HotKey
->Action
= Action
;
4963 HotKey
->DefaultId
= DefaultId
;
4964 if (HotKey
->HelpString
!= NULL
) {
4965 FreePool (HotKey
->HelpString
);
4967 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4973 Register Exit handler function.
4974 When more than one handler function is registered, the latter one will override the previous one.
4975 When NULL handler is specified, the previous Exit handler will be unregistered.
4977 @param[in] Handler Pointer to handler function.
4982 RegiserExitHandler (
4983 IN EXIT_HANDLER Handler
4986 ExitHandlerFunction
= Handler
;
4991 Check whether the browser data has been modified.
4993 @retval TRUE Browser data is modified.
4994 @retval FALSE No browser data is modified.
4999 IsBrowserDataModified (
5004 FORM_BROWSER_FORMSET
*FormSet
;
5006 switch (gBrowserSettingScope
) {
5008 if (gCurrentSelection
== NULL
) {
5011 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5014 if (gCurrentSelection
== NULL
) {
5017 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5020 Link
= GetFirstNode (&gBrowserFormSetList
);
5021 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5022 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5023 if (!ValidateFormSet(FormSet
)) {
5027 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5030 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5040 Execute the action requested by the Action parameter.
5042 @param[in] Action Execute the request action.
5043 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5045 @retval EFI_SUCCESS Execute the request action succss.
5046 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5057 FORM_BROWSER_FORMSET
*FormSet
;
5058 FORM_BROWSER_FORM
*Form
;
5060 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5061 return EFI_NOT_READY
;
5064 Status
= EFI_SUCCESS
;
5067 if (gBrowserSettingScope
< SystemLevel
) {
5068 FormSet
= gCurrentSelection
->FormSet
;
5069 Form
= gCurrentSelection
->Form
;
5073 // Executet the discard action.
5075 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5076 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5077 if (EFI_ERROR (Status
)) {
5083 // Executet the difault action.
5085 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5086 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5087 if (EFI_ERROR (Status
)) {
5090 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5094 // Executet the submit action.
5096 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5097 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5098 if (EFI_ERROR (Status
)) {
5104 // Executet the reset action.
5106 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5107 gResetRequired
= TRUE
;
5111 // Executet the exit action.
5113 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5114 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5115 if (gBrowserSettingScope
== SystemLevel
) {
5116 if (ExitHandlerFunction
!= NULL
) {
5117 ExitHandlerFunction ();
5121 gExitRequired
= TRUE
;
5128 Create reminder to let user to choose save or discard the changed browser data.
5129 Caller can use it to actively check the changed browser data.
5131 @retval BROWSER_NO_CHANGES No browser data is changed.
5132 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5133 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5134 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5144 FORM_BROWSER_FORMSET
*FormSet
;
5145 BOOLEAN IsDataChanged
;
5146 UINT32 DataSavedAction
;
5149 DataSavedAction
= BROWSER_NO_CHANGES
;
5150 IsDataChanged
= FALSE
;
5151 Link
= GetFirstNode (&gBrowserFormSetList
);
5152 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5153 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5154 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5155 if (!ValidateFormSet(FormSet
)) {
5158 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5159 IsDataChanged
= TRUE
;
5165 // No data is changed. No save is required.
5167 if (!IsDataChanged
) {
5168 return DataSavedAction
;
5172 // If data is changed, prompt user to save or discard it.
5175 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5177 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5178 SubmitForm (NULL
, NULL
, SystemLevel
);
5179 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5181 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5182 DiscardForm (NULL
, NULL
, SystemLevel
);
5183 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5185 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5186 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5191 return DataSavedAction
;