2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2013, 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 gResetRequired
;
52 BOOLEAN gExitRequired
;
53 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
54 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
55 EXIT_HANDLER ExitHandlerFunction
= NULL
;
58 // Browser Global Strings
62 CHAR16
*mUnknownString
= L
"!";
64 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
65 EFI_GUID gSetupBrowserGuid
= {
66 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
69 FORM_BROWSER_FORMSET
*gOldFormSet
= NULL
;
70 extern UINT32 gBrowserStatus
;
71 extern CHAR16
*gErrorInfo
;
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
;
262 // Get all the Hii handles
264 HiiHandles
= HiiGetHiiHandles (NULL
);
265 ASSERT (HiiHandles
!= NULL
);
268 // Search for formset of each class type
270 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
272 // Check HiiHandles[Index] does exist in global maintain list.
274 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
279 // Initilize FormSet Setting
281 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
282 ASSERT (LocalFormSet
!= NULL
);
283 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
284 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
285 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
286 DestroyFormSet (LocalFormSet
);
289 InitializeCurrentSetting (LocalFormSet
);
292 // Initilize Questions' Value
294 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
295 if (EFI_ERROR (Status
)) {
296 DestroyFormSet (LocalFormSet
);
302 // Free resources, and restore gOldFormSet and gClassOfVfr
304 FreePool (HiiHandles
);
308 This is the routine which an external caller uses to direct the browser
309 where to obtain it's information.
312 @param This The Form Browser protocol instanse.
313 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
314 display a list of the formsets for the handles specified.
315 @param HandleCount The number of Handles specified in Handle.
316 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
317 field in the EFI_IFR_FORM_SET op-code for the specified
318 forms-based package. If FormSetGuid is NULL, then this
319 function will display the first found forms package.
320 @param FormId This field specifies which EFI_IFR_FORM to render as the first
321 displayable page. If this field has a value of 0x0000, then
322 the forms browser will render the specified forms in their encoded order.
323 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
325 @param ActionRequest Points to the action recommended by the form.
327 @retval EFI_SUCCESS The function completed successfully.
328 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
329 @retval EFI_NOT_FOUND No valid forms could be found to display.
335 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
336 IN EFI_HII_HANDLE
*Handles
,
337 IN UINTN HandleCount
,
338 IN EFI_GUID
*FormSetGuid
, OPTIONAL
339 IN UINT16 FormId
, OPTIONAL
340 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
341 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
345 UI_MENU_SELECTION
*Selection
;
347 FORM_BROWSER_FORMSET
*FormSet
;
348 FORM_ENTRY_INFO
*MenuList
;
351 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
353 if (mFormDisplay
== NULL
) {
354 return EFI_UNSUPPORTED
;
358 // Save globals used by SendForm()
360 SaveBrowserContext ();
362 gResetRequired
= FALSE
;
363 gExitRequired
= FALSE
;
364 Status
= EFI_SUCCESS
;
366 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
368 for (Index
= 0; Index
< HandleCount
; Index
++) {
369 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
370 ASSERT (Selection
!= NULL
);
372 Selection
->Handle
= Handles
[Index
];
373 if (FormSetGuid
!= NULL
) {
374 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
375 Selection
->FormId
= FormId
;
377 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
381 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
382 ASSERT (FormSet
!= NULL
);
385 // Initialize internal data structures of FormSet
387 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
388 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
389 DestroyFormSet (FormSet
);
392 Selection
->FormSet
= FormSet
;
395 // Display this formset
397 gCurrentSelection
= Selection
;
399 Status
= SetupBrowser (Selection
);
401 gCurrentSelection
= NULL
;
404 // If no data is changed, don't need to save current FormSet into the maintain list.
406 if (!IsNvUpdateRequiredForFormSet (FormSet
) && !IsStorageDataChangedForFormSet(FormSet
)) {
407 CleanBrowserStorage(FormSet
);
408 RemoveEntryList (&FormSet
->Link
);
409 DestroyFormSet (FormSet
);
412 if (EFI_ERROR (Status
)) {
415 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
417 FreePool (Selection
);
421 // Still has error info, pop up a message.
423 if (gBrowserStatus
!= BROWSER_SUCCESS
) {
424 gDisplayFormData
.BrowserStatus
= gBrowserStatus
;
425 gDisplayFormData
.ErrorString
= gErrorInfo
;
427 gBrowserStatus
= BROWSER_SUCCESS
;
430 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
433 if (ActionRequest
!= NULL
) {
434 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
435 if (gResetRequired
) {
436 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
440 mFormDisplay
->ExitDisplay();
443 // Clear the menu history data.
445 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
446 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
447 RemoveEntryList (&MenuList
->Link
);
452 // Restore globals used by SendForm()
454 RestoreBrowserContext ();
460 Get or set data to the storage.
462 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
463 @param ResultsData A string returned from an IFR browser or
464 equivalent. The results string will have no
465 routing information in them.
466 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
467 (if RetrieveData = TRUE) data from the uncommitted
468 browser state information or set (if RetrieveData
469 = FALSE) data in the uncommitted browser state
471 @param Storage The pointer to the storage.
473 @retval EFI_SUCCESS The results have been distributed or are awaiting
479 IN OUT UINTN
*ResultsDataSize
,
480 IN OUT EFI_STRING
*ResultsData
,
481 IN BOOLEAN RetrieveData
,
482 IN BROWSER_STORAGE
*Storage
493 // Generate <ConfigResp>
495 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
496 if (EFI_ERROR (Status
)) {
501 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
502 // Also need to consider add "\0" at first time.
504 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
505 BufferSize
= StrSize (StrPtr
);
509 // Copy the data if the input buffer is bigger enough.
511 if (*ResultsDataSize
>= BufferSize
) {
512 StrCpy (*ResultsData
, StrPtr
);
515 *ResultsDataSize
= BufferSize
;
516 FreePool (ConfigResp
);
519 // Prepare <ConfigResp>
521 TmpSize
= StrLen (*ResultsData
);
522 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
523 ConfigResp
= AllocateZeroPool (BufferSize
);
524 ASSERT (ConfigResp
!= NULL
);
526 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
527 StrCat (ConfigResp
, L
"&");
528 StrCat (ConfigResp
, *ResultsData
);
531 // Update Browser uncommited data
533 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
534 FreePool (ConfigResp
);
535 if (EFI_ERROR (Status
)) {
544 This routine called this service in the browser to retrieve or set certain uncommitted
545 state information that resides in the open formsets.
547 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
549 @param ResultsDataSize A pointer to the size of the buffer associated
551 @param ResultsData A string returned from an IFR browser or
552 equivalent. The results string will have no
553 routing information in them.
554 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
555 (if RetrieveData = TRUE) data from the uncommitted
556 browser state information or set (if RetrieveData
557 = FALSE) data in the uncommitted browser state
559 @param VariableGuid An optional field to indicate the target variable
561 @param VariableName An optional field to indicate the target
562 human-readable variable name.
564 @retval EFI_SUCCESS The results have been distributed or are awaiting
566 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
567 contain the results data.
573 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
574 IN OUT UINTN
*ResultsDataSize
,
575 IN OUT EFI_STRING ResultsData
,
576 IN BOOLEAN RetrieveData
,
577 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
578 IN CONST CHAR16
*VariableName OPTIONAL
583 BROWSER_STORAGE
*Storage
;
584 FORMSET_STORAGE
*FormsetStorage
;
585 FORM_BROWSER_FORMSET
*FormSet
;
589 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
590 return EFI_INVALID_PARAMETER
;
593 TotalSize
= *ResultsDataSize
;
596 Status
= EFI_SUCCESS
;
599 // If set browser data, pre load all hii formset to avoid set the varstore which is not
602 if (!RetrieveData
&& (gBrowserSettingScope
== SystemLevel
)) {
606 if (VariableGuid
!= NULL
) {
608 // Try to find target storage in the current formset.
610 Link
= GetFirstNode (&gBrowserStorageList
);
611 while (!IsNull (&gBrowserStorageList
, Link
)) {
612 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
613 Link
= GetNextNode (&gBrowserStorageList
, Link
);
615 // Check the current storage.
617 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
621 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
622 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
624 // Buffer storage require both GUID and Name
626 if (VariableName
== NULL
) {
627 return EFI_NOT_FOUND
;
630 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
635 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
636 if (EFI_ERROR (Status
)) {
641 // Different formsets may have same varstore, so here just set the flag
642 // not exit the circle.
649 return EFI_NOT_FOUND
;
653 // GUID/Name is not specified, take the first storage in FormSet
655 if (gCurrentSelection
== NULL
) {
656 return EFI_NOT_READY
;
660 // Generate <ConfigResp>
662 FormSet
= gCurrentSelection
->FormSet
;
663 Link
= GetFirstNode (&FormSet
->StorageListHead
);
664 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
665 return EFI_UNSUPPORTED
;
668 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
670 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
671 if (EFI_ERROR (Status
)) {
677 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
678 *ResultsDataSize
= TotalSize
;
687 Callback function for SimpleTextInEx protocol install events
689 @param Event the event that is signaled.
690 @param Context not used here.
695 FormDisplayCallback (
702 if (mFormDisplay
!= NULL
) {
706 Status
= gBS
->LocateProtocol (
707 &gEdkiiFormDisplayEngineProtocolGuid
,
709 (VOID
**) &mFormDisplay
714 Initialize Setup Browser driver.
716 @param ImageHandle The image handle.
717 @param SystemTable The system table.
719 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
720 @return Other value if failed to initialize the Setup Browser module.
726 IN EFI_HANDLE ImageHandle
,
727 IN EFI_SYSTEM_TABLE
*SystemTable
734 // Locate required Hii relative protocols
736 Status
= gBS
->LocateProtocol (
737 &gEfiHiiDatabaseProtocolGuid
,
739 (VOID
**) &mHiiDatabase
741 ASSERT_EFI_ERROR (Status
);
743 Status
= gBS
->LocateProtocol (
744 &gEfiHiiConfigRoutingProtocolGuid
,
746 (VOID
**) &mHiiConfigRouting
748 ASSERT_EFI_ERROR (Status
);
750 Status
= gBS
->LocateProtocol (
751 &gEfiDevicePathFromTextProtocolGuid
,
753 (VOID
**) &mPathFromText
757 // Install FormBrowser2 protocol
759 mPrivateData
.Handle
= NULL
;
760 Status
= gBS
->InstallProtocolInterface (
761 &mPrivateData
.Handle
,
762 &gEfiFormBrowser2ProtocolGuid
,
763 EFI_NATIVE_INTERFACE
,
764 &mPrivateData
.FormBrowser2
766 ASSERT_EFI_ERROR (Status
);
769 // Install FormBrowserEx2 protocol
771 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
772 mPrivateData
.Handle
= NULL
;
773 Status
= gBS
->InstallProtocolInterface (
774 &mPrivateData
.Handle
,
775 &gEdkiiFormBrowserEx2ProtocolGuid
,
776 EFI_NATIVE_INTERFACE
,
777 &mPrivateData
.FormBrowserEx2
779 ASSERT_EFI_ERROR (Status
);
781 Status
= gBS
->InstallProtocolInterface (
782 &mPrivateData
.Handle
,
783 &gEfiFormBrowserExProtocolGuid
,
784 EFI_NATIVE_INTERFACE
,
785 &mPrivateData
.FormBrowserEx
787 ASSERT_EFI_ERROR (Status
);
789 InitializeDisplayFormData ();
791 Status
= gBS
->LocateProtocol (
792 &gEdkiiFormDisplayEngineProtocolGuid
,
794 (VOID
**) &mFormDisplay
797 if (EFI_ERROR (Status
)) {
798 EfiCreateProtocolNotifyEvent (
799 &gEdkiiFormDisplayEngineProtocolGuid
,
812 Create a new string in HII Package List.
814 @param String The String to be added
815 @param HiiHandle The package list in the HII database to insert the
818 @return The output string.
824 IN EFI_HII_HANDLE HiiHandle
827 EFI_STRING_ID StringId
;
829 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
830 ASSERT (StringId
!= 0);
837 Delete a string from HII Package List.
839 @param StringId Id of the string in HII database.
840 @param HiiHandle The HII package list handle.
842 @retval EFI_SUCCESS The string was deleted successfully.
847 IN EFI_STRING_ID StringId
,
848 IN EFI_HII_HANDLE HiiHandle
853 NullChar
= CHAR_NULL
;
854 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
860 Get the string based on the StringId and HII Package List Handle.
862 @param Token The String's ID.
863 @param HiiHandle The package list in the HII database to search for
864 the specified string.
866 @return The output string.
871 IN EFI_STRING_ID Token
,
872 IN EFI_HII_HANDLE HiiHandle
877 if (HiiHandle
== NULL
) {
881 String
= HiiGetString (HiiHandle
, Token
, NULL
);
882 if (String
== NULL
) {
883 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
884 ASSERT (String
!= NULL
);
886 return (CHAR16
*) String
;
891 Allocate new memory and then copy the Unicode string Source to Destination.
893 @param Dest Location to copy string
894 @param Src String to copy
899 IN OUT CHAR16
**Dest
,
906 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
907 ASSERT (*Dest
!= NULL
);
912 Allocate new memory and concatinate Source on the end of Destination.
914 @param Dest String to added to the end of.
915 @param Src String to concatinate.
920 IN OUT CHAR16
**Dest
,
928 NewStringCpy (Dest
, Src
);
932 TmpSize
= StrSize (*Dest
);
933 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
934 ASSERT (NewString
!= NULL
);
936 StrCpy (NewString
, *Dest
);
937 StrCat (NewString
, Src
);
944 Get Value for given Name from a NameValue Storage.
946 @param Storage The NameValue Storage.
947 @param Name The Name.
948 @param Value The retured Value.
949 @param GetValueFrom Where to get source value, from EditValue or Value.
951 @retval EFI_SUCCESS Value found for given Name.
952 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
957 IN BROWSER_STORAGE
*Storage
,
959 IN OUT CHAR16
**Value
,
960 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
964 NAME_VALUE_NODE
*Node
;
966 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
967 return EFI_INVALID_PARAMETER
;
972 Link
= GetFirstNode (&Storage
->NameValueListHead
);
973 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
974 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
976 if (StrCmp (Name
, Node
->Name
) == 0) {
977 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
978 NewStringCpy (Value
, Node
->EditValue
);
980 NewStringCpy (Value
, Node
->Value
);
985 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
988 return EFI_NOT_FOUND
;
993 Set Value of given Name in a NameValue Storage.
995 @param Storage The NameValue Storage.
996 @param Name The Name.
997 @param Value The Value to set.
998 @param SetValueTo Whether update editValue or Value.
999 @param ReturnNode The node use the input name.
1001 @retval EFI_SUCCESS Value found for given Name.
1002 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1007 IN BROWSER_STORAGE
*Storage
,
1010 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1011 OUT NAME_VALUE_NODE
**ReturnNode
1015 NAME_VALUE_NODE
*Node
;
1018 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1019 return EFI_INVALID_PARAMETER
;
1022 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1023 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1024 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1026 if (StrCmp (Name
, Node
->Name
) == 0) {
1027 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1028 Buffer
= Node
->EditValue
;
1030 Buffer
= Node
->Value
;
1032 if (Buffer
!= NULL
) {
1035 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1036 ASSERT (Buffer
!= NULL
);
1037 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1038 Node
->EditValue
= Buffer
;
1040 Node
->Value
= Buffer
;
1043 if (ReturnNode
!= NULL
) {
1050 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1053 return EFI_NOT_FOUND
;
1058 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1060 @param Storage The Storage to be conveted.
1061 @param ConfigResp The returned <ConfigResp>.
1062 @param ConfigRequest The ConfigRequest string.
1063 @param GetEditBuf Get the data from editbuffer or buffer.
1065 @retval EFI_SUCCESS Convert success.
1066 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1070 StorageToConfigResp (
1071 IN BROWSER_STORAGE
*Storage
,
1072 IN CHAR16
**ConfigResp
,
1073 IN CHAR16
*ConfigRequest
,
1074 IN BOOLEAN GetEditBuf
1078 EFI_STRING Progress
;
1080 NAME_VALUE_NODE
*Node
;
1083 Status
= EFI_SUCCESS
;
1085 switch (Storage
->Type
) {
1086 case EFI_HII_VARSTORE_BUFFER
:
1087 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1088 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1089 Status
= mHiiConfigRouting
->BlockToConfig (
1099 case EFI_HII_VARSTORE_NAME_VALUE
:
1101 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1103 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1104 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1105 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1107 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1108 NewStringCat (ConfigResp
, L
"&");
1109 NewStringCat (ConfigResp
, Node
->Name
);
1110 NewStringCat (ConfigResp
, L
"=");
1112 NewStringCat (ConfigResp
, Node
->EditValue
);
1114 NewStringCat (ConfigResp
, Node
->Value
);
1117 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1121 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1123 Status
= EFI_INVALID_PARAMETER
;
1132 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1134 @param Storage The Storage to receive the settings.
1135 @param ConfigResp The <ConfigResp> to be converted.
1137 @retval EFI_SUCCESS Convert success.
1138 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1142 ConfigRespToStorage (
1143 IN BROWSER_STORAGE
*Storage
,
1144 IN CHAR16
*ConfigResp
1148 EFI_STRING Progress
;
1154 Status
= EFI_SUCCESS
;
1156 switch (Storage
->Type
) {
1157 case EFI_HII_VARSTORE_BUFFER
:
1158 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1159 BufferSize
= Storage
->Size
;
1160 Status
= mHiiConfigRouting
->ConfigToBlock (
1163 Storage
->EditBuffer
,
1169 case EFI_HII_VARSTORE_NAME_VALUE
:
1170 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1171 if (StrPtr
== NULL
) {
1174 StrPtr
= StrStr (ConfigResp
, L
"&");
1175 while (StrPtr
!= NULL
) {
1179 StrPtr
= StrPtr
+ 1;
1181 StrPtr
= StrStr (StrPtr
, L
"=");
1182 if (StrPtr
== NULL
) {
1190 StrPtr
= StrPtr
+ 1;
1192 StrPtr
= StrStr (StrPtr
, L
"&");
1193 if (StrPtr
!= NULL
) {
1196 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1200 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1202 Status
= EFI_INVALID_PARAMETER
;
1211 Get Question's current Value.
1213 @param FormSet FormSet data structure.
1214 @param Form Form data structure.
1215 @param Question Question to be initialized.
1216 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1218 @retval EFI_SUCCESS The function completed successfully.
1223 IN FORM_BROWSER_FORMSET
*FormSet
,
1224 IN FORM_BROWSER_FORM
*Form
,
1225 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1226 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1235 BROWSER_STORAGE
*Storage
;
1236 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1237 CHAR16
*ConfigRequest
;
1245 BOOLEAN IsBufferStorage
;
1251 Status
= EFI_SUCCESS
;
1255 if (GetValueFrom
>= GetSetValueWithMax
) {
1256 return EFI_INVALID_PARAMETER
;
1260 // Statement don't have storage, skip them
1262 if (Question
->QuestionId
== 0) {
1267 // Question value is provided by an Expression, evaluate it
1269 if (Question
->ValueExpression
!= NULL
) {
1270 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1271 if (!EFI_ERROR (Status
)) {
1272 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1273 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1274 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1275 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1276 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1278 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1279 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1281 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1283 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1284 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1290 // Get question value by read expression.
1292 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1293 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1294 if (!EFI_ERROR (Status
) &&
1295 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1297 // Only update question value to the valid result.
1299 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1300 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1301 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1302 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1303 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1305 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1306 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1308 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1310 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1311 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1317 // Question value is provided by RTC
1319 Storage
= Question
->Storage
;
1320 QuestionValue
= &Question
->HiiValue
.Value
;
1321 if (Storage
== NULL
) {
1323 // It's a Question without storage, or RTC date/time
1325 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1327 // Date and time define the same Flags bit
1329 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1330 case QF_DATE_STORAGE_TIME
:
1331 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1334 case QF_DATE_STORAGE_WAKEUP
:
1335 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1338 case QF_DATE_STORAGE_NORMAL
:
1341 // For date/time without storage
1346 if (EFI_ERROR (Status
)) {
1350 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1351 QuestionValue
->date
.Year
= EfiTime
.Year
;
1352 QuestionValue
->date
.Month
= EfiTime
.Month
;
1353 QuestionValue
->date
.Day
= EfiTime
.Day
;
1355 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1356 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1357 QuestionValue
->time
.Second
= EfiTime
.Second
;
1365 // Question value is provided by EFI variable
1367 StorageWidth
= Question
->StorageWidth
;
1368 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1369 if (Question
->BufferValue
!= NULL
) {
1370 Dst
= Question
->BufferValue
;
1372 Dst
= (UINT8
*) QuestionValue
;
1375 Status
= gRT
->GetVariable (
1376 Question
->VariableName
,
1383 // Always return success, even this EFI variable doesn't exist
1389 // Question Value is provided by Buffer Storage or NameValue Storage
1391 if (Question
->BufferValue
!= NULL
) {
1393 // This Question is password or orderedlist
1395 Dst
= Question
->BufferValue
;
1398 // Other type of Questions
1400 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1403 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1404 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1405 IsBufferStorage
= TRUE
;
1407 IsBufferStorage
= FALSE
;
1409 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1410 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1411 if (IsBufferStorage
) {
1412 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1414 // Copy from storage Edit buffer
1416 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1419 // Copy from storage Edit buffer
1421 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1425 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1426 if (EFI_ERROR (Status
)) {
1430 ASSERT (Value
!= NULL
);
1431 LengthStr
= StrLen (Value
);
1432 Status
= EFI_SUCCESS
;
1435 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1436 // Add string tail char L'\0' into Length
1438 Length
= StorageWidth
+ sizeof (CHAR16
);
1439 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1440 Status
= EFI_BUFFER_TOO_SMALL
;
1442 StringPtr
= (CHAR16
*) Dst
;
1443 ZeroMem (TemStr
, sizeof (TemStr
));
1444 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1445 StrnCpy (TemStr
, Value
+ Index
, 4);
1446 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1449 // Add tailing L'\0' character
1451 StringPtr
[Index
/4] = L
'\0';
1454 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1455 Status
= EFI_BUFFER_TOO_SMALL
;
1457 ZeroMem (TemStr
, sizeof (TemStr
));
1458 for (Index
= 0; Index
< LengthStr
; Index
++) {
1459 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1460 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1461 if ((Index
& 1) == 0) {
1462 Dst
[Index
/2] = DigitUint8
;
1464 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1473 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1475 // Request current settings from Configuration Driver
1477 if (FormSet
->ConfigAccess
== NULL
) {
1478 return EFI_NOT_FOUND
;
1482 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1483 // <ConfigHdr> + "&" + <VariableName>
1485 if (IsBufferStorage
) {
1486 Length
= StrLen (Storage
->ConfigHdr
);
1487 Length
+= StrLen (Question
->BlockName
);
1489 Length
= StrLen (Storage
->ConfigHdr
);
1490 Length
+= StrLen (Question
->VariableName
) + 1;
1492 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1493 ASSERT (ConfigRequest
!= NULL
);
1495 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1496 if (IsBufferStorage
) {
1497 StrCat (ConfigRequest
, Question
->BlockName
);
1499 StrCat (ConfigRequest
, L
"&");
1500 StrCat (ConfigRequest
, Question
->VariableName
);
1503 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1504 FormSet
->ConfigAccess
,
1509 FreePool (ConfigRequest
);
1510 if (EFI_ERROR (Status
)) {
1515 // Skip <ConfigRequest>
1517 if (IsBufferStorage
) {
1518 Value
= StrStr (Result
, L
"&VALUE");
1519 if (Value
== NULL
) {
1521 return EFI_NOT_FOUND
;
1528 Value
= Result
+ Length
;
1530 if (*Value
!= '=') {
1532 return EFI_NOT_FOUND
;
1535 // Skip '=', point to value
1540 // Suppress <AltResp> if any
1543 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1548 LengthStr
= StrLen (Value
);
1549 Status
= EFI_SUCCESS
;
1550 if (!IsBufferStorage
&& IsString
) {
1552 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1553 // Add string tail char L'\0' into Length
1555 Length
= StorageWidth
+ sizeof (CHAR16
);
1556 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1557 Status
= EFI_BUFFER_TOO_SMALL
;
1559 StringPtr
= (CHAR16
*) Dst
;
1560 ZeroMem (TemStr
, sizeof (TemStr
));
1561 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1562 StrnCpy (TemStr
, Value
+ Index
, 4);
1563 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1566 // Add tailing L'\0' character
1568 StringPtr
[Index
/4] = L
'\0';
1571 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1572 Status
= EFI_BUFFER_TOO_SMALL
;
1574 ZeroMem (TemStr
, sizeof (TemStr
));
1575 for (Index
= 0; Index
< LengthStr
; Index
++) {
1576 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1577 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1578 if ((Index
& 1) == 0) {
1579 Dst
[Index
/2] = DigitUint8
;
1581 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1587 if (EFI_ERROR (Status
)) {
1591 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1593 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1594 if (TemBuffer
== NULL
) {
1595 Status
= EFI_OUT_OF_RESOURCES
;
1598 Length
= Storage
->Size
;
1599 Status
= gRT
->GetVariable (
1606 if (EFI_ERROR (Status
)) {
1607 FreePool (TemBuffer
);
1611 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1613 FreePool (TemBuffer
);
1617 // Synchronize Edit Buffer
1619 if (IsBufferStorage
) {
1620 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1622 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1625 if (Result
!= NULL
) {
1635 Save Question Value to edit copy(cached) or Storage(uncached).
1637 @param FormSet FormSet data structure.
1638 @param Form Form data structure.
1639 @param Question Pointer to the Question.
1640 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1642 @retval EFI_SUCCESS The function completed successfully.
1647 IN FORM_BROWSER_FORMSET
*FormSet
,
1648 IN FORM_BROWSER_FORM
*Form
,
1649 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1650 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1660 BROWSER_STORAGE
*Storage
;
1661 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1666 BOOLEAN IsBufferStorage
;
1672 NAME_VALUE_NODE
*Node
;
1674 Status
= EFI_SUCCESS
;
1677 if (SetValueTo
>= GetSetValueWithMax
) {
1678 return EFI_INVALID_PARAMETER
;
1682 // Statement don't have storage, skip them
1684 if (Question
->QuestionId
== 0) {
1689 // If Question value is provided by an Expression, then it is read only
1691 if (Question
->ValueExpression
!= NULL
) {
1696 // Before set question value, evaluate its write expression.
1698 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1699 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1700 if (EFI_ERROR (Status
)) {
1706 // Question value is provided by RTC
1708 Storage
= Question
->Storage
;
1709 QuestionValue
= &Question
->HiiValue
.Value
;
1710 if (Storage
== NULL
) {
1712 // It's a Question without storage, or RTC date/time
1714 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1716 // Date and time define the same Flags bit
1718 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1719 case QF_DATE_STORAGE_TIME
:
1720 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1723 case QF_DATE_STORAGE_WAKEUP
:
1724 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1727 case QF_DATE_STORAGE_NORMAL
:
1730 // For date/time without storage
1735 if (EFI_ERROR (Status
)) {
1739 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1740 EfiTime
.Year
= QuestionValue
->date
.Year
;
1741 EfiTime
.Month
= QuestionValue
->date
.Month
;
1742 EfiTime
.Day
= QuestionValue
->date
.Day
;
1744 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1745 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1746 EfiTime
.Second
= QuestionValue
->time
.Second
;
1749 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1750 Status
= gRT
->SetTime (&EfiTime
);
1752 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1760 // Question value is provided by EFI variable
1762 StorageWidth
= Question
->StorageWidth
;
1763 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1764 if (Question
->BufferValue
!= NULL
) {
1765 Src
= Question
->BufferValue
;
1767 Src
= (UINT8
*) QuestionValue
;
1770 Status
= gRT
->SetVariable (
1771 Question
->VariableName
,
1773 Storage
->Attributes
,
1781 // Question Value is provided by Buffer Storage or NameValue Storage
1783 if (Question
->BufferValue
!= NULL
) {
1784 Src
= Question
->BufferValue
;
1786 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1789 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1790 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1791 IsBufferStorage
= TRUE
;
1793 IsBufferStorage
= FALSE
;
1795 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1797 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1798 if (IsBufferStorage
) {
1799 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1801 // Copy to storage edit buffer
1803 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1804 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1806 // Copy to storage edit buffer
1808 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1811 // Check whether question value has been changed.
1813 if (CompareMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
) != 0) {
1814 Question
->ValueChanged
= TRUE
;
1816 Question
->ValueChanged
= FALSE
;
1821 // Allocate enough string buffer.
1824 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1825 Value
= AllocateZeroPool (BufferLen
);
1826 ASSERT (Value
!= NULL
);
1828 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1830 TemName
= (CHAR16
*) Src
;
1832 for (; *TemName
!= L
'\0'; TemName
++) {
1833 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1836 BufferLen
= StorageWidth
* 2 + 1;
1837 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1838 ASSERT (Value
!= NULL
);
1840 // Convert Buffer to Hex String
1842 TemBuffer
= Src
+ StorageWidth
- 1;
1844 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1845 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1849 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1851 if (EFI_ERROR (Status
)) {
1855 // Check whether question value has been changed.
1857 if (StrCmp (Node
->Value
, Node
->EditValue
) != 0) {
1858 Question
->ValueChanged
= TRUE
;
1860 Question
->ValueChanged
= FALSE
;
1863 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1864 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1866 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1867 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1869 if (IsBufferStorage
) {
1870 Length
= StrLen (Question
->BlockName
) + 7;
1872 Length
= StrLen (Question
->VariableName
) + 2;
1874 if (!IsBufferStorage
&& IsString
) {
1875 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1877 Length
+= (StorageWidth
* 2);
1879 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1880 ASSERT (ConfigResp
!= NULL
);
1882 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1883 if (IsBufferStorage
) {
1884 StrCat (ConfigResp
, Question
->BlockName
);
1885 StrCat (ConfigResp
, L
"&VALUE=");
1887 StrCat (ConfigResp
, L
"&");
1888 StrCat (ConfigResp
, Question
->VariableName
);
1889 StrCat (ConfigResp
, L
"=");
1892 Value
= ConfigResp
+ StrLen (ConfigResp
);
1894 if (!IsBufferStorage
&& IsString
) {
1896 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1898 TemName
= (CHAR16
*) Src
;
1900 for (; *TemName
!= L
'\0'; TemName
++) {
1901 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1905 // Convert Buffer to Hex String
1907 TemBuffer
= Src
+ StorageWidth
- 1;
1909 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1910 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1915 // Convert to lower char.
1917 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1918 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1919 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1924 // Submit Question Value to Configuration Driver
1926 if (FormSet
->ConfigAccess
!= NULL
) {
1927 Status
= FormSet
->ConfigAccess
->RouteConfig (
1928 FormSet
->ConfigAccess
,
1932 if (EFI_ERROR (Status
)) {
1933 FreePool (ConfigResp
);
1937 FreePool (ConfigResp
);
1939 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1941 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1942 if (TemBuffer
== NULL
) {
1943 Status
= EFI_OUT_OF_RESOURCES
;
1946 Length
= Storage
->Size
;
1947 Status
= gRT
->GetVariable (
1955 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1957 Status
= gRT
->SetVariable (
1960 Storage
->Attributes
,
1964 FreePool (TemBuffer
);
1965 if (EFI_ERROR (Status
)){
1970 // Sync storage, from editbuffer to buffer.
1972 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1980 Perform nosubmitif check for a Form.
1982 @param FormSet FormSet data structure.
1983 @param Form Form data structure.
1984 @param Question The Question to be validated.
1985 @param Type Validation type: NoSubmit
1987 @retval EFI_SUCCESS Form validation pass.
1988 @retval other Form validation failed.
1993 IN FORM_BROWSER_FORMSET
*FormSet
,
1994 IN FORM_BROWSER_FORM
*Form
,
1995 IN FORM_BROWSER_STATEMENT
*Question
,
2001 LIST_ENTRY
*ListHead
;
2003 FORM_EXPRESSION
*Expression
;
2005 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
2006 ListHead
= &Question
->NoSubmitListHead
;
2008 return EFI_UNSUPPORTED
;
2011 Link
= GetFirstNode (ListHead
);
2012 while (!IsNull (ListHead
, Link
)) {
2013 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2016 // Evaluate the expression
2018 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2019 if (EFI_ERROR (Status
)) {
2023 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
2025 // Condition meet, show up error message
2027 if (Expression
->Error
!= 0) {
2028 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2029 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
2030 gBrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2035 return EFI_NOT_READY
;
2038 Link
= GetNextNode (ListHead
, Link
);
2046 Perform NoSubmit check for each Form in FormSet.
2048 @param FormSet FormSet data structure.
2049 @param CurrentForm Current input form data structure.
2051 @retval EFI_SUCCESS Form validation pass.
2052 @retval other Form validation failed.
2057 IN FORM_BROWSER_FORMSET
*FormSet
,
2058 IN FORM_BROWSER_FORM
*CurrentForm
2063 FORM_BROWSER_STATEMENT
*Question
;
2064 FORM_BROWSER_FORM
*Form
;
2065 LIST_ENTRY
*LinkForm
;
2067 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2068 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2069 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2070 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2072 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2076 Link
= GetFirstNode (&Form
->StatementListHead
);
2077 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2078 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2080 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2081 if (EFI_ERROR (Status
)) {
2085 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2093 Fill storage's edit copy with settings requested from Configuration Driver.
2095 @param FormSet FormSet data structure.
2096 @param Storage The storage which need to sync.
2097 @param ConfigRequest The config request string which used to sync storage.
2098 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2099 editbuffer to buffer
2100 if TRUE, copy the editbuffer to the buffer.
2101 if FALSE, copy the buffer to the editbuffer.
2103 @retval EFI_SUCCESS The function completed successfully.
2107 SynchronizeStorage (
2108 IN FORM_BROWSER_FORMSET
*FormSet
,
2109 OUT BROWSER_STORAGE
*Storage
,
2110 IN CHAR16
*ConfigRequest
,
2111 IN BOOLEAN SyncOrRestore
2115 EFI_STRING Progress
;
2119 NAME_VALUE_NODE
*Node
;
2123 Status
= EFI_SUCCESS
;
2126 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2127 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2128 BufferSize
= Storage
->Size
;
2130 if (SyncOrRestore
) {
2131 Src
= Storage
->EditBuffer
;
2132 Dst
= Storage
->Buffer
;
2134 Src
= Storage
->Buffer
;
2135 Dst
= Storage
->EditBuffer
;
2138 if (ConfigRequest
!= NULL
) {
2139 Status
= mHiiConfigRouting
->BlockToConfig(
2147 if (EFI_ERROR (Status
)) {
2151 Status
= mHiiConfigRouting
->ConfigToBlock (
2158 if (Result
!= NULL
) {
2162 CopyMem (Dst
, Src
, BufferSize
);
2164 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2165 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2166 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2167 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2169 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2170 (ConfigRequest
== NULL
)) {
2171 if (SyncOrRestore
) {
2172 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2174 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2178 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2186 When discard the question value, call the callback function with Changed type
2187 to inform the hii driver.
2189 @param FormSet FormSet data structure.
2190 @param Form Form data structure.
2194 SendDiscardInfoToDriver (
2195 IN FORM_BROWSER_FORMSET
*FormSet
,
2196 IN FORM_BROWSER_FORM
*Form
2200 FORM_BROWSER_STATEMENT
*Question
;
2201 EFI_IFR_TYPE_VALUE
*TypeValue
;
2202 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2204 Link
= GetFirstNode (&Form
->StatementListHead
);
2205 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2206 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2207 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2209 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2213 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2217 if (!Question
->ValueChanged
) {
2221 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2222 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2224 TypeValue
= &Question
->HiiValue
.Value
;
2227 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2228 FormSet
->ConfigAccess
->Callback (
2229 FormSet
->ConfigAccess
,
2230 EFI_BROWSER_ACTION_CHANGED
,
2231 Question
->QuestionId
,
2232 Question
->HiiValue
.Type
,
2240 Validate the FormSet. If the formset is not validate, remove it from the list.
2242 @param FormSet The input FormSet which need to validate.
2244 @retval TRUE The handle is validate.
2245 @retval FALSE The handle is invalidate.
2250 FORM_BROWSER_FORMSET
*FormSet
2253 EFI_HII_HANDLE
*HiiHandles
;
2257 ASSERT (FormSet
!= NULL
);
2260 // Get all the Hii handles
2262 HiiHandles
= HiiGetHiiHandles (NULL
);
2263 ASSERT (HiiHandles
!= NULL
);
2266 // Search for formset of each class type
2268 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2269 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2276 CleanBrowserStorage(FormSet
);
2277 RemoveEntryList (&FormSet
->Link
);
2278 DestroyFormSet (FormSet
);
2281 FreePool (HiiHandles
);
2286 Check whether need to enable the reset flag in form level.
2287 Also clean all ValueChanged flag in question.
2289 @param SetFlag Whether need to set the Reset Flag.
2290 @param Form Form data structure.
2296 IN FORM_BROWSER_FORM
*Form
2300 FORM_BROWSER_STATEMENT
*Question
;
2304 Link
= GetFirstNode (&Form
->StatementListHead
);
2305 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2306 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2308 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2309 gResetRequired
= TRUE
;
2312 if (Question
->ValueChanged
) {
2313 Question
->ValueChanged
= FALSE
;
2316 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2321 Check whether need to enable the reset flag.
2322 Also clean ValueChanged flag for all statements.
2324 Form level or formset level, only one.
2326 @param SetFlag Whether need to set the Reset Flag.
2327 @param FormSet FormSet data structure.
2328 @param Form Form data structure.
2332 ValueChangeResetFlagUpdate (
2334 IN FORM_BROWSER_FORMSET
*FormSet
,
2335 IN FORM_BROWSER_FORM
*Form
2338 FORM_BROWSER_FORM
*CurrentForm
;
2342 // Form != NULL means only check form level.
2345 UpdateFlagForForm(SetFlag
, Form
);
2349 Link
= GetFirstNode (&FormSet
->FormListHead
);
2350 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2351 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2352 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2354 UpdateFlagForForm(SetFlag
, CurrentForm
);
2359 Discard data based on the input setting scope (Form, FormSet or System).
2361 @param FormSet FormSet data structure.
2362 @param Form Form data structure.
2363 @param SettingScope Setting Scope for Discard action.
2365 @retval EFI_SUCCESS The function completed successfully.
2366 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2371 IN FORM_BROWSER_FORMSET
*FormSet
,
2372 IN FORM_BROWSER_FORM
*Form
,
2373 IN BROWSER_SETTING_SCOPE SettingScope
2377 FORMSET_STORAGE
*Storage
;
2378 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2379 FORM_BROWSER_FORMSET
*LocalFormSet
;
2382 // Check the supported setting level.
2384 if (SettingScope
>= MaxLevel
) {
2385 return EFI_UNSUPPORTED
;
2388 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2390 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2391 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2392 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2393 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2395 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2400 // Skip if there is no RequestElement
2402 if (ConfigInfo
->ElementCount
== 0) {
2407 // Prepare <ConfigResp>
2409 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2412 // Call callback with Changed type to inform the driver.
2414 SendDiscardInfoToDriver (FormSet
, Form
);
2417 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2418 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2421 // Discard Buffer storage or Name/Value storage
2423 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2424 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2425 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2426 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2428 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2433 // Skip if there is no RequestElement
2435 if (Storage
->ElementCount
== 0) {
2439 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2442 Link
= GetFirstNode (&FormSet
->FormListHead
);
2443 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2444 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2445 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2448 // Call callback with Changed type to inform the driver.
2450 SendDiscardInfoToDriver (FormSet
, Form
);
2453 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2454 } else if (SettingScope
== SystemLevel
) {
2456 // System Level Discard.
2460 // Discard changed value for each FormSet in the maintain list.
2462 Link
= GetFirstNode (&gBrowserFormSetList
);
2463 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2464 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2465 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2466 if (!ValidateFormSet(LocalFormSet
)) {
2469 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2470 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2472 // Remove maintain backup list after discard except for the current using FormSet.
2474 CleanBrowserStorage(LocalFormSet
);
2475 RemoveEntryList (&LocalFormSet
->Link
);
2476 DestroyFormSet (LocalFormSet
);
2485 Submit data based on the input Setting level (Form, FormSet or System).
2487 @param FormSet FormSet data structure.
2488 @param Form Form data structure.
2489 @param SettingScope Setting Scope for Submit action.
2491 @retval EFI_SUCCESS The function completed successfully.
2492 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2497 IN FORM_BROWSER_FORMSET
*FormSet
,
2498 IN FORM_BROWSER_FORM
*Form
,
2499 IN BROWSER_SETTING_SCOPE SettingScope
2504 EFI_STRING ConfigResp
;
2505 EFI_STRING Progress
;
2506 BROWSER_STORAGE
*Storage
;
2507 FORMSET_STORAGE
*FormSetStorage
;
2510 FORM_BROWSER_FORMSET
*LocalFormSet
;
2511 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2514 // Check the supported setting level.
2516 if (SettingScope
>= MaxLevel
) {
2517 return EFI_UNSUPPORTED
;
2521 // Validate the Form by NoSubmit check
2523 Status
= EFI_SUCCESS
;
2524 if (SettingScope
== FormLevel
) {
2525 Status
= NoSubmitCheck (FormSet
, Form
);
2526 } else if (SettingScope
== FormSetLevel
) {
2527 Status
= NoSubmitCheck (FormSet
, NULL
);
2529 if (EFI_ERROR (Status
)) {
2533 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2535 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2536 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2537 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2538 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2540 Storage
= ConfigInfo
->Storage
;
2541 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2546 // Skip if there is no RequestElement
2548 if (ConfigInfo
->ElementCount
== 0) {
2553 // 1. Prepare <ConfigResp>
2555 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2556 if (EFI_ERROR (Status
)) {
2561 // 2. Set value to hii driver or efi variable.
2563 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2564 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2566 // Send <ConfigResp> to Configuration Driver
2568 if (FormSet
->ConfigAccess
!= NULL
) {
2569 Status
= FormSet
->ConfigAccess
->RouteConfig (
2570 FormSet
->ConfigAccess
,
2574 if (EFI_ERROR (Status
)) {
2575 FreePool (ConfigResp
);
2579 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2581 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2582 if (TmpBuf
== NULL
) {
2583 Status
= EFI_OUT_OF_RESOURCES
;
2587 BufferSize
= Storage
->Size
;
2588 Status
= gRT
->GetVariable (
2595 if (EFI_ERROR (Status
)) {
2597 FreePool (ConfigResp
);
2600 ASSERT (BufferSize
== Storage
->Size
);
2601 Status
= mHiiConfigRouting
->ConfigToBlock (
2608 if (EFI_ERROR (Status
)) {
2610 FreePool (ConfigResp
);
2614 Status
= gRT
->SetVariable (
2617 Storage
->Attributes
,
2622 if (EFI_ERROR (Status
)) {
2623 FreePool (ConfigResp
);
2627 FreePool (ConfigResp
);
2629 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2631 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2635 // 4. Update the NV flag.
2637 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2638 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2640 // Submit Buffer storage or Name/Value storage
2642 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2643 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2644 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2645 Storage
= FormSetStorage
->BrowserStorage
;
2646 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2648 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2653 // Skip if there is no RequestElement
2655 if (FormSetStorage
->ElementCount
== 0) {
2660 // 1. Prepare <ConfigResp>
2662 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2663 if (EFI_ERROR (Status
)) {
2667 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2668 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2671 // 2. Send <ConfigResp> to Configuration Driver
2673 if (FormSet
->ConfigAccess
!= NULL
) {
2674 Status
= FormSet
->ConfigAccess
->RouteConfig (
2675 FormSet
->ConfigAccess
,
2679 if (EFI_ERROR (Status
)) {
2680 FreePool (ConfigResp
);
2684 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2686 // 1&2. Set the edit data to the variable.
2689 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2690 if (TmpBuf
== NULL
) {
2691 Status
= EFI_OUT_OF_RESOURCES
;
2694 BufferSize
= Storage
->Size
;
2695 Status
= gRT
->GetVariable (
2702 ASSERT (BufferSize
== Storage
->Size
);
2703 Status
= mHiiConfigRouting
->ConfigToBlock (
2710 if (EFI_ERROR (Status
)) {
2712 FreePool (ConfigResp
);
2716 Status
= gRT
->SetVariable (
2719 Storage
->Attributes
,
2723 if (EFI_ERROR (Status
)) {
2725 FreePool (ConfigResp
);
2730 FreePool (ConfigResp
);
2732 // 3. Config success, update storage shadow Buffer
2734 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2738 // 4. Update the NV flag.
2740 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2741 } else if (SettingScope
== SystemLevel
) {
2743 // System Level Save.
2747 // Save changed value for each FormSet in the maintain list.
2749 Link
= GetFirstNode (&gBrowserFormSetList
);
2750 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2751 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2752 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2753 if (!ValidateFormSet(LocalFormSet
)) {
2756 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2757 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2759 // Remove maintain backup list after save except for the current using FormSet.
2761 CleanBrowserStorage(LocalFormSet
);
2762 RemoveEntryList (&LocalFormSet
->Link
);
2763 DestroyFormSet (LocalFormSet
);
2772 Get Question default value from AltCfg string.
2774 @param FormSet The form set.
2775 @param Question The question.
2776 @param DefaultId The default Id.
2778 @retval EFI_SUCCESS Question is reset to default value.
2782 GetDefaultValueFromAltCfg (
2783 IN FORM_BROWSER_FORMSET
*FormSet
,
2784 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2788 BOOLEAN IsBufferStorage
;
2791 BROWSER_STORAGE
*Storage
;
2792 CHAR16
*ConfigRequest
;
2805 Status
= EFI_NOT_FOUND
;
2808 ConfigRequest
= NULL
;
2812 Storage
= Question
->Storage
;
2814 if ((Storage
== NULL
) ||
2815 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2816 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2821 // Question Value is provided by Buffer Storage or NameValue Storage
2823 if (Question
->BufferValue
!= NULL
) {
2825 // This Question is password or orderedlist
2827 Dst
= Question
->BufferValue
;
2830 // Other type of Questions
2832 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2835 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2836 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2839 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2840 // <ConfigHdr> + "&" + <VariableName>
2842 if (IsBufferStorage
) {
2843 Length
= StrLen (Storage
->ConfigHdr
);
2844 Length
+= StrLen (Question
->BlockName
);
2846 Length
= StrLen (Storage
->ConfigHdr
);
2847 Length
+= StrLen (Question
->VariableName
) + 1;
2849 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2850 ASSERT (ConfigRequest
!= NULL
);
2852 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2853 if (IsBufferStorage
) {
2854 StrCat (ConfigRequest
, Question
->BlockName
);
2856 StrCat (ConfigRequest
, L
"&");
2857 StrCat (ConfigRequest
, Question
->VariableName
);
2860 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2861 FormSet
->ConfigAccess
,
2866 if (EFI_ERROR (Status
)) {
2871 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2872 // Get the default configuration string according to the default ID.
2874 Status
= mHiiConfigRouting
->GetAltConfig (
2880 &DefaultId
, // it can be NULL to get the current setting.
2885 // The required setting can't be found. So, it is not required to be validated and set.
2887 if (EFI_ERROR (Status
)) {
2892 // Skip <ConfigRequest>
2894 if (IsBufferStorage
) {
2895 Value
= StrStr (ConfigResp
, L
"&VALUE");
2896 ASSERT (Value
!= NULL
);
2902 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2903 ASSERT (Value
!= NULL
);
2905 Value
= Value
+ StrLen (Question
->VariableName
);
2907 if (*Value
!= '=') {
2908 Status
= EFI_NOT_FOUND
;
2912 // Skip '=', point to value
2917 // Suppress <AltResp> if any
2920 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2925 LengthStr
= StrLen (Value
);
2926 if (!IsBufferStorage
&& IsString
) {
2927 StringPtr
= (CHAR16
*) Dst
;
2928 ZeroMem (TemStr
, sizeof (TemStr
));
2929 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2930 StrnCpy (TemStr
, Value
+ Index
, 4);
2931 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2934 // Add tailing L'\0' character
2936 StringPtr
[Index
/4] = L
'\0';
2938 ZeroMem (TemStr
, sizeof (TemStr
));
2939 for (Index
= 0; Index
< LengthStr
; Index
++) {
2940 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2941 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2942 if ((Index
& 1) == 0) {
2943 Dst
[Index
/2] = DigitUint8
;
2945 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2951 if (ConfigRequest
!= NULL
){
2952 FreePool (ConfigRequest
);
2955 if (ConfigResp
!= NULL
) {
2956 FreePool (ConfigResp
);
2959 if (Result
!= NULL
) {
2967 Get default Id value used for browser.
2969 @param DefaultId The default id value used by hii.
2971 @retval Browser used default value.
2975 GetDefaultIdForCallBack (
2979 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2980 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2981 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2982 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2983 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2984 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2985 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2986 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2987 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2988 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2989 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2990 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2999 Return data element in an Array by its Index.
3001 @param Array The data array.
3002 @param Type Type of the data in this array.
3003 @param Index Zero based index for data in this array.
3005 @retval Value The data to be returned
3017 ASSERT (Array
!= NULL
);
3021 case EFI_IFR_TYPE_NUM_SIZE_8
:
3022 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3025 case EFI_IFR_TYPE_NUM_SIZE_16
:
3026 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3029 case EFI_IFR_TYPE_NUM_SIZE_32
:
3030 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3033 case EFI_IFR_TYPE_NUM_SIZE_64
:
3034 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3046 Set value of a data element in an Array by its Index.
3048 @param Array The data array.
3049 @param Type Type of the data in this array.
3050 @param Index Zero based index for data in this array.
3051 @param Value The value to be set.
3063 ASSERT (Array
!= NULL
);
3066 case EFI_IFR_TYPE_NUM_SIZE_8
:
3067 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3070 case EFI_IFR_TYPE_NUM_SIZE_16
:
3071 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3074 case EFI_IFR_TYPE_NUM_SIZE_32
:
3075 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3078 case EFI_IFR_TYPE_NUM_SIZE_64
:
3079 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3088 Search an Option of a Question by its value.
3090 @param Question The Question
3091 @param OptionValue Value for Option to be searched.
3093 @retval Pointer Pointer to the found Option.
3094 @retval NULL Option not found.
3099 IN FORM_BROWSER_STATEMENT
*Question
,
3100 IN EFI_HII_VALUE
*OptionValue
3104 QUESTION_OPTION
*Option
;
3107 Link
= GetFirstNode (&Question
->OptionListHead
);
3108 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3109 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3111 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3113 // Check the suppressif condition, only a valid option can be return.
3115 if ((Option
->SuppressExpression
== NULL
) ||
3116 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3121 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3129 Reset Question to its default value.
3131 @param FormSet The form set.
3132 @param Form The form.
3133 @param Question The question.
3134 @param DefaultId The Class of the default.
3136 @retval EFI_SUCCESS Question is reset to default value.
3140 GetQuestionDefault (
3141 IN FORM_BROWSER_FORMSET
*FormSet
,
3142 IN FORM_BROWSER_FORM
*Form
,
3143 IN FORM_BROWSER_STATEMENT
*Question
,
3149 QUESTION_DEFAULT
*Default
;
3150 QUESTION_OPTION
*Option
;
3151 EFI_HII_VALUE
*HiiValue
;
3153 EFI_STRING StrValue
;
3154 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3155 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3158 Status
= EFI_NOT_FOUND
;
3162 // Statement don't have storage, skip them
3164 if (Question
->QuestionId
== 0) {
3169 // There are Five ways to specify default value for a Question:
3170 // 1, use call back function (highest priority)
3171 // 2, use ExtractConfig function
3172 // 3, use nested EFI_IFR_DEFAULT
3173 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3174 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3176 HiiValue
= &Question
->HiiValue
;
3179 // Get Question defaut value from call back function.
3181 ConfigAccess
= FormSet
->ConfigAccess
;
3182 Action
= GetDefaultIdForCallBack (DefaultId
);
3183 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3184 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3185 Status
= ConfigAccess
->Callback (
3188 Question
->QuestionId
,
3193 if (!EFI_ERROR (Status
)) {
3199 // Get default value from altcfg string.
3201 if (ConfigAccess
!= NULL
) {
3202 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3203 if (!EFI_ERROR (Status
)) {
3209 // EFI_IFR_DEFAULT has highest priority
3211 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3212 Link
= GetFirstNode (&Question
->DefaultListHead
);
3213 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3214 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3216 if (Default
->DefaultId
== DefaultId
) {
3217 if (Default
->ValueExpression
!= NULL
) {
3219 // Default is provided by an Expression, evaluate it
3221 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3222 if (EFI_ERROR (Status
)) {
3226 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3227 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3228 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3229 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3230 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3232 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3233 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3235 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3237 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3238 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3241 // Default value is embedded in EFI_IFR_DEFAULT
3243 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3246 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3247 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3248 if (StrValue
== NULL
) {
3249 return EFI_NOT_FOUND
;
3251 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3252 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3254 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3261 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3266 // EFI_ONE_OF_OPTION
3268 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3269 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3271 // OneOfOption could only provide Standard and Manufacturing default
3273 Link
= GetFirstNode (&Question
->OptionListHead
);
3274 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3275 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3276 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3278 if ((Option
->SuppressExpression
!= NULL
) &&
3279 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3283 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3284 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3286 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3295 // EFI_IFR_CHECKBOX - lowest priority
3297 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3298 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3300 // Checkbox could only provide Standard and Manufacturing default
3302 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3303 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3305 HiiValue
->Value
.b
= TRUE
;
3307 HiiValue
->Value
.b
= FALSE
;
3315 // For Questions without default
3317 Status
= EFI_NOT_FOUND
;
3318 switch (Question
->Operand
) {
3319 case EFI_IFR_NUMERIC_OP
:
3321 // Take minimum value as numeric default value
3323 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3324 HiiValue
->Value
.u64
= Question
->Minimum
;
3325 Status
= EFI_SUCCESS
;
3329 case EFI_IFR_ONE_OF_OP
:
3331 // Take first oneof option as oneof's default value
3333 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3334 Link
= GetFirstNode (&Question
->OptionListHead
);
3335 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3336 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3337 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3339 if ((Option
->SuppressExpression
!= NULL
) &&
3340 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3344 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3345 Status
= EFI_SUCCESS
;
3351 case EFI_IFR_ORDERED_LIST_OP
:
3353 // Take option sequence in IFR as ordered list's default value
3356 Link
= GetFirstNode (&Question
->OptionListHead
);
3357 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3358 Status
= EFI_SUCCESS
;
3359 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3360 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3362 if ((Option
->SuppressExpression
!= NULL
) &&
3363 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3367 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3370 if (Index
>= Question
->MaxContainers
) {
3385 Reset Questions to their initial value or default value in a Form, Formset or System.
3387 GetDefaultValueScope parameter decides which questions will reset
3388 to its default value.
3390 @param FormSet FormSet data structure.
3391 @param Form Form data structure.
3392 @param DefaultId The Class of the default.
3393 @param SettingScope Setting Scope for Default action.
3394 @param GetDefaultValueScope Get default value scope.
3395 @param Storage Get default value only for this storage.
3396 @param RetrieveValueFirst Whether call the retrieve call back to
3397 get the initial value before get default
3400 @retval EFI_SUCCESS The function completed successfully.
3401 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3406 IN FORM_BROWSER_FORMSET
*FormSet
,
3407 IN FORM_BROWSER_FORM
*Form
,
3408 IN UINT16 DefaultId
,
3409 IN BROWSER_SETTING_SCOPE SettingScope
,
3410 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3411 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3412 IN BOOLEAN RetrieveValueFirst
3416 LIST_ENTRY
*FormLink
;
3418 FORM_BROWSER_STATEMENT
*Question
;
3419 FORM_BROWSER_FORMSET
*LocalFormSet
;
3421 Status
= EFI_SUCCESS
;
3424 // Check the supported setting level.
3426 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3427 return EFI_UNSUPPORTED
;
3430 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3431 return EFI_UNSUPPORTED
;
3434 if (SettingScope
== FormLevel
) {
3436 // Extract Form default
3438 Link
= GetFirstNode (&Form
->StatementListHead
);
3439 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3440 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3441 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3444 // If get default value only for this storage, check the storage first.
3446 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3451 // If get default value only for no storage question, just skip the question which has storage.
3453 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3458 // If Question is disabled, don't reset it to default
3460 if (Question
->Expression
!= NULL
) {
3461 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3466 if (RetrieveValueFirst
) {
3468 // Call the Retrieve call back to get the initial question value.
3470 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3474 // If not request to get the initial value or get initial value fail, then get default value.
3476 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3477 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3478 if (EFI_ERROR (Status
)) {
3484 // Synchronize Buffer storage's Edit buffer
3486 if ((Question
->Storage
!= NULL
) &&
3487 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3488 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3491 } else if (SettingScope
== FormSetLevel
) {
3492 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3493 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3494 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3495 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3496 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3498 } else if (SettingScope
== SystemLevel
) {
3500 // Preload all Hii formset.
3502 LoadAllHiiFormset();
3505 // Set Default Value for each FormSet in the maintain list.
3507 Link
= GetFirstNode (&gBrowserFormSetList
);
3508 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3509 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3510 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3511 if (!ValidateFormSet(LocalFormSet
)) {
3514 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3523 Validate whether this question's value has changed.
3525 @param FormSet FormSet data structure.
3526 @param Form Form data structure.
3527 @param Question Question to be initialized.
3528 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3530 @retval TRUE Question's value has changed.
3531 @retval FALSE Question's value has not changed
3535 IsQuestionValueChanged (
3536 IN FORM_BROWSER_FORMSET
*FormSet
,
3537 IN FORM_BROWSER_FORM
*Form
,
3538 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3539 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3542 EFI_HII_VALUE BackUpValue
;
3543 CHAR8
*BackUpBuffer
;
3545 BOOLEAN ValueChanged
;
3549 // For quetion without storage, always mark it as data not changed.
3551 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3555 BackUpBuffer
= NULL
;
3556 ValueChanged
= FALSE
;
3558 switch (Question
->Operand
) {
3559 case EFI_IFR_ORDERED_LIST_OP
:
3560 BufferWidth
= Question
->StorageWidth
;
3561 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3562 ASSERT (BackUpBuffer
!= NULL
);
3565 case EFI_IFR_STRING_OP
:
3566 case EFI_IFR_PASSWORD_OP
:
3567 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3568 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3569 ASSERT (BackUpBuffer
!= NULL
);
3576 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3578 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3579 ASSERT_EFI_ERROR(Status
);
3581 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3582 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3583 ValueChanged
= TRUE
;
3586 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3587 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3589 if (BackUpBuffer
!= NULL
) {
3590 FreePool (BackUpBuffer
);
3593 return ValueChanged
;
3597 Initialize Question's Edit copy from Storage.
3599 @param Selection Selection contains the information about
3600 the Selection, form and formset to be displayed.
3601 Selection action may be updated in retrieve callback.
3602 If Selection is NULL, only initialize Question value.
3603 @param FormSet FormSet data structure.
3604 @param Form Form data structure.
3606 @retval EFI_SUCCESS The function completed successfully.
3611 IN OUT UI_MENU_SELECTION
*Selection
,
3612 IN FORM_BROWSER_FORMSET
*FormSet
,
3613 IN FORM_BROWSER_FORM
*Form
3618 FORM_BROWSER_STATEMENT
*Question
;
3622 Link
= GetFirstNode (&Form
->StatementListHead
);
3623 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3624 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3627 // Initialize local copy of Value for each Question
3629 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3630 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3632 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3634 if (EFI_ERROR (Status
)) {
3638 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3639 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3643 // Call the Retrieve call back function for all questions.
3645 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3646 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3648 // Check QuestionValue does exist.
3650 StorageWidth
= Question
->StorageWidth
;
3651 if (Question
->BufferValue
!= NULL
) {
3652 BufferValue
= Question
->BufferValue
;
3654 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3658 // For efivarstore storage, initial question value first.
3660 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3661 Status
= gRT
->GetVariable (
3662 Question
->VariableName
,
3663 &Question
->Storage
->Guid
,
3670 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3674 // Update Question Value changed flag.
3676 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
3678 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3685 Initialize Question's Edit copy from Storage for the whole Formset.
3687 @param Selection Selection contains the information about
3688 the Selection, form and formset to be displayed.
3689 Selection action may be updated in retrieve callback.
3690 If Selection is NULL, only initialize Question value.
3691 @param FormSet FormSet data structure.
3693 @retval EFI_SUCCESS The function completed successfully.
3698 IN OUT UI_MENU_SELECTION
*Selection
,
3699 IN FORM_BROWSER_FORMSET
*FormSet
3704 FORM_BROWSER_FORM
*Form
;
3706 Link
= GetFirstNode (&FormSet
->FormListHead
);
3707 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3708 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3711 // Initialize local copy of Value for each Form
3713 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3714 if (EFI_ERROR (Status
)) {
3718 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3722 // Finished question initialization.
3724 FormSet
->QuestionInited
= TRUE
;
3730 Remove the Request element from the Config Request.
3732 @param Storage Pointer to the browser storage.
3733 @param RequestElement The pointer to the Request element.
3738 IN OUT BROWSER_STORAGE
*Storage
,
3739 IN CHAR16
*RequestElement
3745 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3747 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3749 if (NewStr
== NULL
) {
3754 // Remove this element from this ConfigRequest.
3757 NewStr
+= StrLen (RequestElement
);
3758 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3760 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3764 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3766 @param Storage Pointer to the browser storage.
3767 @param ConfigRequest The pointer to the Request element.
3771 RemoveConfigRequest (
3772 BROWSER_STORAGE
*Storage
,
3773 CHAR16
*ConfigRequest
3776 CHAR16
*RequestElement
;
3777 CHAR16
*NextRequestElement
;
3781 // No request element in it, just return.
3783 if (ConfigRequest
== NULL
) {
3787 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3789 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3794 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3796 SearchKey
= L
"&OFFSET";
3800 // Find SearchKey storage
3802 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3803 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3804 ASSERT (RequestElement
!= NULL
);
3805 RequestElement
= StrStr (RequestElement
, SearchKey
);
3807 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3810 while (RequestElement
!= NULL
) {
3812 // +1 to avoid find header itself.
3814 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3817 // The last Request element in configRequest string.
3819 if (NextRequestElement
!= NULL
) {
3821 // Replace "&" with '\0'.
3823 *NextRequestElement
= L
'\0';
3826 RemoveElement (Storage
, RequestElement
);
3828 if (NextRequestElement
!= NULL
) {
3830 // Restore '&' with '\0' for later used.
3832 *NextRequestElement
= L
'&';
3835 RequestElement
= NextRequestElement
;
3839 // If no request element remain, just remove the ConfigRequest string.
3841 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3842 FreePool (Storage
->ConfigRequest
);
3843 Storage
->ConfigRequest
= NULL
;
3844 Storage
->SpareStrLen
= 0;
3849 Base on the current formset info, clean the ConfigRequest string in browser storage.
3851 @param FormSet Pointer of the FormSet
3855 CleanBrowserStorage (
3856 IN OUT FORM_BROWSER_FORMSET
*FormSet
3860 FORMSET_STORAGE
*Storage
;
3861 CHAR16
*ConfigRequest
;
3863 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3864 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3865 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3866 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3868 if ((Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_BUFFER
) &&
3869 (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) &&
3870 (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3874 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3878 ConfigRequest
= FormSet
->QuestionInited
? Storage
->ConfigRequest
: Storage
->ConfigElements
;
3879 RemoveConfigRequest (Storage
->BrowserStorage
, ConfigRequest
);
3884 Check whether current element in the ConfigReqeust string.
3886 @param BrowserStorage Storage which includes ConfigReqeust.
3887 @param RequestElement New element need to check.
3889 @retval TRUE The Element is in the ConfigReqeust string.
3890 @retval FALSE The Element not in the configReqeust String.
3895 BROWSER_STORAGE
*BrowserStorage
,
3896 CHAR16
*RequestElement
3899 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3903 Append the Request element to the Config Request.
3905 @param ConfigRequest Current ConfigRequest info.
3906 @param SpareStrLen Current remain free buffer for config reqeust.
3907 @param RequestElement New Request element.
3911 AppendConfigRequest (
3912 IN OUT CHAR16
**ConfigRequest
,
3913 IN OUT UINTN
*SpareStrLen
,
3914 IN CHAR16
*RequestElement
3921 StrLength
= StrLen (RequestElement
);
3924 // Append <RequestElement> to <ConfigRequest>
3926 if (StrLength
> *SpareStrLen
) {
3928 // Old String buffer is not sufficient for RequestElement, allocate a new one
3930 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3931 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3932 ASSERT (NewStr
!= NULL
);
3934 if (*ConfigRequest
!= NULL
) {
3935 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3936 FreePool (*ConfigRequest
);
3938 *ConfigRequest
= NewStr
;
3939 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3942 StrCat (*ConfigRequest
, RequestElement
);
3943 *SpareStrLen
-= StrLength
;
3947 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3949 @param Storage Form set Storage.
3951 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3952 @retval FALSE All elements covered by current used elements.
3956 ConfigRequestAdjust (
3957 IN FORMSET_STORAGE
*Storage
3960 CHAR16
*RequestElement
;
3961 CHAR16
*NextRequestElement
;
3971 if (Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3972 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3973 if (Storage
->ConfigElements
!= NULL
) {
3974 FreePool (Storage
->ConfigElements
);
3976 Storage
->ConfigElements
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
3980 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3982 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3987 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3989 SearchKey
= L
"&OFFSET";
3993 // Prepare the config header.
3995 RetBuf
= AllocateCopyPool(StrSize (Storage
->BrowserStorage
->ConfigHdr
), Storage
->BrowserStorage
->ConfigHdr
);
3996 ASSERT (RetBuf
!= NULL
);
3999 // Find SearchKey storage
4001 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4002 RequestElement
= StrStr (Storage
->ConfigRequest
, L
"PATH");
4003 ASSERT (RequestElement
!= NULL
);
4004 RequestElement
= StrStr (RequestElement
, SearchKey
);
4006 RequestElement
= StrStr (Storage
->ConfigRequest
, SearchKey
);
4009 while (RequestElement
!= NULL
) {
4011 // +1 to avoid find header itself.
4013 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4016 // The last Request element in configRequest string.
4018 if (NextRequestElement
!= NULL
) {
4020 // Replace "&" with '\0'.
4022 *NextRequestElement
= L
'\0';
4025 if (!ElementValidation (Storage
->BrowserStorage
, RequestElement
)) {
4027 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4029 AppendConfigRequest(&Storage
->BrowserStorage
->ConfigRequest
, &Storage
->BrowserStorage
->SpareStrLen
, RequestElement
);
4030 AppendConfigRequest (&RetBuf
, &SpareBufLen
, RequestElement
);
4034 if (NextRequestElement
!= NULL
) {
4036 // Restore '&' with '\0' for later used.
4038 *NextRequestElement
= L
'&';
4041 RequestElement
= NextRequestElement
;
4045 if (Storage
->ConfigElements
!= NULL
) {
4046 FreePool (Storage
->ConfigElements
);
4048 Storage
->ConfigElements
= RetBuf
;
4058 Base on ConfigRequest info to get default value for current formset.
4060 ConfigRequest info include the info about which questions in current formset need to
4061 get default value. This function only get these questions default value.
4063 @param FormSet FormSet data structure.
4064 @param Storage Storage need to update value.
4065 @param ConfigRequest The config request string.
4069 GetDefaultForFormset (
4070 IN FORM_BROWSER_FORMSET
*FormSet
,
4071 IN BROWSER_STORAGE
*Storage
,
4072 IN CHAR16
*ConfigRequest
4077 LIST_ENTRY BackUpList
;
4078 NAME_VALUE_NODE
*Node
;
4080 LIST_ENTRY
*NodeLink
;
4081 NAME_VALUE_NODE
*TmpNode
;
4083 EFI_STRING Progress
;
4087 InitializeListHead(&BackUpList
);
4090 // Back update the edit buffer.
4092 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4093 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4094 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4095 ASSERT (BackUpBuf
!= NULL
);
4096 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4097 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4098 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4099 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4100 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4103 // Only back Node belong to this formset.
4105 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4109 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4110 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4111 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4113 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4118 // Get default value.
4120 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4123 // Update the question value based on the input ConfigRequest.
4125 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4126 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4127 ASSERT (BackUpBuf
!= NULL
);
4128 BufferSize
= Storage
->Size
;
4129 Status
= mHiiConfigRouting
->BlockToConfig(
4132 Storage
->EditBuffer
,
4137 ASSERT_EFI_ERROR (Status
);
4139 Status
= mHiiConfigRouting
->ConfigToBlock (
4146 ASSERT_EFI_ERROR (Status
);
4148 if (Result
!= NULL
) {
4152 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4153 FreePool (BackUpBuf
);
4154 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4156 // Update question value, only element in ConfigReqeust will be update.
4158 Link
= GetFirstNode (&BackUpList
);
4159 while (!IsNull (&BackUpList
, Link
)) {
4160 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4161 Link
= GetNextNode (&BackUpList
, Link
);
4163 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4167 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4168 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4169 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4170 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4172 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4176 FreePool (TmpNode
->EditValue
);
4177 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4179 RemoveEntryList (&Node
->Link
);
4180 FreePool (Node
->EditValue
);
4181 FreePool (Node
->Name
);
4187 // Restore the Name/Value node.
4189 Link
= GetFirstNode (&BackUpList
);
4190 while (!IsNull (&BackUpList
, Link
)) {
4191 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4192 Link
= GetNextNode (&BackUpList
, Link
);
4197 RemoveEntryList (&Node
->Link
);
4198 FreePool (Node
->EditValue
);
4199 FreePool (Node
->Name
);
4206 Fill storage's edit copy with settings requested from Configuration Driver.
4208 @param FormSet FormSet data structure.
4209 @param Storage Buffer Storage.
4214 IN FORM_BROWSER_FORMSET
*FormSet
,
4215 IN FORMSET_STORAGE
*Storage
4219 EFI_STRING Progress
;
4223 switch (Storage
->BrowserStorage
->Type
) {
4224 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4227 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4228 if (Storage
->BrowserStorage
->ReferenceCount
> 1) {
4229 ConfigRequestAdjust(Storage
);
4233 Status
= gRT
->GetVariable (
4234 Storage
->BrowserStorage
->Name
,
4235 &Storage
->BrowserStorage
->Guid
,
4237 (UINTN
*)&Storage
->BrowserStorage
->Size
,
4238 Storage
->BrowserStorage
->EditBuffer
4241 // If get variable fail, extract default from IFR binary
4243 if (EFI_ERROR (Status
)) {
4244 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4247 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4249 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4251 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4254 case EFI_HII_VARSTORE_BUFFER
:
4255 case EFI_HII_VARSTORE_NAME_VALUE
:
4257 // Skip if there is no RequestElement
4259 if (Storage
->ElementCount
== 0) {
4264 // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig
4265 // will used to call ExtractConfig.
4266 // If not elements need to udpate, return.
4268 if (!ConfigRequestAdjust(Storage
)) {
4271 ASSERT (Storage
->ConfigElements
!= NULL
);
4273 Status
= EFI_NOT_FOUND
;
4274 if (FormSet
->ConfigAccess
!= NULL
) {
4276 // Request current settings from Configuration Driver
4278 Status
= FormSet
->ConfigAccess
->ExtractConfig (
4279 FormSet
->ConfigAccess
,
4280 Storage
->ConfigElements
,
4285 if (!EFI_ERROR (Status
)) {
4287 // Convert Result from <ConfigAltResp> to <ConfigResp>
4289 StrPtr
= StrStr (Result
, L
"&GUID=");
4290 if (StrPtr
!= NULL
) {
4294 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4299 if (EFI_ERROR (Status
)) {
4301 // Base on the configRequest string to get default value.
4303 GetDefaultForFormset (FormSet
, Storage
->BrowserStorage
, Storage
->ConfigElements
);
4306 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigElements
, TRUE
);
4315 Get current setting of Questions.
4317 @param FormSet FormSet data structure.
4321 InitializeCurrentSetting (
4322 IN OUT FORM_BROWSER_FORMSET
*FormSet
4326 FORMSET_STORAGE
*Storage
;
4327 FORM_BROWSER_FORMSET
*OldFormSet
;
4330 // Extract default from IFR binary for no storage questions.
4332 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4335 // Request current settings from Configuration Driver
4337 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4338 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4339 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4341 LoadStorage (FormSet
, Storage
);
4343 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4347 // Try to find pre FormSet in the maintain backup list.
4348 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4350 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4351 if (OldFormSet
!= NULL
) {
4352 RemoveEntryList (&OldFormSet
->Link
);
4353 DestroyFormSet (OldFormSet
);
4355 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4360 Fetch the Ifr binary data of a FormSet.
4362 @param Handle PackageList Handle
4363 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4364 specified (NULL or zero GUID), take the first
4365 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4366 found in package list.
4367 On output, GUID of the formset found(if not NULL).
4368 @param BinaryLength The length of the FormSet IFR binary.
4369 @param BinaryData The buffer designed to receive the FormSet.
4371 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4372 BufferLength was updated.
4373 @retval EFI_INVALID_PARAMETER The handle is unknown.
4374 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4375 be found with the requested FormId.
4380 IN EFI_HII_HANDLE Handle
,
4381 IN OUT EFI_GUID
*FormSetGuid
,
4382 OUT UINTN
*BinaryLength
,
4383 OUT UINT8
**BinaryData
4387 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4393 UINT32 PackageListLength
;
4394 EFI_HII_PACKAGE_HEADER PackageHeader
;
4396 UINT8 NumberOfClassGuid
;
4397 BOOLEAN ClassGuidMatch
;
4398 EFI_GUID
*ClassGuid
;
4399 EFI_GUID
*ComparingGuid
;
4403 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4406 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4408 if (FormSetGuid
== NULL
) {
4409 ComparingGuid
= &gZeroGuid
;
4411 ComparingGuid
= FormSetGuid
;
4415 // Get HII PackageList
4418 HiiPackageList
= NULL
;
4419 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4420 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4421 HiiPackageList
= AllocatePool (BufferSize
);
4422 ASSERT (HiiPackageList
!= NULL
);
4424 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4426 if (EFI_ERROR (Status
)) {
4429 ASSERT (HiiPackageList
!= NULL
);
4432 // Get Form package from this HII package List
4434 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4436 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4438 ClassGuidMatch
= FALSE
;
4439 while (Offset
< PackageListLength
) {
4440 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4441 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4443 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4445 // Search FormSet in this Form Package
4447 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4448 while (Offset2
< PackageHeader
.Length
) {
4449 OpCodeData
= Package
+ Offset2
;
4451 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4453 // Try to compare against formset GUID
4455 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4456 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4460 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4462 // Try to compare against formset class GUID
4464 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4465 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4466 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4467 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4468 ClassGuidMatch
= TRUE
;
4472 if (ClassGuidMatch
) {
4475 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4476 ClassGuidMatch
= TRUE
;
4481 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4484 if (Offset2
< PackageHeader
.Length
) {
4486 // Target formset found
4492 Offset
+= PackageHeader
.Length
;
4495 if (Offset
>= PackageListLength
) {
4497 // Form package not found in this Package List
4499 FreePool (HiiPackageList
);
4500 return EFI_NOT_FOUND
;
4503 if (FormSetGuid
!= NULL
) {
4505 // Return the FormSet GUID
4507 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4511 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4512 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4513 // of the Form Package.
4515 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4516 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4518 FreePool (HiiPackageList
);
4520 if (*BinaryData
== NULL
) {
4521 return EFI_OUT_OF_RESOURCES
;
4529 Initialize the internal data structure of a FormSet.
4531 @param Handle PackageList Handle
4532 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4533 specified (NULL or zero GUID), take the first
4534 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4535 found in package list.
4536 On output, GUID of the formset found(if not NULL).
4537 @param FormSet FormSet data structure.
4539 @retval EFI_SUCCESS The function completed successfully.
4540 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4545 IN EFI_HII_HANDLE Handle
,
4546 IN OUT EFI_GUID
*FormSetGuid
,
4547 OUT FORM_BROWSER_FORMSET
*FormSet
4551 EFI_HANDLE DriverHandle
;
4553 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4554 if (EFI_ERROR (Status
)) {
4558 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4559 FormSet
->HiiHandle
= Handle
;
4560 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4561 FormSet
->QuestionInited
= FALSE
;
4564 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4566 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4567 if (EFI_ERROR (Status
)) {
4570 FormSet
->DriverHandle
= DriverHandle
;
4571 Status
= gBS
->HandleProtocol (
4573 &gEfiHiiConfigAccessProtocolGuid
,
4574 (VOID
**) &FormSet
->ConfigAccess
4576 if (EFI_ERROR (Status
)) {
4578 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4579 // list, then there will be no configuration action required
4581 FormSet
->ConfigAccess
= NULL
;
4585 // Parse the IFR binary OpCodes
4587 Status
= ParseOpCodes (FormSet
);
4594 Save globals used by previous call to SendForm(). SendForm() may be called from
4595 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4596 So, save globals of previous call to SendForm() and restore them upon exit.
4600 SaveBrowserContext (
4604 BROWSER_CONTEXT
*Context
;
4605 FORM_ENTRY_INFO
*MenuList
;
4607 gBrowserContextCount
++;
4608 if (gBrowserContextCount
== 1) {
4610 // This is not reentry of SendForm(), no context to save
4616 // Not support SendForm nest in another SendForm, assert here.
4620 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4621 ASSERT (Context
!= NULL
);
4623 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4626 // Save FormBrowser context
4628 Context
->ResetRequired
= gResetRequired
;
4629 Context
->ExitRequired
= gExitRequired
;
4630 Context
->HiiHandle
= mCurrentHiiHandle
;
4633 // Save the menu history data.
4635 InitializeListHead(&Context
->FormHistoryList
);
4636 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4637 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4638 RemoveEntryList (&MenuList
->Link
);
4640 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4644 // Insert to FormBrowser context list
4646 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4651 Restore globals used by previous call to SendForm().
4655 RestoreBrowserContext (
4660 BROWSER_CONTEXT
*Context
;
4661 FORM_ENTRY_INFO
*MenuList
;
4663 ASSERT (gBrowserContextCount
!= 0);
4664 gBrowserContextCount
--;
4665 if (gBrowserContextCount
== 0) {
4667 // This is not reentry of SendForm(), no context to restore
4672 ASSERT (!IsListEmpty (&gBrowserContextList
));
4674 Link
= GetFirstNode (&gBrowserContextList
);
4675 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4678 // Restore FormBrowser context
4680 gResetRequired
= Context
->ResetRequired
;
4681 gExitRequired
= Context
->ExitRequired
;
4682 mCurrentHiiHandle
= Context
->HiiHandle
;
4685 // Restore the menu history data.
4687 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4688 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4689 RemoveEntryList (&MenuList
->Link
);
4691 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4695 // Remove from FormBrowser context list
4697 RemoveEntryList (&Context
->Link
);
4698 gBS
->FreePool (Context
);
4702 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4704 @param Handle The Hii Handle.
4706 @return the found FormSet context. If no found, NULL will return.
4709 FORM_BROWSER_FORMSET
*
4710 GetFormSetFromHiiHandle (
4711 EFI_HII_HANDLE Handle
4715 FORM_BROWSER_FORMSET
*FormSet
;
4717 Link
= GetFirstNode (&gBrowserFormSetList
);
4718 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4719 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4720 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4721 if (!ValidateFormSet(FormSet
)) {
4724 if (FormSet
->HiiHandle
== Handle
) {
4733 Check whether the input HII handle is the FormSet that is being used.
4735 @param Handle The Hii Handle.
4737 @retval TRUE HII handle is being used.
4738 @retval FALSE HII handle is not being used.
4742 IsHiiHandleInBrowserContext (
4743 EFI_HII_HANDLE Handle
4747 BROWSER_CONTEXT
*Context
;
4750 // HiiHandle is Current FormSet.
4752 if (mCurrentHiiHandle
== Handle
) {
4757 // Check whether HiiHandle is in BrowserContext.
4759 Link
= GetFirstNode (&gBrowserContextList
);
4760 while (!IsNull (&gBrowserContextList
, Link
)) {
4761 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4762 if (Context
->HiiHandle
== Handle
) {
4764 // HiiHandle is in BrowserContext
4768 Link
= GetNextNode (&gBrowserContextList
, Link
);
4775 Perform Password check.
4776 Passwork may be encrypted by driver that requires the specific check.
4778 @param Form Form where Password Statement is in.
4779 @param Statement Password statement
4780 @param PasswordString Password string to be checked. It may be NULL.
4781 NULL means to restore password.
4782 "" string can be used to checked whether old password does exist.
4784 @return Status Status of Password check.
4789 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4790 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4791 IN EFI_STRING PasswordString OPTIONAL
4795 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4796 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4797 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4798 FORM_BROWSER_STATEMENT
*Question
;
4800 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4801 Question
= GetBrowserStatement(Statement
);
4802 ASSERT (Question
!= NULL
);
4804 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4805 if (ConfigAccess
== NULL
) {
4806 return EFI_UNSUPPORTED
;
4809 if (PasswordString
== NULL
) {
4813 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4816 return EFI_NOT_READY
;
4821 // Prepare password string in HII database
4823 if (PasswordString
!= NULL
) {
4824 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4826 IfrTypeValue
.string
= 0;
4830 // Send password to Configuration Driver for validation
4832 Status
= ConfigAccess
->Callback (
4834 EFI_BROWSER_ACTION_CHANGING
,
4835 Question
->QuestionId
,
4836 Question
->HiiValue
.Type
,
4842 // Remove password string from HII database
4844 if (PasswordString
!= NULL
) {
4845 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4852 Find the registered HotKey based on KeyData.
4854 @param[in] KeyData A pointer to a buffer that describes the keystroke
4855 information for the hot key.
4857 @return The registered HotKey context. If no found, NULL will return.
4860 GetHotKeyFromRegisterList (
4861 IN EFI_INPUT_KEY
*KeyData
4865 BROWSER_HOT_KEY
*HotKey
;
4867 Link
= GetFirstNode (&gBrowserHotKeyList
);
4868 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4869 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4870 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4873 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4880 Configure what scope the hot key will impact.
4881 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4882 If no scope is set, the default scope will be FormSet level.
4883 After all registered hot keys are removed, previous Scope can reset to another level.
4885 @param[in] Scope Scope level to be set.
4887 @retval EFI_SUCCESS Scope is set correctly.
4888 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4889 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4895 IN BROWSER_SETTING_SCOPE Scope
4898 if (Scope
>= MaxLevel
) {
4899 return EFI_INVALID_PARAMETER
;
4903 // When no hot key registered in system or on the first setting,
4904 // Scope can be set.
4906 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4907 gBrowserSettingScope
= Scope
;
4908 mBrowserScopeFirstSet
= FALSE
;
4909 } else if (Scope
!= gBrowserSettingScope
) {
4910 return EFI_UNSUPPORTED
;
4917 Register the hot key with its browser action, or unregistered the hot key.
4918 Only support hot key that is not printable character (control key, function key, etc.).
4919 If the action value is zero, the hot key will be unregistered if it has been registered.
4920 If the same hot key has been registered, the new action and help string will override the previous ones.
4922 @param[in] KeyData A pointer to a buffer that describes the keystroke
4923 information for the hot key. Its type is EFI_INPUT_KEY to
4924 be supported by all ConsoleIn devices.
4925 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4926 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4927 @param[in] HelpString Help string that describes the hot key information.
4928 Its value may be NULL for the unregistered hot key.
4930 @retval EFI_SUCCESS Hot key is registered or unregistered.
4931 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4932 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4933 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4938 IN EFI_INPUT_KEY
*KeyData
,
4940 IN UINT16 DefaultId
,
4941 IN EFI_STRING HelpString OPTIONAL
4944 BROWSER_HOT_KEY
*HotKey
;
4947 // Check input parameters.
4949 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4950 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4951 return EFI_INVALID_PARAMETER
;
4955 // Check whether the input KeyData is in BrowserHotKeyList.
4957 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4960 // Unregister HotKey
4962 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4963 if (HotKey
!= NULL
) {
4965 // The registered HotKey is found.
4966 // Remove it from List, and free its resource.
4968 RemoveEntryList (&HotKey
->Link
);
4969 FreePool (HotKey
->KeyData
);
4970 FreePool (HotKey
->HelpString
);
4974 // The registered HotKey is not found.
4976 return EFI_NOT_FOUND
;
4981 // Register HotKey into List.
4983 if (HotKey
== NULL
) {
4985 // Create new Key, and add it into List.
4987 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4988 ASSERT (HotKey
!= NULL
);
4989 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4990 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4991 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4995 // Fill HotKey information.
4997 HotKey
->Action
= Action
;
4998 HotKey
->DefaultId
= DefaultId
;
4999 if (HotKey
->HelpString
!= NULL
) {
5000 FreePool (HotKey
->HelpString
);
5002 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5008 Register Exit handler function.
5009 When more than one handler function is registered, the latter one will override the previous one.
5010 When NULL handler is specified, the previous Exit handler will be unregistered.
5012 @param[in] Handler Pointer to handler function.
5017 RegiserExitHandler (
5018 IN EXIT_HANDLER Handler
5021 ExitHandlerFunction
= Handler
;
5026 Check whether the browser data has been modified.
5028 @retval TRUE Browser data is modified.
5029 @retval FALSE No browser data is modified.
5034 IsBrowserDataModified (
5039 FORM_BROWSER_FORMSET
*FormSet
;
5041 if (gCurrentSelection
== NULL
) {
5045 switch (gBrowserSettingScope
) {
5047 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5050 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5053 Link
= GetFirstNode (&gBrowserFormSetList
);
5054 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5055 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5056 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5059 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5069 Execute the action requested by the Action parameter.
5071 @param[in] Action Execute the request action.
5072 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5074 @retval EFI_SUCCESS Execute the request action succss.
5075 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5087 if (gCurrentSelection
== NULL
) {
5088 return EFI_NOT_READY
;
5091 Status
= EFI_SUCCESS
;
5094 // Executet the discard action.
5096 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5097 Status
= DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5098 if (EFI_ERROR (Status
)) {
5104 // Executet the difault action.
5106 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5107 Status
= ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5108 if (EFI_ERROR (Status
)) {
5114 // Executet the submit action.
5116 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5117 Status
= SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5118 if (EFI_ERROR (Status
)) {
5124 // Executet the reset action.
5126 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5127 gResetRequired
= TRUE
;
5131 // Executet the exit action.
5133 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5134 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5135 if (gBrowserSettingScope
== SystemLevel
) {
5136 if (ExitHandlerFunction
!= NULL
) {
5137 ExitHandlerFunction ();
5141 gExitRequired
= TRUE
;
5148 Create reminder to let user to choose save or discard the changed browser data.
5149 Caller can use it to actively check the changed browser data.
5151 @retval BROWSER_NO_CHANGES No browser data is changed.
5152 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5153 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5163 FORM_BROWSER_FORMSET
*FormSet
;
5164 BOOLEAN IsDataChanged
;
5165 UINT32 DataSavedAction
;
5167 DataSavedAction
= BROWSER_NO_CHANGES
;
5168 IsDataChanged
= FALSE
;
5169 Link
= GetFirstNode (&gBrowserFormSetList
);
5170 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5171 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5172 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5173 if (!ValidateFormSet(FormSet
)) {
5176 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5177 IsDataChanged
= TRUE
;
5183 // No data is changed. No save is required.
5185 if (!IsDataChanged
) {
5186 return DataSavedAction
;
5190 // If data is changed, prompt user to save or discard it.
5193 DataSavedAction
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5195 if (DataSavedAction
== BROWSER_SAVE_CHANGES
) {
5196 SubmitForm (NULL
, NULL
, SystemLevel
);
5198 } else if (DataSavedAction
== BROWSER_DISCARD_CHANGES
) {
5199 DiscardForm (NULL
, NULL
, SystemLevel
);
5204 return DataSavedAction
;