2 This is an example of how a driver might export data to the HII protocol to be
3 later utilized by the Setup Protocol
5 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "DriverSample.h"
19 #define DISPLAY_ONLY_MY_ITEM 0x0002
21 CHAR16 VariableName
[] = L
"MyIfrNVData";
22 CHAR16 MyEfiVar
[] = L
"MyEfiVar";
23 EFI_HANDLE DriverHandle
[2] = {NULL
, NULL
};
24 DRIVER_SAMPLE_PRIVATE_DATA
*mPrivateData
= NULL
;
27 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath0
= {
33 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
34 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
37 DRIVER_SAMPLE_FORMSET_GUID
41 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
43 (UINT8
) (END_DEVICE_PATH_LENGTH
),
44 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
49 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath1
= {
55 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
56 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
59 DRIVER_SAMPLE_INVENTORY_GUID
63 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
65 (UINT8
) (END_DEVICE_PATH_LENGTH
),
66 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
72 Set value of a data element in an Array by its Index.
74 @param Array The data array.
75 @param Type Type of the data in this array.
76 @param Index Zero based index for data in this array.
77 @param Value The value to be set.
89 ASSERT (Array
!= NULL
);
92 case EFI_IFR_TYPE_NUM_SIZE_8
:
93 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
96 case EFI_IFR_TYPE_NUM_SIZE_16
:
97 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
100 case EFI_IFR_TYPE_NUM_SIZE_32
:
101 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
104 case EFI_IFR_TYPE_NUM_SIZE_64
:
105 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
114 Notification function for keystrokes.
116 @param[in] KeyData The key that was pressed.
118 @retval EFI_SUCCESS The operation was successful.
122 NotificationFunction(
123 IN EFI_KEY_DATA
*KeyData
126 gBS
->SignalEvent (mEvent
);
132 Function to start monitoring for CTRL-C using SimpleTextInputEx.
134 @retval EFI_SUCCESS The feature is enabled.
135 @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
139 InternalStartMonitor(
143 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*SimpleEx
;
144 EFI_KEY_DATA KeyData
;
149 EFI_HANDLE NotifyHandle
;
151 Status
= gBS
->LocateHandleBuffer (
153 &gEfiSimpleTextInputExProtocolGuid
,
158 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
159 Status
= gBS
->HandleProtocol (Handles
[HandleIndex
], &gEfiSimpleTextInputExProtocolGuid
, (VOID
**) &SimpleEx
);
160 ASSERT_EFI_ERROR (Status
);
162 KeyData
.KeyState
.KeyToggleState
= 0;
163 KeyData
.Key
.ScanCode
= 0;
164 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_LEFT_CONTROL_PRESSED
;
165 KeyData
.Key
.UnicodeChar
= L
'c';
167 Status
= SimpleEx
->RegisterKeyNotify(
170 NotificationFunction
,
172 if (EFI_ERROR (Status
)) {
176 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_RIGHT_CONTROL_PRESSED
;
177 Status
= SimpleEx
->RegisterKeyNotify(
180 NotificationFunction
,
182 if (EFI_ERROR (Status
)) {
191 Function to stop monitoring for CTRL-C using SimpleTextInputEx.
193 @retval EFI_SUCCESS The feature is enabled.
194 @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
202 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*SimpleEx
;
205 EFI_KEY_DATA KeyData
;
208 EFI_HANDLE NotifyHandle
;
210 Status
= gBS
->LocateHandleBuffer (
212 &gEfiSimpleTextInputExProtocolGuid
,
217 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
218 Status
= gBS
->HandleProtocol (Handles
[HandleIndex
], &gEfiSimpleTextInputExProtocolGuid
, (VOID
**) &SimpleEx
);
219 ASSERT_EFI_ERROR (Status
);
221 KeyData
.KeyState
.KeyToggleState
= 0;
222 KeyData
.Key
.ScanCode
= 0;
223 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_LEFT_CONTROL_PRESSED
;
224 KeyData
.Key
.UnicodeChar
= L
'c';
226 Status
= SimpleEx
->RegisterKeyNotify(
229 NotificationFunction
,
231 if (!EFI_ERROR (Status
)) {
232 Status
= SimpleEx
->UnregisterKeyNotify (SimpleEx
, NotifyHandle
);
235 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_RIGHT_CONTROL_PRESSED
;
236 Status
= SimpleEx
->RegisterKeyNotify(
239 NotificationFunction
,
241 if (!EFI_ERROR (Status
)) {
242 Status
= SimpleEx
->UnregisterKeyNotify (SimpleEx
, NotifyHandle
);
249 Update names of Name/Value storage to current language.
251 @param PrivateData Points to the driver private data.
253 @retval EFI_SUCCESS All names are successfully updated.
254 @retval EFI_NOT_FOUND Failed to get Name from HII database.
259 IN DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
265 // Get Name/Value name string of current language
267 for (Index
= 0; Index
< NAME_VALUE_NAME_NUMBER
; Index
++) {
268 PrivateData
->NameValueName
[Index
] = HiiGetString (
269 PrivateData
->HiiHandle
[0],
270 PrivateData
->NameStringId
[Index
],
273 if (PrivateData
->NameValueName
[Index
] == NULL
) {
274 return EFI_NOT_FOUND
;
283 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
285 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
287 This is a internal function.
289 @param StringPtr String in <BlockConfig> format and points to the
290 first character of <Number>.
291 @param Number The output value. Caller takes the responsibility
293 @param Len Length of the <Number>, in characters.
295 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
297 @retval EFI_SUCCESS Value of <Number> is outputted in Number
303 IN EFI_STRING StringPtr
,
317 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
318 return EFI_INVALID_PARAMETER
;
324 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
327 *Len
= StringPtr
- TmpPtr
;
330 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
332 Status
= EFI_OUT_OF_RESOURCES
;
335 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
336 *(Str
+ *Len
) = L
'\0';
338 Length
= (Length
+ 1) / 2;
339 Buf
= (UINT8
*) AllocateZeroPool (Length
);
341 Status
= EFI_OUT_OF_RESOURCES
;
346 ZeroMem (TemStr
, sizeof (TemStr
));
347 for (Index
= 0; Index
< Length
; Index
++) {
348 TemStr
[0] = Str
[Length
- Index
- 1];
349 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
350 if ((Index
& 1) == 0) {
351 Buf
[Index
/2] = DigitUint8
;
353 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
358 Status
= EFI_SUCCESS
;
369 Create altcfg string.
371 @param Result The request result string.
372 @param ConfigHdr The request head info. <ConfigHdr> format.
373 @param Offset The offset of the parameter int he structure.
374 @param Width The width of the parameter.
377 @retval The string with altcfg info append at the end.
381 IN EFI_STRING Result
,
382 IN EFI_STRING ConfigHdr
,
387 EFI_STRING StringPtr
;
391 NewLen
= StrLen (Result
);
393 // String Len = ConfigResp + AltConfig + AltConfig + 1("\0")
395 NewLen
= (NewLen
+ ((1 + StrLen (ConfigHdr
) + 8 + 4) + (8 + 4 + 7 + 4 + 7 + 4)) * 2 + 1) * sizeof (CHAR16
);
396 StringPtr
= AllocateZeroPool (NewLen
);
397 if (StringPtr
== NULL
) {
402 if (Result
!= NULL
) {
403 StrCpyS (StringPtr
, NewLen
/ sizeof (CHAR16
), Result
);
404 StringPtr
+= StrLen (Result
);
410 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
413 EFI_HII_DEFAULT_CLASS_STANDARD
415 StringPtr
+= StrLen (StringPtr
);
419 (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
420 L
"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
423 DEFAULT_CLASS_STANDARD_VALUE
425 StringPtr
+= StrLen (StringPtr
);
429 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
432 EFI_HII_DEFAULT_CLASS_MANUFACTURING
434 StringPtr
+= StrLen (StringPtr
);
438 (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
439 L
"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
442 DEFAULT_CLASS_MANUFACTURING_VALUE
444 StringPtr
+= StrLen (StringPtr
);
450 Check whether need to add the altcfg string. if need to add, add the altcfg
453 @param RequestResult The request result string.
454 @param ConfigRequestHdr The request head info. <ConfigHdr> format.
459 IN OUT EFI_STRING
*RequestResult
,
460 IN EFI_STRING ConfigRequestHdr
463 EFI_STRING StringPtr
;
474 StringPtr
= *RequestResult
;
475 StringPtr
= StrStr (StringPtr
, L
"OFFSET");
476 BlockSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
477 ValueOffset
= OFFSET_OF (DRIVER_SAMPLE_CONFIGURATION
, GetDefaultValueFromAccess
);
478 ValueWidth
= sizeof (((DRIVER_SAMPLE_CONFIGURATION
*)0)->GetDefaultValueFromAccess
);
480 if (StringPtr
== NULL
) {
484 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
485 StringPtr
+= StrLen (L
"OFFSET=");
489 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
490 if (EFI_ERROR (Status
)) {
497 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
499 FreePool (TmpBuffer
);
502 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
505 StringPtr
+= StrLen (L
"&WIDTH=");
510 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
511 if (EFI_ERROR (Status
)) {
518 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
520 FreePool (TmpBuffer
);
523 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
526 StringPtr
+= StrLen (L
"&VALUE=");
531 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
532 if (EFI_ERROR (Status
)) {
538 // Skip the character "&" before "OFFSET".
543 // Calculate Value and convert it to hex string.
545 if (Offset
+ Width
> BlockSize
) {
549 if (Offset
<= ValueOffset
&& Offset
+ Width
>= ValueOffset
+ ValueWidth
) {
550 *RequestResult
= CreateAltCfgString(*RequestResult
, ConfigRequestHdr
, ValueOffset
, ValueWidth
);
557 This function allows a caller to extract the current configuration for one
558 or more named elements from the target driver.
560 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
561 @param Request A null-terminated Unicode string in
562 <ConfigRequest> format.
563 @param Progress On return, points to a character in the Request
564 string. Points to the string's null terminator if
565 request was successful. Points to the most recent
566 '&' before the first failing name/value pair (or
567 the beginning of the string if the failure is in
568 the first name/value pair) if the request was not
570 @param Results A null-terminated Unicode string in
571 <ConfigAltResp> format which has all values filled
572 in for the names in the Request string. String to
573 be allocated by the called function.
575 @retval EFI_SUCCESS The Results is filled with the requested values.
576 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
577 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
578 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
585 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
586 IN CONST EFI_STRING Request
,
587 OUT EFI_STRING
*Progress
,
588 OUT EFI_STRING
*Results
593 DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
;
594 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
595 EFI_STRING ConfigRequest
;
596 EFI_STRING ConfigRequestHdr
;
602 BOOLEAN AllocatedRequest
;
604 if (Progress
== NULL
|| Results
== NULL
) {
605 return EFI_INVALID_PARAMETER
;
608 // Initialize the local variables.
610 ConfigRequestHdr
= NULL
;
611 ConfigRequest
= NULL
;
614 AllocatedRequest
= FALSE
;
616 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
617 HiiConfigRouting
= PrivateData
->HiiConfigRouting
;
620 // Get Buffer Storage data from EFI variable.
621 // Try to get the current setting from variable.
623 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
624 Status
= gRT
->GetVariable (
626 &gDriverSampleFormSetGuid
,
629 &PrivateData
->Configuration
631 if (EFI_ERROR (Status
)) {
632 return EFI_NOT_FOUND
;
635 if (Request
== NULL
) {
637 // Request is set to NULL, construct full request string.
641 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
642 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
644 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, VariableName
, PrivateData
->DriverHandle
[0]);
645 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
646 ConfigRequest
= AllocateZeroPool (Size
);
647 ASSERT (ConfigRequest
!= NULL
);
648 AllocatedRequest
= TRUE
;
649 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
650 FreePool (ConfigRequestHdr
);
651 ConfigRequestHdr
= NULL
;
654 // Check routing data in <ConfigHdr>.
655 // Note: if only one Storage is used, then this checking could be skipped.
657 if (!HiiIsConfigHdrMatch (Request
, &gDriverSampleFormSetGuid
, NULL
)) {
658 return EFI_NOT_FOUND
;
661 // Check whether request for EFI Varstore. EFI varstore get data
662 // through hii database, not support in this path.
664 if (HiiIsConfigHdrMatch(Request
, &gDriverSampleFormSetGuid
, MyEfiVar
)) {
665 return EFI_UNSUPPORTED
;
668 // Set Request to the unified request string.
670 ConfigRequest
= Request
;
672 // Check whether Request includes Request Element.
674 if (StrStr (Request
, L
"OFFSET") == NULL
) {
676 // Check Request Element does exist in Reques String
678 StrPointer
= StrStr (Request
, L
"PATH");
679 if (StrPointer
== NULL
) {
680 return EFI_INVALID_PARAMETER
;
682 if (StrStr (StrPointer
, L
"&") == NULL
) {
683 Size
= (StrLen (Request
) + 32 + 1) * sizeof (CHAR16
);
684 ConfigRequest
= AllocateZeroPool (Size
);
685 ASSERT (ConfigRequest
!= NULL
);
686 AllocatedRequest
= TRUE
;
687 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", Request
, (UINT64
)BufferSize
);
693 // Check if requesting Name/Value storage
695 if (StrStr (ConfigRequest
, L
"OFFSET") == NULL
) {
697 // Update Name/Value storage Names
699 Status
= LoadNameValueNames (PrivateData
);
700 if (EFI_ERROR (Status
)) {
705 // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"
706 // <Request> ::=<ConfigHdr>&Name0&Name1&Name2
707 // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044
709 BufferSize
= (StrLen (ConfigRequest
) +
710 1 + sizeof (PrivateData
->Configuration
.NameValueVar0
) * 2 +
711 1 + sizeof (PrivateData
->Configuration
.NameValueVar1
) * 2 +
712 1 + sizeof (PrivateData
->Configuration
.NameValueVar2
) * 2 + 1) * sizeof (CHAR16
);
713 *Results
= AllocateZeroPool (BufferSize
);
714 ASSERT (*Results
!= NULL
);
715 StrCpyS (*Results
, BufferSize
/ sizeof (CHAR16
), ConfigRequest
);
719 // Append value of NameValueVar0, type is UINT8
721 if ((Value
= StrStr (*Results
, PrivateData
->NameValueName
[0])) != NULL
) {
722 Value
+= StrLen (PrivateData
->NameValueName
[0]);
723 ValueStrLen
= ((sizeof (PrivateData
->Configuration
.NameValueVar0
) * 2) + 1);
724 CopyMem (Value
+ ValueStrLen
, Value
, StrSize (Value
));
726 BackupChar
= Value
[ValueStrLen
];
728 UnicodeValueToStringS (
730 BufferSize
- ((UINTN
)Value
- (UINTN
)*Results
),
731 PREFIX_ZERO
| RADIX_HEX
,
732 PrivateData
->Configuration
.NameValueVar0
,
733 sizeof (PrivateData
->Configuration
.NameValueVar0
) * 2
735 Value
+= StrnLenS (Value
, (BufferSize
- ((UINTN
)Value
- (UINTN
)*Results
)) / sizeof (CHAR16
));
740 // Append value of NameValueVar1, type is UINT16
742 if ((Value
= StrStr (*Results
, PrivateData
->NameValueName
[1])) != NULL
) {
743 Value
+= StrLen (PrivateData
->NameValueName
[1]);
744 ValueStrLen
= ((sizeof (PrivateData
->Configuration
.NameValueVar1
) * 2) + 1);
745 CopyMem (Value
+ ValueStrLen
, Value
, StrSize (Value
));
747 BackupChar
= Value
[ValueStrLen
];
749 UnicodeValueToStringS (
751 BufferSize
- ((UINTN
)Value
- (UINTN
)*Results
),
752 PREFIX_ZERO
| RADIX_HEX
,
753 PrivateData
->Configuration
.NameValueVar1
,
754 sizeof (PrivateData
->Configuration
.NameValueVar1
) * 2
756 Value
+= StrnLenS (Value
, (BufferSize
- ((UINTN
)Value
- (UINTN
)*Results
)) / sizeof (CHAR16
));
761 // Append value of NameValueVar2, type is CHAR16 *
763 if ((Value
= StrStr (*Results
, PrivateData
->NameValueName
[2])) != NULL
) {
764 Value
+= StrLen (PrivateData
->NameValueName
[2]);
765 ValueStrLen
= StrLen (PrivateData
->Configuration
.NameValueVar2
) * 4 + 1;
766 CopyMem (Value
+ ValueStrLen
, Value
, StrSize (Value
));
770 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
772 StrPointer
= (CHAR16
*) PrivateData
->Configuration
.NameValueVar2
;
773 for (; *StrPointer
!= L
'\0'; StrPointer
++) {
774 UnicodeValueToStringS (
776 BufferSize
- ((UINTN
)Value
- (UINTN
)*Results
),
777 PREFIX_ZERO
| RADIX_HEX
,
781 Value
+= StrnLenS (Value
, (BufferSize
- ((UINTN
)Value
- (UINTN
)*Results
)) / sizeof (CHAR16
));
785 Status
= EFI_SUCCESS
;
788 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
790 Status
= HiiConfigRouting
->BlockToConfig (
793 (UINT8
*) &PrivateData
->Configuration
,
798 if (!EFI_ERROR (Status
)) {
799 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, VariableName
, PrivateData
->DriverHandle
[0]);
800 AppendAltCfgString(Results
, ConfigRequestHdr
);
805 // Free the allocated config request string.
807 if (AllocatedRequest
) {
808 FreePool (ConfigRequest
);
811 if (ConfigRequestHdr
!= NULL
) {
812 FreePool (ConfigRequestHdr
);
815 // Set Progress string to the original request string.
817 if (Request
== NULL
) {
819 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
820 *Progress
= Request
+ StrLen (Request
);
828 This function processes the results of changes in configuration.
830 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
831 @param Configuration A null-terminated Unicode string in <ConfigResp>
833 @param Progress A pointer to a string filled in with the offset of
834 the most recent '&' before the first failing
835 name/value pair (or the beginning of the string if
836 the failure is in the first name/value pair) or
837 the terminating NULL if all was successful.
839 @retval EFI_SUCCESS The Results is processed successfully.
840 @retval EFI_INVALID_PARAMETER Configuration is NULL.
841 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
848 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
849 IN CONST EFI_STRING Configuration
,
850 OUT EFI_STRING
*Progress
855 DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
;
856 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
865 if (Configuration
== NULL
|| Progress
== NULL
) {
866 return EFI_INVALID_PARAMETER
;
869 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
870 HiiConfigRouting
= PrivateData
->HiiConfigRouting
;
871 *Progress
= Configuration
;
874 // Check routing data in <ConfigHdr>.
875 // Note: if only one Storage is used, then this checking could be skipped.
877 if (!HiiIsConfigHdrMatch (Configuration
, &gDriverSampleFormSetGuid
, NULL
)) {
878 return EFI_NOT_FOUND
;
882 // Check whether request for EFI Varstore. EFI varstore get data
883 // through hii database, not support in this path.
885 if (HiiIsConfigHdrMatch(Configuration
, &gDriverSampleFormSetGuid
, MyEfiVar
)) {
886 return EFI_UNSUPPORTED
;
890 // Get Buffer Storage data from EFI variable
892 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
893 Status
= gRT
->GetVariable (
895 &gDriverSampleFormSetGuid
,
898 &PrivateData
->Configuration
900 if (EFI_ERROR (Status
)) {
905 // Check if configuring Name/Value storage
907 if (StrStr (Configuration
, L
"OFFSET") == NULL
) {
909 // Update Name/Value storage Names
911 Status
= LoadNameValueNames (PrivateData
);
912 if (EFI_ERROR (Status
)) {
917 // Convert value for NameValueVar0
919 if ((Value
= StrStr (Configuration
, PrivateData
->NameValueName
[0])) != NULL
) {
923 Value
+= StrLen (PrivateData
->NameValueName
[0]);
928 StrPtr
= StrStr (Value
, L
"&");
929 if (StrPtr
== NULL
) {
930 StrPtr
= Value
+ StrLen (Value
);
933 // Convert Value to Buffer data
935 DataBuffer
= (UINT8
*) &PrivateData
->Configuration
.NameValueVar0
;
936 ZeroMem (TemStr
, sizeof (TemStr
));
937 for (Index
= 0, StrPtr
--; StrPtr
>= Value
; StrPtr
--, Index
++) {
939 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
940 if ((Index
& 1) == 0) {
941 DataBuffer
[Index
/2] = DigitUint8
;
943 DataBuffer
[Index
/2] = (UINT8
) ((UINT8
) (DigitUint8
<< 4) + DataBuffer
[Index
/2]);
949 // Convert value for NameValueVar1
951 if ((Value
= StrStr (Configuration
, PrivateData
->NameValueName
[1])) != NULL
) {
955 Value
+= StrLen (PrivateData
->NameValueName
[1]);
960 StrPtr
= StrStr (Value
, L
"&");
961 if (StrPtr
== NULL
) {
962 StrPtr
= Value
+ StrLen (Value
);
965 // Convert Value to Buffer data
967 DataBuffer
= (UINT8
*) &PrivateData
->Configuration
.NameValueVar1
;
968 ZeroMem (TemStr
, sizeof (TemStr
));
969 for (Index
= 0, StrPtr
--; StrPtr
>= Value
; StrPtr
--, Index
++) {
971 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
972 if ((Index
& 1) == 0) {
973 DataBuffer
[Index
/2] = DigitUint8
;
975 DataBuffer
[Index
/2] = (UINT8
) ((UINT8
) (DigitUint8
<< 4) + DataBuffer
[Index
/2]);
981 // Convert value for NameValueVar2
983 if ((Value
= StrStr (Configuration
, PrivateData
->NameValueName
[2])) != NULL
) {
987 Value
+= StrLen (PrivateData
->NameValueName
[2]);
992 StrPtr
= StrStr (Value
, L
"&");
993 if (StrPtr
== NULL
) {
994 StrPtr
= Value
+ StrLen (Value
);
997 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
999 StrBuffer
= (CHAR16
*) PrivateData
->Configuration
.NameValueVar2
;
1000 ZeroMem (TemStr
, sizeof (TemStr
));
1001 while (Value
< StrPtr
) {
1002 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
, 4);
1003 *(StrBuffer
++) = (CHAR16
) StrHexToUint64 (TemStr
);
1010 // Store Buffer Storage back to EFI variable
1012 Status
= gRT
->SetVariable(
1014 &gDriverSampleFormSetGuid
,
1015 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1016 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1017 &PrivateData
->Configuration
1024 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
1026 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
1027 Status
= HiiConfigRouting
->ConfigToBlock (
1030 (UINT8
*) &PrivateData
->Configuration
,
1034 if (EFI_ERROR (Status
)) {
1039 // Store Buffer Storage back to EFI variable
1041 Status
= gRT
->SetVariable(
1043 &gDriverSampleFormSetGuid
,
1044 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1045 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1046 &PrivateData
->Configuration
1054 This function processes the results of changes in configuration.
1056 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1057 @param Action Specifies the type of action taken by the browser.
1058 @param QuestionId A unique value which is sent to the original
1059 exporting driver so that it can identify the type
1061 @param Type The type of value for the question.
1062 @param Value A pointer to the data being sent to the original
1064 @param ActionRequest On return, points to the action requested by the
1067 @retval EFI_SUCCESS The callback successfully handled the action.
1068 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1069 variable and its data.
1070 @retval EFI_DEVICE_ERROR The variable could not be saved.
1071 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1078 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1079 IN EFI_BROWSER_ACTION Action
,
1080 IN EFI_QUESTION_ID QuestionId
,
1082 IN EFI_IFR_TYPE_VALUE
*Value
,
1083 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1086 DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
;
1088 VOID
*StartOpCodeHandle
;
1089 VOID
*OptionsOpCodeHandle
;
1090 EFI_IFR_GUID_LABEL
*StartLabel
;
1091 VOID
*EndOpCodeHandle
;
1092 EFI_IFR_GUID_LABEL
*EndLabel
;
1094 DRIVER_SAMPLE_CONFIGURATION
*Configuration
;
1095 MY_EFI_VARSTORE_DATA
*EfiData
;
1097 EFI_STRING Progress
;
1104 if (((Value
== NULL
) && (Action
!= EFI_BROWSER_ACTION_FORM_OPEN
) && (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
))||
1105 (ActionRequest
== NULL
)) {
1106 return EFI_INVALID_PARAMETER
;
1112 Status
= EFI_SUCCESS
;
1114 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
1117 case EFI_BROWSER_ACTION_FORM_OPEN
:
1119 if (QuestionId
== 0x1234) {
1121 // Sample CallBack for UEFI FORM_OPEN action:
1122 // Add Save action into Form 3 when Form 1 is opened.
1123 // This will be done only in FORM_OPEN CallBack of question with ID 0x1234 from Form 1.
1125 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
1128 // Initialize the container for dynamic opcodes
1130 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1131 ASSERT (StartOpCodeHandle
!= NULL
);
1134 // Create Hii Extend Label OpCode as the start opcode
1136 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1137 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1138 StartLabel
->Number
= LABEL_UPDATE2
;
1140 HiiCreateActionOpCode (
1141 StartOpCodeHandle
, // Container for dynamic created opcodes
1142 0x1238, // Question ID
1143 STRING_TOKEN(STR_SAVE_TEXT
), // Prompt text
1144 STRING_TOKEN(STR_SAVE_TEXT
), // Help text
1145 EFI_IFR_FLAG_CALLBACK
, // Question flag
1146 0 // Action String ID
1150 PrivateData
->HiiHandle
[0], // HII handle
1151 &gDriverSampleFormSetGuid
, // Formset GUID
1153 StartOpCodeHandle
, // Label for where to insert opcodes
1157 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1160 if (QuestionId
== 0x1247) {
1161 Status
= InternalStartMonitor ();
1162 ASSERT_EFI_ERROR (Status
);
1167 case EFI_BROWSER_ACTION_FORM_CLOSE
:
1169 if (QuestionId
== 0x5678) {
1171 // Sample CallBack for UEFI FORM_CLOSE action:
1172 // Show up a pop-up to specify Form 3 will be closed when exit Form 3.
1176 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1179 L
"You are going to leave third Form!",
1180 L
"Press ESC or ENTER to continue ...",
1184 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1187 if (QuestionId
== 0x1247) {
1188 Status
= InternalStopMonitor ();
1189 ASSERT_EFI_ERROR (Status
);
1194 case EFI_BROWSER_ACTION_RETRIEVE
:
1196 switch (QuestionId
) {
1198 if (Type
!= EFI_IFR_TYPE_REF
) {
1199 return EFI_INVALID_PARAMETER
;
1201 Value
->ref
.FormId
= 0x3;
1207 // We will reach here once the Question is refreshed
1211 // Initialize the container for dynamic opcodes
1213 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1214 ASSERT (StartOpCodeHandle
!= NULL
);
1217 // Create Hii Extend Label OpCode as the start opcode
1219 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1220 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1221 if (QuestionId
== 0x5678) {
1222 StartLabel
->Number
= LABEL_UPDATE2
;
1224 PrivateData
->Configuration
.DynamicRefresh
++;
1225 } else if (QuestionId
== 0x1247 ) {
1226 StartLabel
->Number
= LABEL_UPDATE3
;
1228 PrivateData
->Configuration
.RefreshGuidCount
++;
1231 HiiCreateActionOpCode (
1232 StartOpCodeHandle
, // Container for dynamic created opcodes
1233 0x1237, // Question ID
1234 STRING_TOKEN(STR_EXIT_TEXT
), // Prompt text
1235 STRING_TOKEN(STR_EXIT_TEXT
), // Help text
1236 EFI_IFR_FLAG_CALLBACK
, // Question flag
1237 0 // Action String ID
1241 PrivateData
->HiiHandle
[0], // HII handle
1242 &gDriverSampleFormSetGuid
, // Formset GUID
1244 StartOpCodeHandle
, // Label for where to insert opcodes
1248 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1251 // Refresh the Question value
1253 Status
= gRT
->SetVariable(
1255 &gDriverSampleFormSetGuid
,
1256 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1257 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1258 &PrivateData
->Configuration
1261 if (QuestionId
== 0x5678) {
1263 // Update uncommitted data of Browser
1265 EfiData
= AllocateZeroPool (sizeof (MY_EFI_VARSTORE_DATA
));
1266 ASSERT (EfiData
!= NULL
);
1267 if (HiiGetBrowserData (&gDriverSampleFormSetGuid
, MyEfiVar
, sizeof (MY_EFI_VARSTORE_DATA
), (UINT8
*) EfiData
)) {
1268 EfiData
->Field8
= 111;
1270 &gDriverSampleFormSetGuid
,
1272 sizeof (MY_EFI_VARSTORE_DATA
),
1284 case EFI_BROWSER_ACTION_DEFAULT_STANDARD
:
1286 switch (QuestionId
) {
1288 Value
->u8
= DEFAULT_CLASS_STANDARD_VALUE
;
1292 for (Index
= 0; Index
< 3; Index
++) {
1293 SetArrayData (Value
, EFI_IFR_TYPE_NUM_SIZE_8
, Index
, BufferValue
--);
1298 Status
= EFI_UNSUPPORTED
;
1304 case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
:
1306 switch (QuestionId
) {
1308 Value
->u8
= DEFAULT_CLASS_MANUFACTURING_VALUE
;
1312 Status
= EFI_UNSUPPORTED
;
1318 case EFI_BROWSER_ACTION_CHANGING
:
1320 switch (QuestionId
) {
1323 if (Type
!= EFI_IFR_TYPE_REF
) {
1324 return EFI_INVALID_PARAMETER
;
1327 Value
->ref
.FormId
= 0x1234;
1332 // Initialize the container for dynamic opcodes
1334 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1335 ASSERT (StartOpCodeHandle
!= NULL
);
1337 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1338 ASSERT (EndOpCodeHandle
!= NULL
);
1341 // Create Hii Extend Label OpCode as the start opcode
1343 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1344 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1345 StartLabel
->Number
= LABEL_UPDATE1
;
1348 // Create Hii Extend Label OpCode as the end opcode
1350 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1351 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1352 EndLabel
->Number
= LABEL_END
;
1354 HiiCreateActionOpCode (
1355 StartOpCodeHandle
, // Container for dynamic created opcodes
1356 0x1237, // Question ID
1357 STRING_TOKEN(STR_EXIT_TEXT
), // Prompt text
1358 STRING_TOKEN(STR_EXIT_TEXT
), // Help text
1359 EFI_IFR_FLAG_CALLBACK
, // Question flag
1360 0 // Action String ID
1364 // Create Option OpCode
1366 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1367 ASSERT (OptionsOpCodeHandle
!= NULL
);
1369 HiiCreateOneOfOptionOpCode (
1370 OptionsOpCodeHandle
,
1371 STRING_TOKEN (STR_BOOT_OPTION1
),
1373 EFI_IFR_NUMERIC_SIZE_1
,
1377 HiiCreateOneOfOptionOpCode (
1378 OptionsOpCodeHandle
,
1379 STRING_TOKEN (STR_BOOT_OPTION2
),
1381 EFI_IFR_NUMERIC_SIZE_1
,
1386 // Prepare initial value for the dynamic created oneof Question
1388 PrivateData
->Configuration
.DynamicOneof
= 2;
1389 Status
= gRT
->SetVariable(
1391 &gDriverSampleFormSetGuid
,
1392 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1393 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1394 &PrivateData
->Configuration
1398 // Set initial vlaue of dynamic created oneof Question in Form Browser
1400 Configuration
= AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION
));
1401 ASSERT (Configuration
!= NULL
);
1402 if (HiiGetBrowserData (&gDriverSampleFormSetGuid
, VariableName
, sizeof (DRIVER_SAMPLE_CONFIGURATION
), (UINT8
*) Configuration
)) {
1403 Configuration
->DynamicOneof
= 2;
1406 // Update uncommitted data of Browser
1409 &gDriverSampleFormSetGuid
,
1411 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1412 (UINT8
*) Configuration
,
1416 FreePool (Configuration
);
1418 HiiCreateOneOfOpCode (
1419 StartOpCodeHandle
, // Container for dynamic created opcodes
1420 0x8001, // Question ID (or call it "key")
1421 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1422 (UINT16
) DYNAMIC_ONE_OF_VAR_OFFSET
, // Offset in Buffer Storage
1423 STRING_TOKEN (STR_ONE_OF_PROMPT
), // Question prompt text
1424 STRING_TOKEN (STR_ONE_OF_HELP
), // Question help text
1425 EFI_IFR_FLAG_CALLBACK
, // Question flag
1426 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question Value
1427 OptionsOpCodeHandle
, // Option Opcode list
1428 NULL
// Default Opcode is NULl
1431 HiiCreateOrderedListOpCode (
1432 StartOpCodeHandle
, // Container for dynamic created opcodes
1433 0x8002, // Question ID
1434 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1435 (UINT16
) DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1436 STRING_TOKEN (STR_BOOT_OPTIONS
), // Question prompt text
1437 STRING_TOKEN (STR_BOOT_OPTIONS
), // Question help text
1438 EFI_IFR_FLAG_RESET_REQUIRED
, // Question flag
1439 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1440 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1441 5, // Maximum container
1442 OptionsOpCodeHandle
, // Option Opcode list
1443 NULL
// Default Opcode is NULl
1446 HiiCreateTextOpCode (
1448 STRING_TOKEN(STR_TEXT_SAMPLE_HELP
),
1449 STRING_TOKEN(STR_TEXT_SAMPLE_HELP
),
1450 STRING_TOKEN(STR_TEXT_SAMPLE_STRING
)
1453 HiiCreateDateOpCode (
1458 STRING_TOKEN(STR_DATE_SAMPLE_HELP
),
1459 STRING_TOKEN(STR_DATE_SAMPLE_HELP
),
1461 QF_DATE_STORAGE_TIME
,
1465 HiiCreateTimeOpCode (
1470 STRING_TOKEN(STR_TIME_SAMPLE_HELP
),
1471 STRING_TOKEN(STR_TIME_SAMPLE_HELP
),
1473 QF_TIME_STORAGE_TIME
,
1477 HiiCreateGotoOpCode (
1478 StartOpCodeHandle
, // Container for dynamic created opcodes
1479 1, // Target Form ID
1480 STRING_TOKEN (STR_GOTO_FORM1
), // Prompt text
1481 STRING_TOKEN (STR_GOTO_HELP
), // Help text
1483 0x8003 // Question ID
1487 PrivateData
->HiiHandle
[0], // HII handle
1488 &gDriverSampleFormSetGuid
, // Formset GUID
1490 StartOpCodeHandle
, // Label for where to insert opcodes
1491 EndOpCodeHandle
// Replace data
1494 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1495 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1496 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1505 case EFI_BROWSER_ACTION_CHANGED
:
1506 switch (QuestionId
) {
1509 // User press "Exit now", request Browser to exit
1511 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
1516 // User press "Save now", request Browser to save the uncommitted data.
1518 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
1524 // User press "Submit current form and Exit now", request Browser to submit current form and exit
1526 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
1531 // User press "Discard current form now", request Browser to discard the uncommitted data.
1533 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
;
1538 // User press "Submit current form now", request Browser to save the uncommitted data.
1540 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
1546 // User press "Discard current form and Exit now", request Browser to discard the uncommitted data and exit.
1548 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
1553 // 1. Check to see whether system support keyword.
1555 Status
= PrivateData
->HiiKeywordHandler
->GetData (PrivateData
->HiiKeywordHandler
,
1556 L
"NAMESPACE=x-UEFI-ns",
1557 L
"KEYWORD=iSCSIBootEnable",
1562 if (EFI_ERROR (Status
)) {
1565 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1568 L
"This system not support this keyword!",
1569 L
"Press ENTER to continue ...",
1573 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1575 Status
= EFI_SUCCESS
;
1580 // 2. If system support this keyword, just try to change value.
1584 // Change value from '0' to '1' or from '1' to '0'
1586 TmpStr
= StrStr (Results
, L
"&VALUE=");
1587 ASSERT (TmpStr
!= NULL
);
1588 TmpStr
+= StrLen (L
"&VALUE=");
1590 if (*TmpStr
== L
'0') {
1597 // 3. Call the keyword handler protocol to change the value.
1599 Status
= PrivateData
->HiiKeywordHandler
->SetData (PrivateData
->HiiKeywordHandler
,
1604 if (EFI_ERROR (Status
)) {
1607 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1610 L
"Set keyword to the system failed!",
1611 L
"Press ENTER to continue ...",
1615 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1617 Status
= EFI_SUCCESS
;
1627 case EFI_BROWSER_ACTION_SUBMITTED
:
1629 if (QuestionId
== 0x1250) {
1631 // Sample CallBack for EFI_BROWSER_ACTION_SUBMITTED action:
1632 // Show up a pop-up to show SUBMITTED callback has been triggered.
1636 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1639 L
"EfiVarstore value has been submitted!",
1640 L
"Press ESC or ENTER to continue ...",
1644 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1650 Status
= EFI_UNSUPPORTED
;
1658 Main entry for this driver.
1660 @param ImageHandle Image handle this driver.
1661 @param SystemTable Pointer to SystemTable.
1663 @retval EFI_SUCESS This function always complete successfully.
1669 IN EFI_HANDLE ImageHandle
,
1670 IN EFI_SYSTEM_TABLE
*SystemTable
1674 EFI_HII_HANDLE HiiHandle
[2];
1675 EFI_SCREEN_DESCRIPTOR Screen
;
1676 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
1677 EFI_HII_STRING_PROTOCOL
*HiiString
;
1678 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
1679 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
1680 EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*HiiKeywordHandler
;
1683 DRIVER_SAMPLE_CONFIGURATION
*Configuration
;
1685 EFI_STRING ConfigRequestHdr
;
1686 EFI_STRING NameRequestHdr
;
1687 MY_EFI_VARSTORE_DATA
*VarStoreConfig
;
1688 EFI_INPUT_KEY HotKey
;
1689 EDKII_FORM_BROWSER_EXTENSION_PROTOCOL
*FormBrowserEx
;
1692 // Initialize the local variables.
1694 ConfigRequestHdr
= NULL
;
1698 // Initialize screen dimensions for SendForm().
1699 // Remove 3 characters from top and bottom
1701 ZeroMem (&Screen
, sizeof (EFI_SCREEN_DESCRIPTOR
));
1702 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &Screen
.RightColumn
, &Screen
.BottomRow
);
1705 Screen
.BottomRow
= Screen
.BottomRow
- 3;
1708 // Initialize driver private data
1710 mPrivateData
= AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA
));
1711 if (mPrivateData
== NULL
) {
1712 return EFI_OUT_OF_RESOURCES
;
1715 mPrivateData
->Signature
= DRIVER_SAMPLE_PRIVATE_SIGNATURE
;
1717 mPrivateData
->ConfigAccess
.ExtractConfig
= ExtractConfig
;
1718 mPrivateData
->ConfigAccess
.RouteConfig
= RouteConfig
;
1719 mPrivateData
->ConfigAccess
.Callback
= DriverCallback
;
1722 // Locate Hii Database protocol
1724 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**) &HiiDatabase
);
1725 if (EFI_ERROR (Status
)) {
1728 mPrivateData
->HiiDatabase
= HiiDatabase
;
1731 // Locate HiiString protocol
1733 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, (VOID
**) &HiiString
);
1734 if (EFI_ERROR (Status
)) {
1737 mPrivateData
->HiiString
= HiiString
;
1740 // Locate Formbrowser2 protocol
1742 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &FormBrowser2
);
1743 if (EFI_ERROR (Status
)) {
1746 mPrivateData
->FormBrowser2
= FormBrowser2
;
1749 // Locate ConfigRouting protocol
1751 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
1752 if (EFI_ERROR (Status
)) {
1755 mPrivateData
->HiiConfigRouting
= HiiConfigRouting
;
1758 // Locate keyword handler protocol
1760 Status
= gBS
->LocateProtocol (&gEfiConfigKeywordHandlerProtocolGuid
, NULL
, (VOID
**) &HiiKeywordHandler
);
1761 if (EFI_ERROR (Status
)) {
1764 mPrivateData
->HiiKeywordHandler
= HiiKeywordHandler
;
1766 Status
= gBS
->InstallMultipleProtocolInterfaces (
1768 &gEfiDevicePathProtocolGuid
,
1769 &mHiiVendorDevicePath0
,
1770 &gEfiHiiConfigAccessProtocolGuid
,
1771 &mPrivateData
->ConfigAccess
,
1774 ASSERT_EFI_ERROR (Status
);
1776 mPrivateData
->DriverHandle
[0] = DriverHandle
[0];
1779 // Publish our HII data
1781 HiiHandle
[0] = HiiAddPackages (
1782 &gDriverSampleFormSetGuid
,
1784 DriverSampleStrings
,
1788 if (HiiHandle
[0] == NULL
) {
1789 return EFI_OUT_OF_RESOURCES
;
1792 mPrivateData
->HiiHandle
[0] = HiiHandle
[0];
1795 // Publish another Fromset
1797 Status
= gBS
->InstallMultipleProtocolInterfaces (
1799 &gEfiDevicePathProtocolGuid
,
1800 &mHiiVendorDevicePath1
,
1801 &gEfiHiiConfigAccessProtocolGuid
,
1802 &mPrivateData
->ConfigAccess
,
1805 ASSERT_EFI_ERROR (Status
);
1807 mPrivateData
->DriverHandle
[1] = DriverHandle
[1];
1809 HiiHandle
[1] = HiiAddPackages (
1810 &gDriverSampleInventoryGuid
,
1812 DriverSampleStrings
,
1816 if (HiiHandle
[1] == NULL
) {
1817 DriverSampleUnload (ImageHandle
);
1818 return EFI_OUT_OF_RESOURCES
;
1821 mPrivateData
->HiiHandle
[1] = HiiHandle
[1];
1824 // Update the device path string.
1826 NewString
= ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL
*)&mHiiVendorDevicePath0
, FALSE
, FALSE
);
1827 if (HiiSetString (HiiHandle
[0], STRING_TOKEN (STR_DEVICE_PATH
), NewString
, NULL
) == 0) {
1828 DriverSampleUnload (ImageHandle
);
1829 return EFI_OUT_OF_RESOURCES
;
1831 if (NewString
!= NULL
) {
1832 FreePool (NewString
);
1836 // Very simple example of how one would update a string that is already
1837 // in the HII database
1839 NewString
= L
"700 Mhz";
1841 if (HiiSetString (HiiHandle
[0], STRING_TOKEN (STR_CPU_STRING2
), NewString
, NULL
) == 0) {
1842 DriverSampleUnload (ImageHandle
);
1843 return EFI_OUT_OF_RESOURCES
;
1846 HiiSetString (HiiHandle
[0], 0, NewString
, NULL
);
1849 // Initialize Name/Value name String ID
1851 mPrivateData
->NameStringId
[0] = STR_NAME_VALUE_VAR_NAME0
;
1852 mPrivateData
->NameStringId
[1] = STR_NAME_VALUE_VAR_NAME1
;
1853 mPrivateData
->NameStringId
[2] = STR_NAME_VALUE_VAR_NAME2
;
1856 // Initialize configuration data
1858 Configuration
= &mPrivateData
->Configuration
;
1859 ZeroMem (Configuration
, sizeof (DRIVER_SAMPLE_CONFIGURATION
));
1862 // Try to read NV config EFI variable first
1864 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, VariableName
, DriverHandle
[0]);
1865 ASSERT (ConfigRequestHdr
!= NULL
);
1867 NameRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, NULL
, DriverHandle
[0]);
1868 ASSERT (NameRequestHdr
!= NULL
);
1870 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
1871 Status
= gRT
->GetVariable (VariableName
, &gDriverSampleFormSetGuid
, NULL
, &BufferSize
, Configuration
);
1872 if (EFI_ERROR (Status
)) {
1874 // Store zero data Buffer Storage to EFI variable
1876 Status
= gRT
->SetVariable(
1878 &gDriverSampleFormSetGuid
,
1879 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1880 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1883 if (EFI_ERROR (Status
)) {
1884 DriverSampleUnload (ImageHandle
);
1888 // EFI variable for NV config doesn't exit, we should build this variable
1889 // based on default values stored in IFR
1891 ActionFlag
= HiiSetToDefaults (NameRequestHdr
, EFI_HII_DEFAULT_CLASS_STANDARD
);
1893 DriverSampleUnload (ImageHandle
);
1894 return EFI_INVALID_PARAMETER
;
1897 ActionFlag
= HiiSetToDefaults (ConfigRequestHdr
, EFI_HII_DEFAULT_CLASS_STANDARD
);
1899 DriverSampleUnload (ImageHandle
);
1900 return EFI_INVALID_PARAMETER
;
1904 // EFI variable does exist and Validate Current Setting
1906 ActionFlag
= HiiValidateSettings (NameRequestHdr
);
1908 DriverSampleUnload (ImageHandle
);
1909 return EFI_INVALID_PARAMETER
;
1912 ActionFlag
= HiiValidateSettings (ConfigRequestHdr
);
1914 DriverSampleUnload (ImageHandle
);
1915 return EFI_INVALID_PARAMETER
;
1918 FreePool (ConfigRequestHdr
);
1921 // Initialize efi varstore configuration data
1923 VarStoreConfig
= &mPrivateData
->VarStoreConfig
;
1924 ZeroMem (VarStoreConfig
, sizeof (MY_EFI_VARSTORE_DATA
));
1926 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, MyEfiVar
, DriverHandle
[0]);
1927 ASSERT (ConfigRequestHdr
!= NULL
);
1929 BufferSize
= sizeof (MY_EFI_VARSTORE_DATA
);
1930 Status
= gRT
->GetVariable (MyEfiVar
, &gDriverSampleFormSetGuid
, NULL
, &BufferSize
, VarStoreConfig
);
1931 if (EFI_ERROR (Status
)) {
1933 // Store zero data to EFI variable Storage.
1935 Status
= gRT
->SetVariable(
1937 &gDriverSampleFormSetGuid
,
1938 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1939 sizeof (MY_EFI_VARSTORE_DATA
),
1942 if (EFI_ERROR (Status
)) {
1943 DriverSampleUnload (ImageHandle
);
1947 // EFI variable for NV config doesn't exit, we should build this variable
1948 // based on default values stored in IFR
1950 ActionFlag
= HiiSetToDefaults (ConfigRequestHdr
, EFI_HII_DEFAULT_CLASS_STANDARD
);
1952 DriverSampleUnload (ImageHandle
);
1953 return EFI_INVALID_PARAMETER
;
1957 // EFI variable does exist and Validate Current Setting
1959 ActionFlag
= HiiValidateSettings (ConfigRequestHdr
);
1961 DriverSampleUnload (ImageHandle
);
1962 return EFI_INVALID_PARAMETER
;
1965 FreePool (ConfigRequestHdr
);
1967 Status
= gBS
->CreateEventEx (
1970 EfiEventEmptyFunction
,
1972 &gEfiIfrRefreshIdOpGuid
,
1975 ASSERT_EFI_ERROR (Status
);
1978 // Example of how to use BrowserEx protocol to register HotKey.
1980 Status
= gBS
->LocateProtocol (&gEdkiiFormBrowserExProtocolGuid
, NULL
, (VOID
**) &FormBrowserEx
);
1981 if (!EFI_ERROR (Status
)) {
1983 // First unregister the default hot key F9 and F10.
1985 HotKey
.UnicodeChar
= CHAR_NULL
;
1986 HotKey
.ScanCode
= SCAN_F9
;
1987 FormBrowserEx
->RegisterHotKey (&HotKey
, 0, 0, NULL
);
1988 HotKey
.ScanCode
= SCAN_F10
;
1989 FormBrowserEx
->RegisterHotKey (&HotKey
, 0, 0, NULL
);
1992 // Register the default HotKey F9 and F10 again.
1994 HotKey
.ScanCode
= SCAN_F10
;
1995 NewString
= HiiGetString (mPrivateData
->HiiHandle
[0], STRING_TOKEN (FUNCTION_TEN_STRING
), NULL
);
1996 ASSERT (NewString
!= NULL
);
1997 FormBrowserEx
->RegisterHotKey (&HotKey
, BROWSER_ACTION_SUBMIT
, 0, NewString
);
1998 HotKey
.ScanCode
= SCAN_F9
;
1999 NewString
= HiiGetString (mPrivateData
->HiiHandle
[0], STRING_TOKEN (FUNCTION_NINE_STRING
), NULL
);
2000 ASSERT (NewString
!= NULL
);
2001 FormBrowserEx
->RegisterHotKey (&HotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, NewString
);
2005 // In default, this driver is built into Flash device image,
2006 // the following code doesn't run.
2010 // Example of how to display only the item we sent to HII
2011 // When this driver is not built into Flash device image,
2012 // it need to call SendForm to show front page by itself.
2014 if (DISPLAY_ONLY_MY_ITEM
<= 1) {
2016 // Have the browser pull out our copy of the data, and only display our data
2018 Status
= FormBrowser2
->SendForm (
2020 &(HiiHandle
[DISPLAY_ONLY_MY_ITEM
]),
2028 HiiRemovePackages (HiiHandle
[0]);
2030 HiiRemovePackages (HiiHandle
[1]);
2037 Unloads the application and its installed protocol.
2039 @param[in] ImageHandle Handle that identifies the image to be unloaded.
2041 @retval EFI_SUCCESS The image has been unloaded.
2045 DriverSampleUnload (
2046 IN EFI_HANDLE ImageHandle
2051 ASSERT (mPrivateData
!= NULL
);
2053 if (DriverHandle
[0] != NULL
) {
2054 gBS
->UninstallMultipleProtocolInterfaces (
2056 &gEfiDevicePathProtocolGuid
,
2057 &mHiiVendorDevicePath0
,
2058 &gEfiHiiConfigAccessProtocolGuid
,
2059 &mPrivateData
->ConfigAccess
,
2062 DriverHandle
[0] = NULL
;
2065 if (DriverHandle
[1] != NULL
) {
2066 gBS
->UninstallMultipleProtocolInterfaces (
2068 &gEfiDevicePathProtocolGuid
,
2069 &mHiiVendorDevicePath1
,
2070 &gEfiHiiConfigAccessProtocolGuid
,
2071 &mPrivateData
->ConfigAccess
,
2074 DriverHandle
[1] = NULL
;
2077 if (mPrivateData
->HiiHandle
[0] != NULL
) {
2078 HiiRemovePackages (mPrivateData
->HiiHandle
[0]);
2081 if (mPrivateData
->HiiHandle
[1] != NULL
) {
2082 HiiRemovePackages (mPrivateData
->HiiHandle
[1]);
2085 for (Index
= 0; Index
< NAME_VALUE_NAME_NUMBER
; Index
++) {
2086 if (mPrivateData
->NameValueName
[Index
] != NULL
) {
2087 FreePool (mPrivateData
->NameValueName
[Index
]);
2090 FreePool (mPrivateData
);
2091 mPrivateData
= NULL
;
2093 gBS
->CloseEvent (mEvent
);