2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2011, 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
,
26 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
27 EFI_HII_STRING_PROTOCOL
*mHiiString
;
28 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
30 UINTN gBrowserContextCount
= 0;
31 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
33 BANNER_DATA
*gBannerData
;
34 EFI_HII_HANDLE gFrontPageHandle
;
36 UINTN gFunctionKeySetting
;
37 BOOLEAN gResetRequired
;
38 EFI_HII_HANDLE gHiiHandle
;
40 EFI_SCREEN_DESCRIPTOR gScreenDimensions
;
43 // Browser Global Strings
45 CHAR16
*gFunctionNineString
;
46 CHAR16
*gFunctionTenString
;
48 CHAR16
*gEnterCommitString
;
49 CHAR16
*gEnterEscapeString
;
50 CHAR16
*gEscapeString
;
52 CHAR16
*gMoveHighlight
;
53 CHAR16
*gMakeSelection
;
54 CHAR16
*gDecNumericInput
;
55 CHAR16
*gHexNumericInput
;
56 CHAR16
*gToggleCheckBox
;
57 CHAR16
*gPromptForData
;
58 CHAR16
*gPromptForPassword
;
59 CHAR16
*gPromptForNewPassword
;
60 CHAR16
*gConfirmPassword
;
61 CHAR16
*gConfirmError
;
62 CHAR16
*gPassowordInvalid
;
71 CHAR16
*gAdjustNumber
;
73 CHAR16
*gOptionMismatch
;
74 CHAR16
*gFormSuppress
;
76 CHAR16
*mUnknownString
= L
"!";
78 CHAR16 gPromptBlockWidth
;
79 CHAR16 gOptionBlockWidth
;
80 CHAR16 gHelpBlockWidth
;
82 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
83 EFI_GUID gSetupBrowserGuid
= {
84 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
87 FORM_BROWSER_FORMSET
*gOldFormSet
;
89 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
109 NONE_FUNCTION_KEY_SETTING
130 NONE_FUNCTION_KEY_SETTING
151 NONE_FUNCTION_KEY_SETTING
154 // BMM File Explorer FormSet.
172 NONE_FUNCTION_KEY_SETTING
177 This is the routine which an external caller uses to direct the browser
178 where to obtain it's information.
181 @param This The Form Browser protocol instanse.
182 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
183 display a list of the formsets for the handles specified.
184 @param HandleCount The number of Handles specified in Handle.
185 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
186 field in the EFI_IFR_FORM_SET op-code for the specified
187 forms-based package. If FormSetGuid is NULL, then this
188 function will display the first found forms package.
189 @param FormId This field specifies which EFI_IFR_FORM to render as the first
190 displayable page. If this field has a value of 0x0000, then
191 the forms browser will render the specified forms in their encoded order.
192 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
194 @param ActionRequest Points to the action recommended by the form.
196 @retval EFI_SUCCESS The function completed successfully.
197 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
198 @retval EFI_NOT_FOUND No valid forms could be found to display.
204 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
205 IN EFI_HII_HANDLE
*Handles
,
206 IN UINTN HandleCount
,
207 IN EFI_GUID
*FormSetGuid
, OPTIONAL
208 IN UINT16 FormId
, OPTIONAL
209 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
210 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
214 UI_MENU_SELECTION
*Selection
;
216 FORM_BROWSER_FORMSET
*FormSet
;
219 // Save globals used by SendForm()
221 SaveBrowserContext ();
223 Status
= EFI_SUCCESS
;
224 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
227 // Seed the dimensions in the global
229 gST
->ConOut
->QueryMode (
231 gST
->ConOut
->Mode
->Mode
,
232 &gScreenDimensions
.RightColumn
,
233 &gScreenDimensions
.BottomRow
236 if (ScreenDimensions
!= NULL
) {
238 // Check local dimension vs. global dimension.
240 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
241 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
243 Status
= EFI_INVALID_PARAMETER
;
247 // Local dimension validation.
249 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
250 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
251 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
253 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
254 SCROLL_ARROW_HEIGHT
*
256 FRONT_PAGE_HEADER_HEIGHT
+
261 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
263 Status
= EFI_INVALID_PARAMETER
;
269 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
270 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
271 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
274 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
276 InitializeBrowserStrings ();
278 gFunctionKeySetting
= DEFAULT_FUNCTION_KEY_SETTING
;
281 // Ensure we are in Text mode
283 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
285 for (Index
= 0; Index
< HandleCount
; Index
++) {
286 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
287 ASSERT (Selection
!= NULL
);
289 Selection
->Handle
= Handles
[Index
];
290 if (FormSetGuid
!= NULL
) {
291 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
292 Selection
->FormId
= FormId
;
298 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
299 ASSERT (FormSet
!= NULL
);
302 // Initialize internal data structures of FormSet
304 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
305 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
306 DestroyFormSet (FormSet
);
309 Selection
->FormSet
= FormSet
;
312 // Display this formset
314 gCurrentSelection
= Selection
;
316 Status
= SetupBrowser (Selection
);
318 gCurrentSelection
= NULL
;
320 if (EFI_ERROR (Status
)) {
324 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
326 if (gOldFormSet
!= NULL
) {
327 DestroyFormSet (gOldFormSet
);
331 FreePool (Selection
);
334 if (ActionRequest
!= NULL
) {
335 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
336 if (gResetRequired
) {
337 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
341 FreeBrowserStrings ();
343 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
344 gST
->ConOut
->ClearScreen (gST
->ConOut
);
348 // Restore globals used by SendForm()
350 RestoreBrowserContext ();
357 This function is called by a callback handler to retrieve uncommitted state
358 data from the browser.
360 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
362 @param ResultsDataSize A pointer to the size of the buffer associated
364 @param ResultsData A string returned from an IFR browser or
365 equivalent. The results string will have no
366 routing information in them.
367 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
368 (if RetrieveData = TRUE) data from the uncommitted
369 browser state information or set (if RetrieveData
370 = FALSE) data in the uncommitted browser state
372 @param VariableGuid An optional field to indicate the target variable
374 @param VariableName An optional field to indicate the target
375 human-readable variable name.
377 @retval EFI_SUCCESS The results have been distributed or are awaiting
379 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
380 contain the results data.
386 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
387 IN OUT UINTN
*ResultsDataSize
,
388 IN OUT EFI_STRING ResultsData
,
389 IN BOOLEAN RetrieveData
,
390 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
391 IN CONST CHAR16
*VariableName OPTIONAL
396 FORMSET_STORAGE
*Storage
;
397 FORM_BROWSER_FORMSET
*FormSet
;
404 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
405 return EFI_INVALID_PARAMETER
;
408 if (gCurrentSelection
== NULL
) {
409 return EFI_NOT_READY
;
414 FormSet
= gCurrentSelection
->FormSet
;
417 // Find target storage
419 Link
= GetFirstNode (&FormSet
->StorageListHead
);
420 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
421 return EFI_UNSUPPORTED
;
424 if (VariableGuid
!= NULL
) {
426 // Try to find target storage
429 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
430 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
431 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
433 if (CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
434 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
436 // Buffer storage require both GUID and Name
438 if (VariableName
== NULL
) {
439 return EFI_NOT_FOUND
;
442 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
452 return EFI_NOT_FOUND
;
456 // GUID/Name is not specified, take the first storage in FormSet
458 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
463 // Skip if there is no RequestElement
465 if (Storage
->ElementCount
== 0) {
470 // Generate <ConfigResp>
472 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
473 if (EFI_ERROR (Status
)) {
478 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
480 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
482 BufferSize
= StrSize (StrPtr
);
483 if (*ResultsDataSize
< BufferSize
) {
484 *ResultsDataSize
= BufferSize
;
486 FreePool (ConfigResp
);
487 return EFI_BUFFER_TOO_SMALL
;
490 *ResultsDataSize
= BufferSize
;
491 CopyMem (ResultsData
, StrPtr
, BufferSize
);
493 FreePool (ConfigResp
);
496 // Prepare <ConfigResp>
498 TmpSize
= StrLen (ResultsData
);
499 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
500 ConfigResp
= AllocateZeroPool (BufferSize
);
501 ASSERT (ConfigResp
!= NULL
);
503 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
504 StrCat (ConfigResp
, L
"&");
505 StrCat (ConfigResp
, ResultsData
);
508 // Update Browser uncommited data
510 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
511 if (EFI_ERROR (Status
)) {
521 Initialize Setup Browser driver.
523 @param ImageHandle The image handle.
524 @param SystemTable The system table.
526 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
527 @return Other value if failed to initialize the Setup Browser module.
533 IN EFI_HANDLE ImageHandle
,
534 IN EFI_SYSTEM_TABLE
*SystemTable
540 // Locate required Hii relative protocols
542 Status
= gBS
->LocateProtocol (
543 &gEfiHiiDatabaseProtocolGuid
,
545 (VOID
**) &mHiiDatabase
547 ASSERT_EFI_ERROR (Status
);
549 Status
= gBS
->LocateProtocol (
550 &gEfiHiiStringProtocolGuid
,
552 (VOID
**) &mHiiString
554 ASSERT_EFI_ERROR (Status
);
556 Status
= gBS
->LocateProtocol (
557 &gEfiHiiConfigRoutingProtocolGuid
,
559 (VOID
**) &mHiiConfigRouting
561 ASSERT_EFI_ERROR (Status
);
564 // Publish our HII data
566 gHiiHandle
= HiiAddPackages (
572 ASSERT (gHiiHandle
!= NULL
);
575 // Initialize Driver private data
577 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
578 ASSERT (gBannerData
!= NULL
);
581 // Install FormBrowser2 protocol
583 mPrivateData
.Handle
= NULL
;
584 Status
= gBS
->InstallProtocolInterface (
585 &mPrivateData
.Handle
,
586 &gEfiFormBrowser2ProtocolGuid
,
587 EFI_NATIVE_INTERFACE
,
588 &mPrivateData
.FormBrowser2
590 ASSERT_EFI_ERROR (Status
);
597 Create a new string in HII Package List.
599 @param String The String to be added
600 @param HiiHandle The package list in the HII database to insert the
603 @return The output string.
609 IN EFI_HII_HANDLE HiiHandle
612 EFI_STRING_ID StringId
;
614 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
615 ASSERT (StringId
!= 0);
622 Delete a string from HII Package List.
624 @param StringId Id of the string in HII database.
625 @param HiiHandle The HII package list handle.
627 @retval EFI_SUCCESS The string was deleted successfully.
632 IN EFI_STRING_ID StringId
,
633 IN EFI_HII_HANDLE HiiHandle
638 NullChar
= CHAR_NULL
;
639 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
645 Get the string based on the StringId and HII Package List Handle.
647 @param Token The String's ID.
648 @param HiiHandle The package list in the HII database to search for
649 the specified string.
651 @return The output string.
656 IN EFI_STRING_ID Token
,
657 IN EFI_HII_HANDLE HiiHandle
662 if (HiiHandle
== NULL
) {
666 String
= HiiGetString (HiiHandle
, Token
, NULL
);
667 if (String
== NULL
) {
668 String
= AllocateCopyPool (sizeof (mUnknownString
), mUnknownString
);
669 ASSERT (String
!= NULL
);
671 return (CHAR16
*) String
;
676 Allocate new memory and then copy the Unicode string Source to Destination.
678 @param Dest Location to copy string
679 @param Src String to copy
684 IN OUT CHAR16
**Dest
,
691 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
692 ASSERT (*Dest
!= NULL
);
697 Allocate new memory and concatinate Source on the end of Destination.
699 @param Dest String to added to the end of.
700 @param Src String to concatinate.
705 IN OUT CHAR16
**Dest
,
713 NewStringCpy (Dest
, Src
);
717 TmpSize
= StrSize (*Dest
);
718 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
719 ASSERT (NewString
!= NULL
);
721 StrCpy (NewString
, *Dest
);
722 StrCat (NewString
, Src
);
730 Synchronize Storage's Edit copy to Shadow copy.
732 @param Storage The Storage to be synchronized.
737 IN FORMSET_STORAGE
*Storage
741 NAME_VALUE_NODE
*Node
;
743 switch (Storage
->Type
) {
744 case EFI_HII_VARSTORE_BUFFER
:
745 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
748 case EFI_HII_VARSTORE_NAME_VALUE
:
749 Link
= GetFirstNode (&Storage
->NameValueListHead
);
750 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
751 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
753 NewStringCpy (&Node
->Value
, Node
->EditValue
);
755 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
759 case EFI_HII_VARSTORE_EFI_VARIABLE
:
767 Get Value for given Name from a NameValue Storage.
769 @param Storage The NameValue Storage.
770 @param Name The Name.
771 @param Value The retured Value.
773 @retval EFI_SUCCESS Value found for given Name.
774 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
779 IN FORMSET_STORAGE
*Storage
,
781 IN OUT CHAR16
**Value
785 NAME_VALUE_NODE
*Node
;
789 Link
= GetFirstNode (&Storage
->NameValueListHead
);
790 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
791 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
793 if (StrCmp (Name
, Node
->Name
) == 0) {
794 NewStringCpy (Value
, Node
->EditValue
);
798 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
801 return EFI_NOT_FOUND
;
806 Set Value of given Name in a NameValue Storage.
808 @param Storage The NameValue Storage.
809 @param Name The Name.
810 @param Value The Value to set.
811 @param Edit Whether update editValue or Value.
813 @retval EFI_SUCCESS Value found for given Name.
814 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
819 IN FORMSET_STORAGE
*Storage
,
826 NAME_VALUE_NODE
*Node
;
829 Link
= GetFirstNode (&Storage
->NameValueListHead
);
830 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
831 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
833 if (StrCmp (Name
, Node
->Name
) == 0) {
835 Buffer
= Node
->EditValue
;
837 Buffer
= Node
->Value
;
839 if (Buffer
!= NULL
) {
842 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
843 ASSERT (Buffer
!= NULL
);
845 Node
->EditValue
= Buffer
;
847 Node
->Value
= Buffer
;
852 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
855 return EFI_NOT_FOUND
;
860 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
862 @param Buffer The Storage to be conveted.
863 @param ConfigResp The returned <ConfigResp>.
864 @param SingleForm Whether update data for single form or formset level.
866 @retval EFI_SUCCESS Convert success.
867 @retval EFI_INVALID_PARAMETER Incorrect storage type.
871 StorageToConfigResp (
873 IN CHAR16
**ConfigResp
,
874 IN BOOLEAN SingleForm
880 NAME_VALUE_NODE
*Node
;
881 CHAR16
*ConfigRequest
;
882 FORMSET_STORAGE
*Storage
;
883 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
885 Status
= EFI_SUCCESS
;
887 ConfigInfo
= (FORM_BROWSER_CONFIG_REQUEST
*) Buffer
;
888 Storage
= ConfigInfo
->Storage
;
889 ConfigRequest
= ConfigInfo
->ConfigRequest
;
891 Storage
= (FORMSET_STORAGE
*) Buffer
;
892 ConfigRequest
= Storage
->ConfigRequest
;
895 switch (Storage
->Type
) {
896 case EFI_HII_VARSTORE_BUFFER
:
897 Status
= mHiiConfigRouting
->BlockToConfig (
907 case EFI_HII_VARSTORE_NAME_VALUE
:
909 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
911 Link
= GetFirstNode (&Storage
->NameValueListHead
);
912 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
913 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
915 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
916 NewStringCat (ConfigResp
, L
"&");
917 NewStringCat (ConfigResp
, Node
->Name
);
918 NewStringCat (ConfigResp
, L
"=");
919 NewStringCat (ConfigResp
, Node
->EditValue
);
921 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
925 case EFI_HII_VARSTORE_EFI_VARIABLE
:
927 Status
= EFI_INVALID_PARAMETER
;
936 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
938 @param Storage The Storage to receive the settings.
939 @param ConfigResp The <ConfigResp> to be converted.
941 @retval EFI_SUCCESS Convert success.
942 @retval EFI_INVALID_PARAMETER Incorrect storage type.
946 ConfigRespToStorage (
947 IN FORMSET_STORAGE
*Storage
,
948 IN CHAR16
*ConfigResp
958 Status
= EFI_SUCCESS
;
960 switch (Storage
->Type
) {
961 case EFI_HII_VARSTORE_BUFFER
:
962 BufferSize
= Storage
->Size
;
963 Status
= mHiiConfigRouting
->ConfigToBlock (
972 case EFI_HII_VARSTORE_NAME_VALUE
:
973 StrPtr
= StrStr (ConfigResp
, L
"PATH");
974 if (StrPtr
== NULL
) {
977 StrPtr
= StrStr (ConfigResp
, L
"&");
978 while (StrPtr
!= NULL
) {
984 StrPtr
= StrStr (StrPtr
, L
"=");
985 if (StrPtr
== NULL
) {
995 StrPtr
= StrStr (StrPtr
, L
"&");
996 if (StrPtr
!= NULL
) {
999 SetValueByName (Storage
, Name
, Value
, TRUE
);
1003 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1005 Status
= EFI_INVALID_PARAMETER
;
1014 Get Question's current Value.
1016 @param FormSet FormSet data structure.
1017 @param Form Form data structure.
1018 @param Question Question to be initialized.
1019 @param Cached TRUE: get from Edit copy FALSE: get from original
1022 @retval EFI_SUCCESS The function completed successfully.
1027 IN FORM_BROWSER_FORMSET
*FormSet
,
1028 IN FORM_BROWSER_FORM
*Form
,
1029 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1039 FORMSET_STORAGE
*Storage
;
1040 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1041 CHAR16
*ConfigRequest
;
1049 BOOLEAN IsBufferStorage
;
1054 Status
= EFI_SUCCESS
;
1057 // Statement don't have storage, skip them
1059 if (Question
->QuestionId
== 0) {
1064 // Question value is provided by an Expression, evaluate it
1066 if (Question
->ValueExpression
!= NULL
) {
1067 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1068 if (!EFI_ERROR (Status
)) {
1069 CopyMem (&Question
->HiiValue
, &Question
->ValueExpression
->Result
, sizeof (EFI_HII_VALUE
));
1075 // Get question value by read expression.
1077 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1078 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1079 if (!EFI_ERROR (Status
) && (Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
)) {
1081 // Only update question value to the valid result.
1083 CopyMem (&Question
->HiiValue
, &Question
->ReadExpression
->Result
, sizeof (EFI_HII_VALUE
));
1089 // Question value is provided by RTC
1091 Storage
= Question
->Storage
;
1092 QuestionValue
= &Question
->HiiValue
.Value
;
1093 if (Storage
== NULL
) {
1095 // It's a Question without storage, or RTC date/time
1097 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1099 // Date and time define the same Flags bit
1101 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1102 case QF_DATE_STORAGE_TIME
:
1103 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1106 case QF_DATE_STORAGE_WAKEUP
:
1107 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1110 case QF_DATE_STORAGE_NORMAL
:
1113 // For date/time without storage
1118 if (EFI_ERROR (Status
)) {
1122 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1123 QuestionValue
->date
.Year
= EfiTime
.Year
;
1124 QuestionValue
->date
.Month
= EfiTime
.Month
;
1125 QuestionValue
->date
.Day
= EfiTime
.Day
;
1127 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1128 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1129 QuestionValue
->time
.Second
= EfiTime
.Second
;
1137 // Question value is provided by EFI variable
1139 StorageWidth
= Question
->StorageWidth
;
1140 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1141 if (Question
->BufferValue
!= NULL
) {
1142 Dst
= Question
->BufferValue
;
1144 Dst
= (UINT8
*) QuestionValue
;
1147 Status
= gRT
->GetVariable (
1148 Question
->VariableName
,
1155 // Always return success, even this EFI variable doesn't exist
1161 // Question Value is provided by Buffer Storage or NameValue Storage
1163 if (Question
->BufferValue
!= NULL
) {
1165 // This Question is password or orderedlist
1167 Dst
= Question
->BufferValue
;
1170 // Other type of Questions
1172 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1175 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
1176 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1178 if (IsBufferStorage
) {
1180 // Copy from storage Edit buffer
1182 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1185 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
);
1186 if (EFI_ERROR (Status
)) {
1190 ASSERT (Value
!= NULL
);
1191 LengthStr
= StrLen (Value
);
1192 Status
= EFI_SUCCESS
;
1195 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1196 // Add string tail char L'\0' into Length
1198 Length
= StorageWidth
+ sizeof (CHAR16
);
1199 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1200 Status
= EFI_BUFFER_TOO_SMALL
;
1202 StringPtr
= (CHAR16
*) Dst
;
1203 ZeroMem (TemStr
, sizeof (TemStr
));
1204 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1205 StrnCpy (TemStr
, Value
+ Index
, 4);
1206 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1209 // Add tailing L'\0' character
1211 StringPtr
[Index
/4] = L
'\0';
1214 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1215 Status
= EFI_BUFFER_TOO_SMALL
;
1217 ZeroMem (TemStr
, sizeof (TemStr
));
1218 for (Index
= 0; Index
< LengthStr
; Index
++) {
1219 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1220 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1221 if ((Index
& 1) == 0) {
1222 Dst
[Index
/2] = DigitUint8
;
1224 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1234 // Request current settings from Configuration Driver
1236 if (FormSet
->ConfigAccess
== NULL
) {
1237 return EFI_NOT_FOUND
;
1241 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1242 // <ConfigHdr> + "&" + <VariableName>
1244 if (IsBufferStorage
) {
1245 Length
= StrLen (Storage
->ConfigHdr
);
1246 Length
+= StrLen (Question
->BlockName
);
1248 Length
= StrLen (Storage
->ConfigHdr
);
1249 Length
+= StrLen (Question
->VariableName
) + 1;
1251 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1252 ASSERT (ConfigRequest
!= NULL
);
1254 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1255 if (IsBufferStorage
) {
1256 StrCat (ConfigRequest
, Question
->BlockName
);
1258 StrCat (ConfigRequest
, L
"&");
1259 StrCat (ConfigRequest
, Question
->VariableName
);
1262 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1263 FormSet
->ConfigAccess
,
1268 if (EFI_ERROR (Status
)) {
1273 // Skip <ConfigRequest>
1275 Value
= Result
+ Length
;
1276 if (IsBufferStorage
) {
1282 if (*Value
!= '=') {
1284 return EFI_NOT_FOUND
;
1287 // Skip '=', point to value
1292 // Suppress <AltResp> if any
1295 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1300 LengthStr
= StrLen (Value
);
1301 Status
= EFI_SUCCESS
;
1302 if (!IsBufferStorage
&& IsString
) {
1304 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1305 // Add string tail char L'\0' into Length
1307 Length
= StorageWidth
+ sizeof (CHAR16
);
1308 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1309 Status
= EFI_BUFFER_TOO_SMALL
;
1311 StringPtr
= (CHAR16
*) Dst
;
1312 ZeroMem (TemStr
, sizeof (TemStr
));
1313 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1314 StrnCpy (TemStr
, Value
+ Index
, 4);
1315 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1318 // Add tailing L'\0' character
1320 StringPtr
[Index
/4] = L
'\0';
1323 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1324 Status
= EFI_BUFFER_TOO_SMALL
;
1326 ZeroMem (TemStr
, sizeof (TemStr
));
1327 for (Index
= 0; Index
< LengthStr
; Index
++) {
1328 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1329 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1330 if ((Index
& 1) == 0) {
1331 Dst
[Index
/2] = DigitUint8
;
1333 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1339 if (EFI_ERROR (Status
)) {
1345 // Synchronize Edit Buffer
1347 if (IsBufferStorage
) {
1348 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1350 SetValueByName (Storage
, Question
->VariableName
, Value
, TRUE
);
1361 Save Question Value to edit copy(cached) or Storage(uncached).
1363 @param FormSet FormSet data structure.
1364 @param Form Form data structure.
1365 @param Question Pointer to the Question.
1366 @param Cached TRUE: set to Edit copy FALSE: set to original
1369 @retval EFI_SUCCESS The function completed successfully.
1374 IN FORM_BROWSER_FORMSET
*FormSet
,
1375 IN FORM_BROWSER_FORM
*Form
,
1376 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1387 FORMSET_STORAGE
*Storage
;
1388 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1393 BOOLEAN IsBufferStorage
;
1400 Status
= EFI_SUCCESS
;
1403 // Statement don't have storage, skip them
1405 if (Question
->QuestionId
== 0) {
1410 // If Question value is provided by an Expression, then it is read only
1412 if (Question
->ValueExpression
!= NULL
) {
1417 // Before set question value, evaluate its write expression.
1419 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1420 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1421 if (EFI_ERROR (Status
)) {
1427 // Question value is provided by RTC
1429 Storage
= Question
->Storage
;
1430 QuestionValue
= &Question
->HiiValue
.Value
;
1431 if (Storage
== NULL
) {
1433 // It's a Question without storage, or RTC date/time
1435 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1437 // Date and time define the same Flags bit
1439 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1440 case QF_DATE_STORAGE_TIME
:
1441 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1444 case QF_DATE_STORAGE_WAKEUP
:
1445 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1448 case QF_DATE_STORAGE_NORMAL
:
1451 // For date/time without storage
1456 if (EFI_ERROR (Status
)) {
1460 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1461 EfiTime
.Year
= QuestionValue
->date
.Year
;
1462 EfiTime
.Month
= QuestionValue
->date
.Month
;
1463 EfiTime
.Day
= QuestionValue
->date
.Day
;
1465 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1466 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1467 EfiTime
.Second
= QuestionValue
->time
.Second
;
1470 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1471 Status
= gRT
->SetTime (&EfiTime
);
1473 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1481 // Question value is provided by EFI variable
1483 StorageWidth
= Question
->StorageWidth
;
1484 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1485 if (Question
->BufferValue
!= NULL
) {
1486 Src
= Question
->BufferValue
;
1488 Src
= (UINT8
*) QuestionValue
;
1491 Status
= gRT
->SetVariable (
1492 Question
->VariableName
,
1494 Storage
->Attributes
,
1502 // Question Value is provided by Buffer Storage or NameValue Storage
1504 if (Question
->BufferValue
!= NULL
) {
1505 Src
= Question
->BufferValue
;
1507 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1510 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
1511 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1512 if (IsBufferStorage
) {
1514 // Copy to storage edit buffer
1516 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1520 // Allocate enough string buffer.
1523 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1524 Value
= AllocateZeroPool (BufferLen
);
1525 ASSERT (Value
!= NULL
);
1527 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1529 TemName
= (CHAR16
*) Src
;
1531 for (; *TemName
!= L
'\0'; TemName
++) {
1532 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1535 BufferLen
= StorageWidth
* 2 + 1;
1536 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1537 ASSERT (Value
!= NULL
);
1539 // Convert Buffer to Hex String
1541 TemBuffer
= Src
+ StorageWidth
- 1;
1543 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1544 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1548 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, TRUE
);
1554 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1555 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1557 if (IsBufferStorage
) {
1558 Length
= StrLen (Question
->BlockName
) + 7;
1560 Length
= StrLen (Question
->VariableName
) + 2;
1562 if (!IsBufferStorage
&& IsString
) {
1563 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1565 Length
+= (StorageWidth
* 2);
1567 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1568 ASSERT (ConfigResp
!= NULL
);
1570 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1571 if (IsBufferStorage
) {
1572 StrCat (ConfigResp
, Question
->BlockName
);
1573 StrCat (ConfigResp
, L
"&VALUE=");
1575 StrCat (ConfigResp
, L
"&");
1576 StrCat (ConfigResp
, Question
->VariableName
);
1577 StrCat (ConfigResp
, L
"=");
1580 Value
= ConfigResp
+ StrLen (ConfigResp
);
1582 if (!IsBufferStorage
&& IsString
) {
1584 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1586 TemName
= (CHAR16
*) Src
;
1588 for (; *TemName
!= L
'\0'; TemName
++) {
1589 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1593 // Convert Buffer to Hex String
1595 TemBuffer
= Src
+ StorageWidth
- 1;
1597 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1598 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1603 // Convert to lower char.
1605 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1606 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1607 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1612 // Submit Question Value to Configuration Driver
1614 if (FormSet
->ConfigAccess
!= NULL
) {
1615 Status
= FormSet
->ConfigAccess
->RouteConfig (
1616 FormSet
->ConfigAccess
,
1620 if (EFI_ERROR (Status
)) {
1621 FreePool (ConfigResp
);
1625 FreePool (ConfigResp
);
1628 // Synchronize shadow Buffer
1630 SynchronizeStorage (Storage
);
1638 Perform inconsistent check for a Form.
1640 @param FormSet FormSet data structure.
1641 @param Form Form data structure.
1642 @param Question The Question to be validated.
1643 @param Type Validation type: InConsistent or NoSubmit
1645 @retval EFI_SUCCESS Form validation pass.
1646 @retval other Form validation failed.
1651 IN FORM_BROWSER_FORMSET
*FormSet
,
1652 IN FORM_BROWSER_FORM
*Form
,
1653 IN FORM_BROWSER_STATEMENT
*Question
,
1659 LIST_ENTRY
*ListHead
;
1662 FORM_EXPRESSION
*Expression
;
1664 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1665 ListHead
= &Question
->InconsistentListHead
;
1666 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1667 ListHead
= &Question
->NoSubmitListHead
;
1669 return EFI_UNSUPPORTED
;
1672 Link
= GetFirstNode (ListHead
);
1673 while (!IsNull (ListHead
, Link
)) {
1674 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1677 // Evaluate the expression
1679 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1680 if (EFI_ERROR (Status
)) {
1684 if (Expression
->Result
.Value
.b
) {
1686 // Condition meet, show up error message
1688 if (Expression
->Error
!= 0) {
1689 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1691 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1692 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1696 return EFI_NOT_READY
;
1699 Link
= GetNextNode (ListHead
, Link
);
1707 Perform NoSubmit check for each Form in FormSet.
1709 @param FormSet FormSet data structure.
1710 @param CurrentForm Current input form data structure.
1712 @retval EFI_SUCCESS Form validation pass.
1713 @retval other Form validation failed.
1718 IN FORM_BROWSER_FORMSET
*FormSet
,
1719 IN FORM_BROWSER_FORM
*CurrentForm
1724 FORM_BROWSER_STATEMENT
*Question
;
1725 FORM_BROWSER_FORM
*Form
;
1726 LIST_ENTRY
*LinkForm
;
1728 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1729 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1730 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1731 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1733 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
1737 Link
= GetFirstNode (&Form
->StatementListHead
);
1738 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1739 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1741 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
1742 if (EFI_ERROR (Status
)) {
1746 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1754 Restore Storage's Edit copy to Shadow copy.
1756 @param Storage The Storage to be synchronized.
1761 IN FORMSET_STORAGE
*Storage
1765 NAME_VALUE_NODE
*Node
;
1767 switch (Storage
->Type
) {
1768 case EFI_HII_VARSTORE_BUFFER
:
1769 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
1772 case EFI_HII_VARSTORE_NAME_VALUE
:
1773 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1774 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1775 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1777 if (Node
->EditValue
!= NULL
) {
1778 FreePool (Node
->EditValue
);
1780 Node
->EditValue
= AllocateCopyPool (StrSize (Node
->Value
), Node
->Value
);
1781 ASSERT (Node
->EditValue
!= NULL
);
1782 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1786 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1793 Fill storage's edit copy with settings requested from Configuration Driver.
1795 @param FormSet FormSet data structure.
1796 @param ConfigInfo The config info related to this form.
1798 @retval EFI_SUCCESS The function completed successfully.
1802 FormRestoreStorage (
1803 IN FORM_BROWSER_FORMSET
*FormSet
,
1804 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
1808 EFI_STRING Progress
;
1812 NAME_VALUE_NODE
*Node
;
1814 Status
= EFI_SUCCESS
;
1816 if (FormSet
->ConfigAccess
== NULL
) {
1817 return EFI_NOT_FOUND
;
1820 if (ConfigInfo
->ElementCount
== 0) {
1822 // Skip if there is no RequestElement
1827 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
1828 BufferSize
= ConfigInfo
->Storage
->Size
;
1829 Status
= mHiiConfigRouting
->BlockToConfig(
1831 ConfigInfo
->ConfigRequest
,
1832 ConfigInfo
->Storage
->Buffer
,
1837 if (EFI_ERROR (Status
)) {
1841 Status
= mHiiConfigRouting
->ConfigToBlock (
1844 ConfigInfo
->Storage
->EditBuffer
,
1848 if (Result
!= NULL
) {
1852 if (EFI_ERROR (Status
)) {
1855 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1856 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
1857 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
1858 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1860 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
1861 if (Node
->EditValue
!= NULL
) {
1862 FreePool (Node
->EditValue
);
1864 Node
->EditValue
= AllocateCopyPool (StrSize (Node
->Value
), Node
->Value
);
1865 ASSERT (Node
->EditValue
!= NULL
);
1868 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
1877 Discard data for form level or formset level.
1879 @param FormSet FormSet data structure.
1880 @param Form Form data structure.
1881 @param SingleForm Only discard single form or formset.
1883 @retval EFI_SUCCESS The function completed successfully.
1888 IN FORM_BROWSER_FORMSET
*FormSet
,
1889 IN FORM_BROWSER_FORM
*Form
,
1890 IN BOOLEAN SingleForm
1894 FORMSET_STORAGE
*Storage
;
1895 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
1898 if (Form
->NvUpdateRequired
) {
1900 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
1901 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
1902 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
1903 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
1905 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1910 // Skip if there is no RequestElement
1912 if (ConfigInfo
->ElementCount
== 0) {
1917 // Prepare <ConfigResp>
1919 FormRestoreStorage(FormSet
, ConfigInfo
);
1922 Form
->NvUpdateRequired
= FALSE
;
1925 if (IsNvUpdateRequired(FormSet
)) {
1927 // Discard Buffer storage or Name/Value storage
1929 Link
= GetFirstNode (&FormSet
->StorageListHead
);
1930 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
1931 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
1932 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
1934 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1939 // Skip if there is no RequestElement
1941 if (Storage
->ElementCount
== 0) {
1945 RestoreStorage(Storage
);
1948 UpdateNvInfoInForm(FormSet
, FALSE
);
1956 Submit data for form level or formset level.
1958 @param FormSet FormSet data structure.
1959 @param Form Form data structure.
1960 @param SingleForm whether submit for the single form or all form set.
1962 @retval EFI_SUCCESS The function completed successfully.
1967 IN FORM_BROWSER_FORMSET
*FormSet
,
1968 IN FORM_BROWSER_FORM
*Form
,
1969 IN BOOLEAN SingleForm
1974 EFI_STRING ConfigResp
;
1975 EFI_STRING Progress
;
1976 FORMSET_STORAGE
*Storage
;
1977 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
1980 // Validate the Form by NoSubmit check
1983 Status
= NoSubmitCheck (FormSet
, Form
);
1985 Status
= NoSubmitCheck (FormSet
, NULL
);
1987 if (EFI_ERROR (Status
)) {
1993 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
1994 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
1995 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
1996 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
1998 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2003 // Skip if there is no RequestElement
2005 if (ConfigInfo
->ElementCount
== 0) {
2010 // Prepare <ConfigResp>
2012 Status
= StorageToConfigResp (ConfigInfo
, &ConfigResp
, TRUE
);
2013 if (EFI_ERROR (Status
)) {
2018 // Send <ConfigResp> to Configuration Driver
2020 if (FormSet
->ConfigAccess
!= NULL
) {
2021 Status
= FormSet
->ConfigAccess
->RouteConfig (
2022 FormSet
->ConfigAccess
,
2026 if (EFI_ERROR (Status
)) {
2027 FreePool (ConfigResp
);
2031 FreePool (ConfigResp
);
2034 // Config success, update storage shadow Buffer
2036 SynchronizeStorage (ConfigInfo
->Storage
);
2039 Form
->NvUpdateRequired
= FALSE
;
2042 // Submit Buffer storage or Name/Value storage
2044 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2045 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2046 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2047 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2049 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2054 // Skip if there is no RequestElement
2056 if (Storage
->ElementCount
== 0) {
2061 // Prepare <ConfigResp>
2063 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FALSE
);
2064 if (EFI_ERROR (Status
)) {
2069 // Send <ConfigResp> to Configuration Driver
2071 if (FormSet
->ConfigAccess
!= NULL
) {
2072 Status
= FormSet
->ConfigAccess
->RouteConfig (
2073 FormSet
->ConfigAccess
,
2077 if (EFI_ERROR (Status
)) {
2078 FreePool (ConfigResp
);
2082 FreePool (ConfigResp
);
2085 // Config success, update storage shadow Buffer
2087 SynchronizeStorage (Storage
);
2090 UpdateNvInfoInForm(FormSet
, FALSE
);
2097 Get Question default value from AltCfg string.
2099 @param FormSet The form set.
2100 @param Question The question.
2101 @param DefaultId The default Id.
2103 @retval EFI_SUCCESS Question is reset to default value.
2107 GetDefaultValueFromAltCfg (
2108 IN FORM_BROWSER_FORMSET
*FormSet
,
2109 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2113 BOOLEAN IsBufferStorage
;
2116 FORMSET_STORAGE
*Storage
;
2117 CHAR16
*ConfigRequest
;
2130 Status
= EFI_NOT_FOUND
;
2133 ConfigRequest
= NULL
;
2136 Storage
= Question
->Storage
;
2138 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2143 // Question Value is provided by Buffer Storage or NameValue Storage
2145 if (Question
->BufferValue
!= NULL
) {
2147 // This Question is password or orderedlist
2149 Dst
= Question
->BufferValue
;
2152 // Other type of Questions
2154 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2157 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2158 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2161 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2162 // <ConfigHdr> + "&" + <VariableName>
2164 if (IsBufferStorage
) {
2165 Length
= StrLen (Storage
->ConfigHdr
);
2166 Length
+= StrLen (Question
->BlockName
);
2168 Length
= StrLen (Storage
->ConfigHdr
);
2169 Length
+= StrLen (Question
->VariableName
) + 1;
2171 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2172 ASSERT (ConfigRequest
!= NULL
);
2174 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2175 if (IsBufferStorage
) {
2176 StrCat (ConfigRequest
, Question
->BlockName
);
2178 StrCat (ConfigRequest
, L
"&");
2179 StrCat (ConfigRequest
, Question
->VariableName
);
2182 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2183 FormSet
->ConfigAccess
,
2188 if (EFI_ERROR (Status
)) {
2193 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2194 // Get the default configuration string according to the default ID.
2196 Status
= mHiiConfigRouting
->GetAltConfig (
2202 &DefaultId
, // it can be NULL to get the current setting.
2207 // The required setting can't be found. So, it is not required to be validated and set.
2209 if (EFI_ERROR (Status
)) {
2214 // Skip <ConfigRequest>
2216 Value
= StrStr (ConfigResp
, L
"&VALUE");
2217 if (IsBufferStorage
) {
2223 if (*Value
!= '=') {
2224 Status
= EFI_NOT_FOUND
;
2228 // Skip '=', point to value
2233 // Suppress <AltResp> if any
2236 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2241 LengthStr
= StrLen (Value
);
2242 if (!IsBufferStorage
&& IsString
) {
2243 StringPtr
= (CHAR16
*) Dst
;
2244 ZeroMem (TemStr
, sizeof (TemStr
));
2245 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2246 StrnCpy (TemStr
, Value
+ Index
, 4);
2247 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2250 // Add tailing L'\0' character
2252 StringPtr
[Index
/4] = L
'\0';
2254 ZeroMem (TemStr
, sizeof (TemStr
));
2255 for (Index
= 0; Index
< LengthStr
; Index
++) {
2256 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2257 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2258 if ((Index
& 1) == 0) {
2259 Dst
[Index
/2] = DigitUint8
;
2261 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2267 if (ConfigRequest
!= NULL
){
2268 FreePool (ConfigRequest
);
2271 if (ConfigResp
!= NULL
) {
2272 FreePool (ConfigResp
);
2275 if (Result
!= NULL
) {
2283 Get default Id value used for browser.
2285 @param DefaultId The default id value used by hii.
2287 @retval Browser used default value.
2291 GetDefaultIdForCallBack (
2295 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2296 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2297 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2298 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2299 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2300 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2301 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2302 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2303 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2304 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2305 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2306 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2313 Reset Question to its default value.
2315 @param FormSet The form set.
2316 @param Form The form.
2317 @param Question The question.
2318 @param DefaultId The Class of the default.
2320 @retval EFI_SUCCESS Question is reset to default value.
2324 GetQuestionDefault (
2325 IN FORM_BROWSER_FORMSET
*FormSet
,
2326 IN FORM_BROWSER_FORM
*Form
,
2327 IN FORM_BROWSER_STATEMENT
*Question
,
2333 QUESTION_DEFAULT
*Default
;
2334 QUESTION_OPTION
*Option
;
2335 EFI_HII_VALUE
*HiiValue
;
2337 EFI_STRING StrValue
;
2338 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2339 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2342 Status
= EFI_SUCCESS
;
2346 // Statement don't have storage, skip them
2348 if (Question
->QuestionId
== 0) {
2353 // There are Five ways to specify default value for a Question:
2354 // 1, use call back function (highest priority)
2355 // 2, use ExtractConfig function
2356 // 3, use nested EFI_IFR_DEFAULT
2357 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2358 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2360 HiiValue
= &Question
->HiiValue
;
2363 // Get Question defaut value from call back function.
2365 ConfigAccess
= FormSet
->ConfigAccess
;
2366 Action
= GetDefaultIdForCallBack (DefaultId
);
2367 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2368 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2369 Status
= ConfigAccess
->Callback (
2372 Question
->QuestionId
,
2377 if (!EFI_ERROR (Status
)) {
2383 // Get default value from altcfg string.
2385 if (ConfigAccess
!= NULL
) {
2386 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2387 if (!EFI_ERROR (Status
)) {
2393 // EFI_IFR_DEFAULT has highest priority
2395 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2396 Link
= GetFirstNode (&Question
->DefaultListHead
);
2397 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2398 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2400 if (Default
->DefaultId
== DefaultId
) {
2401 if (Default
->ValueExpression
!= NULL
) {
2403 // Default is provided by an Expression, evaluate it
2405 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2406 if (EFI_ERROR (Status
)) {
2410 CopyMem (HiiValue
, &Default
->ValueExpression
->Result
, sizeof (EFI_HII_VALUE
));
2413 // Default value is embedded in EFI_IFR_DEFAULT
2415 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2418 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2419 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
2420 if (StrValue
== NULL
) {
2421 return EFI_NOT_FOUND
;
2423 Question
->BufferValue
= AllocateCopyPool (StrSize (StrValue
), StrValue
);
2429 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
2434 // EFI_ONE_OF_OPTION
2436 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
2437 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2439 // OneOfOption could only provide Standard and Manufacturing default
2441 Link
= GetFirstNode (&Question
->OptionListHead
);
2442 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2443 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2445 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
2446 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
2448 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
2453 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2459 // EFI_IFR_CHECKBOX - lowest priority
2461 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
2462 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2464 // Checkbox could only provide Standard and Manufacturing default
2466 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
2467 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
2469 HiiValue
->Value
.b
= TRUE
;
2471 HiiValue
->Value
.b
= FALSE
;
2479 // For Questions without default
2481 switch (Question
->Operand
) {
2482 case EFI_IFR_NUMERIC_OP
:
2484 // Take minimum value as numeric default value
2486 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
2487 HiiValue
->Value
.u64
= Question
->Minimum
;
2491 case EFI_IFR_ONE_OF_OP
:
2493 // Take first oneof option as oneof's default value
2495 if (ValueToOption (Question
, HiiValue
) == NULL
) {
2496 Link
= GetFirstNode (&Question
->OptionListHead
);
2497 if (!IsNull (&Question
->OptionListHead
, Link
)) {
2498 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2499 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
2504 case EFI_IFR_ORDERED_LIST_OP
:
2506 // Take option sequence in IFR as ordered list's default value
2509 Link
= GetFirstNode (&Question
->OptionListHead
);
2510 while (!IsNull (&Question
->OptionListHead
, Link
)) {
2511 Option
= QUESTION_OPTION_FROM_LINK (Link
);
2513 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
2516 if (Index
>= Question
->MaxContainers
) {
2520 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
2525 Status
= EFI_NOT_FOUND
;
2534 Reset Questions in a Form to their default value.
2536 @param FormSet FormSet data structure.
2537 @param Form The Form which to be reset.
2538 @param DefaultId The Class of the default.
2540 @retval EFI_SUCCESS The function completed successfully.
2544 ExtractFormDefault (
2545 IN FORM_BROWSER_FORMSET
*FormSet
,
2546 IN FORM_BROWSER_FORM
*Form
,
2552 FORM_BROWSER_STATEMENT
*Question
;
2554 Link
= GetFirstNode (&Form
->StatementListHead
);
2555 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2556 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2557 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2560 // If Question is disabled, don't reset it to default
2562 if (Question
->DisableExpression
!= NULL
) {
2563 Status
= EvaluateExpression (FormSet
, Form
, Question
->DisableExpression
);
2564 if (!EFI_ERROR (Status
) && Question
->DisableExpression
->Result
.Value
.b
) {
2570 // Reset Question to its default value
2572 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
2573 if (EFI_ERROR (Status
)) {
2578 // Synchronize Buffer storage's Edit buffer
2580 if ((Question
->Storage
!= NULL
) &&
2581 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2582 SetQuestionValue (FormSet
, Form
, Question
, TRUE
);
2590 Initialize Question's Edit copy from Storage.
2592 @param Selection Selection contains the information about
2593 the Selection, form and formset to be displayed.
2594 Selection action may be updated in retrieve callback.
2595 @param FormSet FormSet data structure.
2596 @param Form Form data structure.
2598 @retval EFI_SUCCESS The function completed successfully.
2603 IN OUT UI_MENU_SELECTION
*Selection
,
2604 IN FORM_BROWSER_FORMSET
*FormSet
,
2605 IN FORM_BROWSER_FORM
*Form
2610 FORM_BROWSER_STATEMENT
*Question
;
2614 Link
= GetFirstNode (&Form
->StatementListHead
);
2615 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2616 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2619 // Initialize local copy of Value for each Question
2621 Status
= GetQuestionValue (FormSet
, Form
, Question
, TRUE
);
2622 if (EFI_ERROR (Status
)) {
2626 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
2627 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2631 // Check whether EfiVarstore with CallBack can be got.
2633 if ((FormSet
->ConfigAccess
!= NULL
) &&
2634 (Selection
->Action
!= UI_ACTION_REFRESH_FORMSET
) &&
2635 (Question
->QuestionId
!= 0) &&
2636 (Question
->Storage
!= NULL
) &&
2637 (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) &&
2638 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
2641 // Check QuestionValue does exist.
2643 StorageWidth
= Question
->StorageWidth
;
2644 if (Question
->BufferValue
!= NULL
) {
2645 BufferValue
= Question
->BufferValue
;
2647 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
2649 Status
= gRT
->GetVariable (
2650 Question
->VariableName
,
2651 &Question
->Storage
->Guid
,
2657 if (!EFI_ERROR (Status
)) {
2658 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
2662 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2669 Initialize Question's Edit copy from Storage for the whole Formset.
2671 @param Selection Selection contains the information about
2672 the Selection, form and formset to be displayed.
2673 Selection action may be updated in retrieve callback.
2674 @param FormSet FormSet data structure.
2676 @retval EFI_SUCCESS The function completed successfully.
2681 IN OUT UI_MENU_SELECTION
*Selection
,
2682 IN FORM_BROWSER_FORMSET
*FormSet
2687 FORM_BROWSER_FORM
*Form
;
2689 Link
= GetFirstNode (&FormSet
->FormListHead
);
2690 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2691 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2694 // Initialize local copy of Value for each Form
2696 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
2697 if (EFI_ERROR (Status
)) {
2701 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2708 Fill storage's edit copy with settings requested from Configuration Driver.
2710 @param FormSet FormSet data structure.
2711 @param Storage Buffer Storage.
2713 @retval EFI_SUCCESS The function completed successfully.
2718 IN FORM_BROWSER_FORMSET
*FormSet
,
2719 IN FORMSET_STORAGE
*Storage
2723 EFI_STRING Progress
;
2727 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2731 if (FormSet
->ConfigAccess
== NULL
) {
2732 return EFI_NOT_FOUND
;
2735 if (Storage
->ElementCount
== 0) {
2737 // Skip if there is no RequestElement
2743 // Request current settings from Configuration Driver
2745 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2746 FormSet
->ConfigAccess
,
2747 Storage
->ConfigRequest
,
2751 if (EFI_ERROR (Status
)) {
2756 // Convert Result from <ConfigAltResp> to <ConfigResp>
2758 StrPtr
= StrStr (Result
, L
"ALTCFG");
2759 if (StrPtr
!= NULL
) {
2763 Status
= ConfigRespToStorage (Storage
, Result
);
2770 Copy uncommitted data from source Storage to destination Storage.
2772 @param Dst Target Storage for uncommitted data.
2773 @param Src Source Storage for uncommitted data.
2775 @retval EFI_SUCCESS The function completed successfully.
2776 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
2781 IN OUT FORMSET_STORAGE
*Dst
,
2782 IN FORMSET_STORAGE
*Src
2786 NAME_VALUE_NODE
*Node
;
2788 if ((Dst
->Type
!= Src
->Type
) || (Dst
->Size
!= Src
->Size
)) {
2789 return EFI_INVALID_PARAMETER
;
2792 switch (Src
->Type
) {
2793 case EFI_HII_VARSTORE_BUFFER
:
2794 CopyMem (Dst
->EditBuffer
, Src
->EditBuffer
, Src
->Size
);
2795 CopyMem (Dst
->Buffer
, Src
->Buffer
, Src
->Size
);
2798 case EFI_HII_VARSTORE_NAME_VALUE
:
2799 Link
= GetFirstNode (&Src
->NameValueListHead
);
2800 while (!IsNull (&Src
->NameValueListHead
, Link
)) {
2801 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2803 SetValueByName (Dst
, Node
->Name
, Node
->EditValue
, TRUE
);
2804 SetValueByName (Dst
, Node
->Name
, Node
->Value
, FALSE
);
2806 Link
= GetNextNode (&Src
->NameValueListHead
, Link
);
2810 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2820 Get current setting of Questions.
2822 @param FormSet FormSet data structure.
2824 @retval EFI_SUCCESS The function completed successfully.
2828 InitializeCurrentSetting (
2829 IN OUT FORM_BROWSER_FORMSET
*FormSet
2834 FORMSET_STORAGE
*Storage
;
2835 FORMSET_STORAGE
*StorageSrc
;
2836 FORMSET_STORAGE
*OldStorage
;
2837 FORM_BROWSER_FORM
*Form
;
2841 // Extract default from IFR binary
2843 Link
= GetFirstNode (&FormSet
->FormListHead
);
2844 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2845 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2847 Status
= ExtractFormDefault (FormSet
, Form
, EFI_HII_DEFAULT_CLASS_STANDARD
);
2849 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2853 // Request current settings from Configuration Driver
2855 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2856 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2857 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2860 if (gOldFormSet
!= NULL
) {
2862 // Try to find the Storage in backup formset gOldFormSet
2864 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
2865 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
2866 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
2868 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
2869 OldStorage
= StorageSrc
;
2873 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
2877 if (OldStorage
== NULL
) {
2879 // Storage is not found in backup formset, request it from ConfigDriver
2881 Status
= LoadStorage (FormSet
, Storage
);
2883 // Now Edit Buffer is filled with default values(lower priority) and current
2884 // settings(higher priority), sychronize it to shadow Buffer
2886 if (!EFI_ERROR (Status
)) {
2887 SynchronizeStorage (Storage
);
2891 // Storage found in backup formset, use it
2893 Status
= CopyStorage (Storage
, OldStorage
);
2896 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2904 Fetch the Ifr binary data of a FormSet.
2906 @param Handle PackageList Handle
2907 @param FormSetGuid On input, GUID or class GUID of a formset. If not
2908 specified (NULL or zero GUID), take the first
2909 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
2910 found in package list.
2911 On output, GUID of the formset found(if not NULL).
2912 @param BinaryLength The length of the FormSet IFR binary.
2913 @param BinaryData The buffer designed to receive the FormSet.
2915 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
2916 BufferLength was updated.
2917 @retval EFI_INVALID_PARAMETER The handle is unknown.
2918 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
2919 be found with the requested FormId.
2924 IN EFI_HII_HANDLE Handle
,
2925 IN OUT EFI_GUID
*FormSetGuid
,
2926 OUT UINTN
*BinaryLength
,
2927 OUT UINT8
**BinaryData
2931 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
2937 UINT32 PackageListLength
;
2938 EFI_HII_PACKAGE_HEADER PackageHeader
;
2940 UINT8 NumberOfClassGuid
;
2941 BOOLEAN ClassGuidMatch
;
2942 EFI_GUID
*ClassGuid
;
2943 EFI_GUID
*ComparingGuid
;
2947 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
2950 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
2952 if (FormSetGuid
== NULL
|| CompareGuid (FormSetGuid
, &gZeroGuid
)) {
2953 ComparingGuid
= &gEfiHiiPlatformSetupFormsetGuid
;
2955 ComparingGuid
= FormSetGuid
;
2959 // Get HII PackageList
2962 HiiPackageList
= NULL
;
2963 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
2964 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2965 HiiPackageList
= AllocatePool (BufferSize
);
2966 ASSERT (HiiPackageList
!= NULL
);
2968 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
2970 if (EFI_ERROR (Status
)) {
2973 ASSERT (HiiPackageList
!= NULL
);
2976 // Get Form package from this HII package List
2978 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
2980 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
2982 ClassGuidMatch
= FALSE
;
2983 while (Offset
< PackageListLength
) {
2984 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
2985 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
2987 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
2989 // Search FormSet in this Form Package
2991 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
2992 while (Offset2
< PackageHeader
.Length
) {
2993 OpCodeData
= Package
+ Offset2
;
2995 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
2997 // Try to compare against formset GUID
2999 if (CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3003 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3005 // Try to compare against formset class GUID
3007 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3008 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3009 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3010 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3011 ClassGuidMatch
= TRUE
;
3015 if (ClassGuidMatch
) {
3018 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3019 ClassGuidMatch
= TRUE
;
3024 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3027 if (Offset2
< PackageHeader
.Length
) {
3029 // Target formset found
3035 Offset
+= PackageHeader
.Length
;
3038 if (Offset
>= PackageListLength
) {
3040 // Form package not found in this Package List
3042 FreePool (HiiPackageList
);
3043 return EFI_NOT_FOUND
;
3046 if (ClassGuidMatch
&& (FormSetGuid
!= NULL
)) {
3048 // Return the FormSet GUID
3050 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3054 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3055 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3056 // of the Form Package.
3058 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3059 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3061 FreePool (HiiPackageList
);
3063 if (*BinaryData
== NULL
) {
3064 return EFI_OUT_OF_RESOURCES
;
3072 Initialize the internal data structure of a FormSet.
3074 @param Handle PackageList Handle
3075 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3076 specified (NULL or zero GUID), take the first
3077 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3078 found in package list.
3079 On output, GUID of the formset found(if not NULL).
3080 @param FormSet FormSet data structure.
3082 @retval EFI_SUCCESS The function completed successfully.
3083 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3088 IN EFI_HII_HANDLE Handle
,
3089 IN OUT EFI_GUID
*FormSetGuid
,
3090 OUT FORM_BROWSER_FORMSET
*FormSet
3094 EFI_HANDLE DriverHandle
;
3097 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3098 if (EFI_ERROR (Status
)) {
3102 FormSet
->HiiHandle
= Handle
;
3103 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3106 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3108 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3109 if (EFI_ERROR (Status
)) {
3112 FormSet
->DriverHandle
= DriverHandle
;
3113 Status
= gBS
->HandleProtocol (
3115 &gEfiHiiConfigAccessProtocolGuid
,
3116 (VOID
**) &FormSet
->ConfigAccess
3118 if (EFI_ERROR (Status
)) {
3120 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3121 // list, then there will be no configuration action required
3123 FormSet
->ConfigAccess
= NULL
;
3127 // Parse the IFR binary OpCodes
3129 Status
= ParseOpCodes (FormSet
);
3130 if (EFI_ERROR (Status
)) {
3135 // Set VFR type by FormSet SubClass field
3137 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
3138 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
3139 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
3143 // Set VFR type by FormSet class guid
3145 for (Index
= 0; Index
< 3; Index
++) {
3146 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
3147 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
3152 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
3153 gFrontPageHandle
= FormSet
->HiiHandle
;
3157 // Match GUID to find out the function key setting. If match fail, use the default setting.
3159 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
3160 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
3162 // Update the function key setting.
3164 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
3166 // Function key prompt can not be displayed if the function key has been disabled.
3168 if ((gFunctionKeySetting
& FUNCTION_NINE
) != FUNCTION_NINE
) {
3169 gFunctionNineString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
3172 if ((gFunctionKeySetting
& FUNCTION_TEN
) != FUNCTION_TEN
) {
3173 gFunctionTenString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
3183 Save globals used by previous call to SendForm(). SendForm() may be called from
3184 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
3185 So, save globals of previous call to SendForm() and restore them upon exit.
3189 SaveBrowserContext (
3193 BROWSER_CONTEXT
*Context
;
3195 gBrowserContextCount
++;
3196 if (gBrowserContextCount
== 1) {
3198 // This is not reentry of SendForm(), no context to save
3203 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
3204 ASSERT (Context
!= NULL
);
3206 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
3209 // Save FormBrowser context
3211 Context
->BannerData
= gBannerData
;
3212 Context
->ClassOfVfr
= gClassOfVfr
;
3213 Context
->FunctionKeySetting
= gFunctionKeySetting
;
3214 Context
->ResetRequired
= gResetRequired
;
3215 Context
->Direction
= gDirection
;
3216 Context
->FunctionNineString
= gFunctionNineString
;
3217 Context
->FunctionTenString
= gFunctionTenString
;
3218 Context
->EnterString
= gEnterString
;
3219 Context
->EnterCommitString
= gEnterCommitString
;
3220 Context
->EnterEscapeString
= gEnterEscapeString
;
3221 Context
->EscapeString
= gEscapeString
;
3222 Context
->SaveFailed
= gSaveFailed
;
3223 Context
->MoveHighlight
= gMoveHighlight
;
3224 Context
->MakeSelection
= gMakeSelection
;
3225 Context
->DecNumericInput
= gDecNumericInput
;
3226 Context
->HexNumericInput
= gHexNumericInput
;
3227 Context
->ToggleCheckBox
= gToggleCheckBox
;
3228 Context
->PromptForData
= gPromptForData
;
3229 Context
->PromptForPassword
= gPromptForPassword
;
3230 Context
->PromptForNewPassword
= gPromptForNewPassword
;
3231 Context
->ConfirmPassword
= gConfirmPassword
;
3232 Context
->ConfirmError
= gConfirmError
;
3233 Context
->PassowordInvalid
= gPassowordInvalid
;
3234 Context
->PressEnter
= gPressEnter
;
3235 Context
->EmptyString
= gEmptyString
;
3236 Context
->AreYouSure
= gAreYouSure
;
3237 Context
->YesResponse
= gYesResponse
;
3238 Context
->NoResponse
= gNoResponse
;
3239 Context
->MiniString
= gMiniString
;
3240 Context
->PlusString
= gPlusString
;
3241 Context
->MinusString
= gMinusString
;
3242 Context
->AdjustNumber
= gAdjustNumber
;
3243 Context
->SaveChanges
= gSaveChanges
;
3244 Context
->OptionMismatch
= gOptionMismatch
;
3245 Context
->FormSuppress
= gFormSuppress
;
3246 Context
->PromptBlockWidth
= gPromptBlockWidth
;
3247 Context
->OptionBlockWidth
= gOptionBlockWidth
;
3248 Context
->HelpBlockWidth
= gHelpBlockWidth
;
3249 Context
->OldFormSet
= gOldFormSet
;
3250 Context
->MenuRefreshHead
= gMenuRefreshHead
;
3252 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
3253 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
3256 // Insert to FormBrowser context list
3258 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
3263 Restore globals used by previous call to SendForm().
3267 RestoreBrowserContext (
3272 BROWSER_CONTEXT
*Context
;
3274 ASSERT (gBrowserContextCount
!= 0);
3275 gBrowserContextCount
--;
3276 if (gBrowserContextCount
== 0) {
3278 // This is not reentry of SendForm(), no context to restore
3283 ASSERT (!IsListEmpty (&gBrowserContextList
));
3285 Link
= GetFirstNode (&gBrowserContextList
);
3286 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
3289 // Restore FormBrowser context
3291 gBannerData
= Context
->BannerData
;
3292 gClassOfVfr
= Context
->ClassOfVfr
;
3293 gFunctionKeySetting
= Context
->FunctionKeySetting
;
3294 gResetRequired
= Context
->ResetRequired
;
3295 gDirection
= Context
->Direction
;
3296 gFunctionNineString
= Context
->FunctionNineString
;
3297 gFunctionTenString
= Context
->FunctionTenString
;
3298 gEnterString
= Context
->EnterString
;
3299 gEnterCommitString
= Context
->EnterCommitString
;
3300 gEnterEscapeString
= Context
->EnterEscapeString
;
3301 gEscapeString
= Context
->EscapeString
;
3302 gSaveFailed
= Context
->SaveFailed
;
3303 gMoveHighlight
= Context
->MoveHighlight
;
3304 gMakeSelection
= Context
->MakeSelection
;
3305 gDecNumericInput
= Context
->DecNumericInput
;
3306 gHexNumericInput
= Context
->HexNumericInput
;
3307 gToggleCheckBox
= Context
->ToggleCheckBox
;
3308 gPromptForData
= Context
->PromptForData
;
3309 gPromptForPassword
= Context
->PromptForPassword
;
3310 gPromptForNewPassword
= Context
->PromptForNewPassword
;
3311 gConfirmPassword
= Context
->ConfirmPassword
;
3312 gConfirmError
= Context
->ConfirmError
;
3313 gPassowordInvalid
= Context
->PassowordInvalid
;
3314 gPressEnter
= Context
->PressEnter
;
3315 gEmptyString
= Context
->EmptyString
;
3316 gAreYouSure
= Context
->AreYouSure
;
3317 gYesResponse
= Context
->YesResponse
;
3318 gNoResponse
= Context
->NoResponse
;
3319 gMiniString
= Context
->MiniString
;
3320 gPlusString
= Context
->PlusString
;
3321 gMinusString
= Context
->MinusString
;
3322 gAdjustNumber
= Context
->AdjustNumber
;
3323 gSaveChanges
= Context
->SaveChanges
;
3324 gOptionMismatch
= Context
->OptionMismatch
;
3325 gFormSuppress
= Context
->FormSuppress
;
3326 gPromptBlockWidth
= Context
->PromptBlockWidth
;
3327 gOptionBlockWidth
= Context
->OptionBlockWidth
;
3328 gHelpBlockWidth
= Context
->HelpBlockWidth
;
3329 gOldFormSet
= Context
->OldFormSet
;
3330 gMenuRefreshHead
= Context
->MenuRefreshHead
;
3332 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
3333 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
3336 // Remove from FormBrowser context list
3338 RemoveEntryList (&Context
->Link
);
3339 gBS
->FreePool (Context
);