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 - 2016, 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 Add empty function for event process function.
116 @param Event The Event need to be process
117 @param Context The context of the event.
122 DriverSampleInternalEmptyFunction (
130 Notification function for keystrokes.
132 @param[in] KeyData The key that was pressed.
134 @retval EFI_SUCCESS The operation was successful.
138 NotificationFunction(
139 IN EFI_KEY_DATA
*KeyData
142 gBS
->SignalEvent (mEvent
);
148 Function to start monitoring for CTRL-C using SimpleTextInputEx.
150 @retval EFI_SUCCESS The feature is enabled.
151 @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
155 InternalStartMonitor(
159 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*SimpleEx
;
160 EFI_KEY_DATA KeyData
;
165 EFI_HANDLE NotifyHandle
;
167 Status
= gBS
->LocateHandleBuffer (
169 &gEfiSimpleTextInputExProtocolGuid
,
174 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
175 Status
= gBS
->HandleProtocol (Handles
[HandleIndex
], &gEfiSimpleTextInputExProtocolGuid
, (VOID
**) &SimpleEx
);
176 ASSERT_EFI_ERROR (Status
);
178 KeyData
.KeyState
.KeyToggleState
= 0;
179 KeyData
.Key
.ScanCode
= 0;
180 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_LEFT_CONTROL_PRESSED
;
181 KeyData
.Key
.UnicodeChar
= L
'c';
183 Status
= SimpleEx
->RegisterKeyNotify(
186 NotificationFunction
,
188 if (EFI_ERROR (Status
)) {
192 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_RIGHT_CONTROL_PRESSED
;
193 Status
= SimpleEx
->RegisterKeyNotify(
196 NotificationFunction
,
198 if (EFI_ERROR (Status
)) {
207 Function to stop monitoring for CTRL-C using SimpleTextInputEx.
209 @retval EFI_SUCCESS The feature is enabled.
210 @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
218 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*SimpleEx
;
221 EFI_KEY_DATA KeyData
;
224 EFI_HANDLE NotifyHandle
;
226 Status
= gBS
->LocateHandleBuffer (
228 &gEfiSimpleTextInputExProtocolGuid
,
233 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
234 Status
= gBS
->HandleProtocol (Handles
[HandleIndex
], &gEfiSimpleTextInputExProtocolGuid
, (VOID
**) &SimpleEx
);
235 ASSERT_EFI_ERROR (Status
);
237 KeyData
.KeyState
.KeyToggleState
= 0;
238 KeyData
.Key
.ScanCode
= 0;
239 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_LEFT_CONTROL_PRESSED
;
240 KeyData
.Key
.UnicodeChar
= L
'c';
242 Status
= SimpleEx
->RegisterKeyNotify(
245 NotificationFunction
,
247 if (!EFI_ERROR (Status
)) {
248 Status
= SimpleEx
->UnregisterKeyNotify (SimpleEx
, NotifyHandle
);
251 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_RIGHT_CONTROL_PRESSED
;
252 Status
= SimpleEx
->RegisterKeyNotify(
255 NotificationFunction
,
257 if (!EFI_ERROR (Status
)) {
258 Status
= SimpleEx
->UnregisterKeyNotify (SimpleEx
, NotifyHandle
);
265 Update names of Name/Value storage to current language.
267 @param PrivateData Points to the driver private data.
269 @retval EFI_SUCCESS All names are successfully updated.
270 @retval EFI_NOT_FOUND Failed to get Name from HII database.
275 IN DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
281 // Get Name/Value name string of current language
283 for (Index
= 0; Index
< NAME_VALUE_NAME_NUMBER
; Index
++) {
284 PrivateData
->NameValueName
[Index
] = HiiGetString (
285 PrivateData
->HiiHandle
[0],
286 PrivateData
->NameStringId
[Index
],
289 if (PrivateData
->NameValueName
[Index
] == NULL
) {
290 return EFI_NOT_FOUND
;
299 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
301 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
303 This is a internal function.
305 @param StringPtr String in <BlockConfig> format and points to the
306 first character of <Number>.
307 @param Number The output value. Caller takes the responsibility
309 @param Len Length of the <Number>, in characters.
311 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
313 @retval EFI_SUCCESS Value of <Number> is outputted in Number
319 IN EFI_STRING StringPtr
,
333 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
334 return EFI_INVALID_PARAMETER
;
340 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
343 *Len
= StringPtr
- TmpPtr
;
346 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
348 Status
= EFI_OUT_OF_RESOURCES
;
351 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
352 *(Str
+ *Len
) = L
'\0';
354 Length
= (Length
+ 1) / 2;
355 Buf
= (UINT8
*) AllocateZeroPool (Length
);
357 Status
= EFI_OUT_OF_RESOURCES
;
362 ZeroMem (TemStr
, sizeof (TemStr
));
363 for (Index
= 0; Index
< Length
; Index
++) {
364 TemStr
[0] = Str
[Length
- Index
- 1];
365 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
366 if ((Index
& 1) == 0) {
367 Buf
[Index
/2] = DigitUint8
;
369 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
374 Status
= EFI_SUCCESS
;
385 Create altcfg string.
387 @param Result The request result string.
388 @param ConfigHdr The request head info. <ConfigHdr> format.
389 @param Offset The offset of the parameter int he structure.
390 @param Width The width of the parameter.
393 @retval The string with altcfg info append at the end.
397 IN EFI_STRING Result
,
398 IN EFI_STRING ConfigHdr
,
403 EFI_STRING StringPtr
;
407 NewLen
= StrLen (Result
);
409 // String Len = ConfigResp + AltConfig + AltConfig + 1("\0")
411 NewLen
= (NewLen
+ ((1 + StrLen (ConfigHdr
) + 8 + 4) + (8 + 4 + 7 + 4 + 7 + 4)) * 2 + 1) * sizeof (CHAR16
);
412 StringPtr
= AllocateZeroPool (NewLen
);
413 if (StringPtr
== NULL
) {
418 if (Result
!= NULL
) {
419 StrCpyS (StringPtr
, NewLen
/ sizeof (CHAR16
), Result
);
420 StringPtr
+= StrLen (Result
);
426 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
429 EFI_HII_DEFAULT_CLASS_STANDARD
431 StringPtr
+= StrLen (StringPtr
);
435 (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
436 L
"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
439 DEFAULT_CLASS_STANDARD_VALUE
441 StringPtr
+= StrLen (StringPtr
);
445 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
448 EFI_HII_DEFAULT_CLASS_MANUFACTURING
450 StringPtr
+= StrLen (StringPtr
);
454 (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
455 L
"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
458 DEFAULT_CLASS_MANUFACTURING_VALUE
460 StringPtr
+= StrLen (StringPtr
);
466 Check whether need to add the altcfg string. if need to add, add the altcfg
469 @param RequestResult The request result string.
470 @param ConfigRequestHdr The request head info. <ConfigHdr> format.
475 IN OUT EFI_STRING
*RequestResult
,
476 IN EFI_STRING ConfigRequestHdr
479 EFI_STRING StringPtr
;
490 StringPtr
= *RequestResult
;
491 StringPtr
= StrStr (StringPtr
, L
"OFFSET");
492 BlockSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
493 ValueOffset
= OFFSET_OF (DRIVER_SAMPLE_CONFIGURATION
, GetDefaultValueFromAccess
);
494 ValueWidth
= sizeof (((DRIVER_SAMPLE_CONFIGURATION
*)0)->GetDefaultValueFromAccess
);
496 if (StringPtr
== NULL
) {
500 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
501 StringPtr
+= StrLen (L
"OFFSET=");
505 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
506 if (EFI_ERROR (Status
)) {
513 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
515 FreePool (TmpBuffer
);
518 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
521 StringPtr
+= StrLen (L
"&WIDTH=");
526 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
527 if (EFI_ERROR (Status
)) {
534 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
536 FreePool (TmpBuffer
);
539 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
542 StringPtr
+= StrLen (L
"&VALUE=");
547 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
548 if (EFI_ERROR (Status
)) {
554 // Skip the character "&" before "OFFSET".
559 // Calculate Value and convert it to hex string.
561 if (Offset
+ Width
> BlockSize
) {
565 if (Offset
<= ValueOffset
&& Offset
+ Width
>= ValueOffset
+ ValueWidth
) {
566 *RequestResult
= CreateAltCfgString(*RequestResult
, ConfigRequestHdr
, ValueOffset
, ValueWidth
);
573 This function allows a caller to extract the current configuration for one
574 or more named elements from the target driver.
576 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
577 @param Request A null-terminated Unicode string in
578 <ConfigRequest> format.
579 @param Progress On return, points to a character in the Request
580 string. Points to the string's null terminator if
581 request was successful. Points to the most recent
582 '&' before the first failing name/value pair (or
583 the beginning of the string if the failure is in
584 the first name/value pair) if the request was not
586 @param Results A null-terminated Unicode string in
587 <ConfigAltResp> format which has all values filled
588 in for the names in the Request string. String to
589 be allocated by the called function.
591 @retval EFI_SUCCESS The Results is filled with the requested values.
592 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
593 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
594 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
601 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
602 IN CONST EFI_STRING Request
,
603 OUT EFI_STRING
*Progress
,
604 OUT EFI_STRING
*Results
609 DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
;
610 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
611 EFI_STRING ConfigRequest
;
612 EFI_STRING ConfigRequestHdr
;
618 BOOLEAN AllocatedRequest
;
620 if (Progress
== NULL
|| Results
== NULL
) {
621 return EFI_INVALID_PARAMETER
;
624 // Initialize the local variables.
626 ConfigRequestHdr
= NULL
;
627 ConfigRequest
= NULL
;
630 AllocatedRequest
= FALSE
;
632 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
633 HiiConfigRouting
= PrivateData
->HiiConfigRouting
;
636 // Get Buffer Storage data from EFI variable.
637 // Try to get the current setting from variable.
639 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
640 Status
= gRT
->GetVariable (
642 &gDriverSampleFormSetGuid
,
645 &PrivateData
->Configuration
647 if (EFI_ERROR (Status
)) {
648 return EFI_NOT_FOUND
;
651 if (Request
== NULL
) {
653 // Request is set to NULL, construct full request string.
657 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
658 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
660 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, VariableName
, PrivateData
->DriverHandle
[0]);
661 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
662 ConfigRequest
= AllocateZeroPool (Size
);
663 ASSERT (ConfigRequest
!= NULL
);
664 AllocatedRequest
= TRUE
;
665 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
666 FreePool (ConfigRequestHdr
);
667 ConfigRequestHdr
= NULL
;
670 // Check routing data in <ConfigHdr>.
671 // Note: if only one Storage is used, then this checking could be skipped.
673 if (!HiiIsConfigHdrMatch (Request
, &gDriverSampleFormSetGuid
, NULL
)) {
674 return EFI_NOT_FOUND
;
677 // Check whether request for EFI Varstore. EFI varstore get data
678 // through hii database, not support in this path.
680 if (HiiIsConfigHdrMatch(Request
, &gDriverSampleFormSetGuid
, MyEfiVar
)) {
681 return EFI_UNSUPPORTED
;
684 // Set Request to the unified request string.
686 ConfigRequest
= Request
;
688 // Check whether Request includes Request Element.
690 if (StrStr (Request
, L
"OFFSET") == NULL
) {
692 // Check Request Element does exist in Reques String
694 StrPointer
= StrStr (Request
, L
"PATH");
695 if (StrPointer
== NULL
) {
696 return EFI_INVALID_PARAMETER
;
698 if (StrStr (StrPointer
, L
"&") == NULL
) {
699 Size
= (StrLen (Request
) + 32 + 1) * sizeof (CHAR16
);
700 ConfigRequest
= AllocateZeroPool (Size
);
701 ASSERT (ConfigRequest
!= NULL
);
702 AllocatedRequest
= TRUE
;
703 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", Request
, (UINT64
)BufferSize
);
709 // Check if requesting Name/Value storage
711 if (StrStr (ConfigRequest
, L
"OFFSET") == NULL
) {
713 // Update Name/Value storage Names
715 Status
= LoadNameValueNames (PrivateData
);
716 if (EFI_ERROR (Status
)) {
721 // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"
722 // <Request> ::=<ConfigHdr>&Name0&Name1&Name2
723 // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044
725 BufferSize
= (StrLen (ConfigRequest
) +
726 1 + sizeof (PrivateData
->Configuration
.NameValueVar0
) * 2 +
727 1 + sizeof (PrivateData
->Configuration
.NameValueVar1
) * 2 +
728 1 + sizeof (PrivateData
->Configuration
.NameValueVar2
) * 2 + 1) * sizeof (CHAR16
);
729 *Results
= AllocateZeroPool (BufferSize
);
730 ASSERT (*Results
!= NULL
);
731 StrCpyS (*Results
, BufferSize
/ sizeof (CHAR16
), ConfigRequest
);
735 // Append value of NameValueVar0, type is UINT8
737 if ((Value
= StrStr (*Results
, PrivateData
->NameValueName
[0])) != NULL
) {
738 Value
+= StrLen (PrivateData
->NameValueName
[0]);
739 ValueStrLen
= ((sizeof (PrivateData
->Configuration
.NameValueVar0
) * 2) + 1);
740 CopyMem (Value
+ ValueStrLen
, Value
, StrSize (Value
));
742 BackupChar
= Value
[ValueStrLen
];
744 Value
+= UnicodeValueToString (
746 PREFIX_ZERO
| RADIX_HEX
,
747 PrivateData
->Configuration
.NameValueVar0
,
748 sizeof (PrivateData
->Configuration
.NameValueVar0
) * 2
754 // Append value of NameValueVar1, type is UINT16
756 if ((Value
= StrStr (*Results
, PrivateData
->NameValueName
[1])) != NULL
) {
757 Value
+= StrLen (PrivateData
->NameValueName
[1]);
758 ValueStrLen
= ((sizeof (PrivateData
->Configuration
.NameValueVar1
) * 2) + 1);
759 CopyMem (Value
+ ValueStrLen
, Value
, StrSize (Value
));
761 BackupChar
= Value
[ValueStrLen
];
763 Value
+= UnicodeValueToString (
765 PREFIX_ZERO
| RADIX_HEX
,
766 PrivateData
->Configuration
.NameValueVar1
,
767 sizeof (PrivateData
->Configuration
.NameValueVar1
) * 2
773 // Append value of NameValueVar2, type is CHAR16 *
775 if ((Value
= StrStr (*Results
, PrivateData
->NameValueName
[2])) != NULL
) {
776 Value
+= StrLen (PrivateData
->NameValueName
[2]);
777 ValueStrLen
= StrLen (PrivateData
->Configuration
.NameValueVar2
) * 4 + 1;
778 CopyMem (Value
+ ValueStrLen
, Value
, StrSize (Value
));
782 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
784 StrPointer
= (CHAR16
*) PrivateData
->Configuration
.NameValueVar2
;
785 for (; *StrPointer
!= L
'\0'; StrPointer
++) {
786 Value
+= UnicodeValueToString (Value
, PREFIX_ZERO
| RADIX_HEX
, *StrPointer
, 4);
790 Status
= EFI_SUCCESS
;
793 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
795 Status
= HiiConfigRouting
->BlockToConfig (
798 (UINT8
*) &PrivateData
->Configuration
,
803 if (!EFI_ERROR (Status
)) {
804 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, VariableName
, PrivateData
->DriverHandle
[0]);
805 AppendAltCfgString(Results
, ConfigRequestHdr
);
810 // Free the allocated config request string.
812 if (AllocatedRequest
) {
813 FreePool (ConfigRequest
);
816 if (ConfigRequestHdr
!= NULL
) {
817 FreePool (ConfigRequestHdr
);
820 // Set Progress string to the original request string.
822 if (Request
== NULL
) {
824 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
825 *Progress
= Request
+ StrLen (Request
);
833 This function processes the results of changes in configuration.
835 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
836 @param Configuration A null-terminated Unicode string in <ConfigResp>
838 @param Progress A pointer to a string filled in with the offset of
839 the most recent '&' before the first failing
840 name/value pair (or the beginning of the string if
841 the failure is in the first name/value pair) or
842 the terminating NULL if all was successful.
844 @retval EFI_SUCCESS The Results is processed successfully.
845 @retval EFI_INVALID_PARAMETER Configuration is NULL.
846 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
853 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
854 IN CONST EFI_STRING Configuration
,
855 OUT EFI_STRING
*Progress
860 DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
;
861 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
870 if (Configuration
== NULL
|| Progress
== NULL
) {
871 return EFI_INVALID_PARAMETER
;
874 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
875 HiiConfigRouting
= PrivateData
->HiiConfigRouting
;
876 *Progress
= Configuration
;
879 // Check routing data in <ConfigHdr>.
880 // Note: if only one Storage is used, then this checking could be skipped.
882 if (!HiiIsConfigHdrMatch (Configuration
, &gDriverSampleFormSetGuid
, NULL
)) {
883 return EFI_NOT_FOUND
;
887 // Check whether request for EFI Varstore. EFI varstore get data
888 // through hii database, not support in this path.
890 if (HiiIsConfigHdrMatch(Configuration
, &gDriverSampleFormSetGuid
, MyEfiVar
)) {
891 return EFI_UNSUPPORTED
;
895 // Get Buffer Storage data from EFI variable
897 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
898 Status
= gRT
->GetVariable (
900 &gDriverSampleFormSetGuid
,
903 &PrivateData
->Configuration
905 if (EFI_ERROR (Status
)) {
910 // Check if configuring Name/Value storage
912 if (StrStr (Configuration
, L
"OFFSET") == NULL
) {
914 // Update Name/Value storage Names
916 Status
= LoadNameValueNames (PrivateData
);
917 if (EFI_ERROR (Status
)) {
922 // Convert value for NameValueVar0
924 if ((Value
= StrStr (Configuration
, PrivateData
->NameValueName
[0])) != NULL
) {
928 Value
+= StrLen (PrivateData
->NameValueName
[0]);
933 StrPtr
= StrStr (Value
, L
"&");
934 if (StrPtr
== NULL
) {
935 StrPtr
= Value
+ StrLen (Value
);
938 // Convert Value to Buffer data
940 DataBuffer
= (UINT8
*) &PrivateData
->Configuration
.NameValueVar0
;
941 ZeroMem (TemStr
, sizeof (TemStr
));
942 for (Index
= 0, StrPtr
--; StrPtr
>= Value
; StrPtr
--, Index
++) {
944 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
945 if ((Index
& 1) == 0) {
946 DataBuffer
[Index
/2] = DigitUint8
;
948 DataBuffer
[Index
/2] = (UINT8
) ((UINT8
) (DigitUint8
<< 4) + DataBuffer
[Index
/2]);
954 // Convert value for NameValueVar1
956 if ((Value
= StrStr (Configuration
, PrivateData
->NameValueName
[1])) != NULL
) {
960 Value
+= StrLen (PrivateData
->NameValueName
[1]);
965 StrPtr
= StrStr (Value
, L
"&");
966 if (StrPtr
== NULL
) {
967 StrPtr
= Value
+ StrLen (Value
);
970 // Convert Value to Buffer data
972 DataBuffer
= (UINT8
*) &PrivateData
->Configuration
.NameValueVar1
;
973 ZeroMem (TemStr
, sizeof (TemStr
));
974 for (Index
= 0, StrPtr
--; StrPtr
>= Value
; StrPtr
--, Index
++) {
976 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
977 if ((Index
& 1) == 0) {
978 DataBuffer
[Index
/2] = DigitUint8
;
980 DataBuffer
[Index
/2] = (UINT8
) ((UINT8
) (DigitUint8
<< 4) + DataBuffer
[Index
/2]);
986 // Convert value for NameValueVar2
988 if ((Value
= StrStr (Configuration
, PrivateData
->NameValueName
[2])) != NULL
) {
992 Value
+= StrLen (PrivateData
->NameValueName
[2]);
997 StrPtr
= StrStr (Value
, L
"&");
998 if (StrPtr
== NULL
) {
999 StrPtr
= Value
+ StrLen (Value
);
1002 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1004 StrBuffer
= (CHAR16
*) PrivateData
->Configuration
.NameValueVar2
;
1005 ZeroMem (TemStr
, sizeof (TemStr
));
1006 while (Value
< StrPtr
) {
1007 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
, 4);
1008 *(StrBuffer
++) = (CHAR16
) StrHexToUint64 (TemStr
);
1015 // Store Buffer Storage back to EFI variable
1017 Status
= gRT
->SetVariable(
1019 &gDriverSampleFormSetGuid
,
1020 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1021 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1022 &PrivateData
->Configuration
1029 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
1031 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
1032 Status
= HiiConfigRouting
->ConfigToBlock (
1035 (UINT8
*) &PrivateData
->Configuration
,
1039 if (EFI_ERROR (Status
)) {
1044 // Store Buffer Storage back to EFI variable
1046 Status
= gRT
->SetVariable(
1048 &gDriverSampleFormSetGuid
,
1049 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1050 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1051 &PrivateData
->Configuration
1059 This function processes the results of changes in configuration.
1061 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1062 @param Action Specifies the type of action taken by the browser.
1063 @param QuestionId A unique value which is sent to the original
1064 exporting driver so that it can identify the type
1066 @param Type The type of value for the question.
1067 @param Value A pointer to the data being sent to the original
1069 @param ActionRequest On return, points to the action requested by the
1072 @retval EFI_SUCCESS The callback successfully handled the action.
1073 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1074 variable and its data.
1075 @retval EFI_DEVICE_ERROR The variable could not be saved.
1076 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1083 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1084 IN EFI_BROWSER_ACTION Action
,
1085 IN EFI_QUESTION_ID QuestionId
,
1087 IN EFI_IFR_TYPE_VALUE
*Value
,
1088 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1091 DRIVER_SAMPLE_PRIVATE_DATA
*PrivateData
;
1093 VOID
*StartOpCodeHandle
;
1094 VOID
*OptionsOpCodeHandle
;
1095 EFI_IFR_GUID_LABEL
*StartLabel
;
1096 VOID
*EndOpCodeHandle
;
1097 EFI_IFR_GUID_LABEL
*EndLabel
;
1099 DRIVER_SAMPLE_CONFIGURATION
*Configuration
;
1100 MY_EFI_VARSTORE_DATA
*EfiData
;
1102 EFI_STRING Progress
;
1109 if (((Value
== NULL
) && (Action
!= EFI_BROWSER_ACTION_FORM_OPEN
) && (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
))||
1110 (ActionRequest
== NULL
)) {
1111 return EFI_INVALID_PARAMETER
;
1117 Status
= EFI_SUCCESS
;
1119 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
1122 case EFI_BROWSER_ACTION_FORM_OPEN
:
1124 if (QuestionId
== 0x1234) {
1126 // Sample CallBack for UEFI FORM_OPEN action:
1127 // Add Save action into Form 3 when Form 1 is opened.
1128 // This will be done only in FORM_OPEN CallBack of question with ID 0x1234 from Form 1.
1130 PrivateData
= DRIVER_SAMPLE_PRIVATE_FROM_THIS (This
);
1133 // Initialize the container for dynamic opcodes
1135 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1136 ASSERT (StartOpCodeHandle
!= NULL
);
1139 // Create Hii Extend Label OpCode as the start opcode
1141 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1142 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1143 StartLabel
->Number
= LABEL_UPDATE2
;
1145 HiiCreateActionOpCode (
1146 StartOpCodeHandle
, // Container for dynamic created opcodes
1147 0x1238, // Question ID
1148 STRING_TOKEN(STR_SAVE_TEXT
), // Prompt text
1149 STRING_TOKEN(STR_SAVE_TEXT
), // Help text
1150 EFI_IFR_FLAG_CALLBACK
, // Question flag
1151 0 // Action String ID
1155 PrivateData
->HiiHandle
[0], // HII handle
1156 &gDriverSampleFormSetGuid
, // Formset GUID
1158 StartOpCodeHandle
, // Label for where to insert opcodes
1162 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1165 if (QuestionId
== 0x1247) {
1166 Status
= InternalStartMonitor ();
1167 ASSERT_EFI_ERROR (Status
);
1172 case EFI_BROWSER_ACTION_FORM_CLOSE
:
1174 if (QuestionId
== 0x5678) {
1176 // Sample CallBack for UEFI FORM_CLOSE action:
1177 // Show up a pop-up to specify Form 3 will be closed when exit Form 3.
1181 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1184 L
"You are going to leave third Form!",
1185 L
"Press ESC or ENTER to continue ...",
1189 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1192 if (QuestionId
== 0x1247) {
1193 Status
= InternalStopMonitor ();
1194 ASSERT_EFI_ERROR (Status
);
1199 case EFI_BROWSER_ACTION_RETRIEVE
:
1201 switch (QuestionId
) {
1203 if (Type
!= EFI_IFR_TYPE_REF
) {
1204 return EFI_INVALID_PARAMETER
;
1206 Value
->ref
.FormId
= 0x3;
1212 // We will reach here once the Question is refreshed
1216 // Initialize the container for dynamic opcodes
1218 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1219 ASSERT (StartOpCodeHandle
!= NULL
);
1222 // Create Hii Extend Label OpCode as the start opcode
1224 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1225 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1226 if (QuestionId
== 0x5678) {
1227 StartLabel
->Number
= LABEL_UPDATE2
;
1229 PrivateData
->Configuration
.DynamicRefresh
++;
1230 } else if (QuestionId
== 0x1247 ) {
1231 StartLabel
->Number
= LABEL_UPDATE3
;
1233 PrivateData
->Configuration
.RefreshGuidCount
++;
1236 HiiCreateActionOpCode (
1237 StartOpCodeHandle
, // Container for dynamic created opcodes
1238 0x1237, // Question ID
1239 STRING_TOKEN(STR_EXIT_TEXT
), // Prompt text
1240 STRING_TOKEN(STR_EXIT_TEXT
), // Help text
1241 EFI_IFR_FLAG_CALLBACK
, // Question flag
1242 0 // Action String ID
1246 PrivateData
->HiiHandle
[0], // HII handle
1247 &gDriverSampleFormSetGuid
, // Formset GUID
1249 StartOpCodeHandle
, // Label for where to insert opcodes
1253 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1256 // Refresh the Question value
1258 Status
= gRT
->SetVariable(
1260 &gDriverSampleFormSetGuid
,
1261 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1262 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1263 &PrivateData
->Configuration
1266 if (QuestionId
== 0x5678) {
1268 // Update uncommitted data of Browser
1270 EfiData
= AllocateZeroPool (sizeof (MY_EFI_VARSTORE_DATA
));
1271 ASSERT (EfiData
!= NULL
);
1272 if (HiiGetBrowserData (&gDriverSampleFormSetGuid
, MyEfiVar
, sizeof (MY_EFI_VARSTORE_DATA
), (UINT8
*) EfiData
)) {
1273 EfiData
->Field8
= 111;
1275 &gDriverSampleFormSetGuid
,
1277 sizeof (MY_EFI_VARSTORE_DATA
),
1289 case EFI_BROWSER_ACTION_DEFAULT_STANDARD
:
1291 switch (QuestionId
) {
1293 Value
->u8
= DEFAULT_CLASS_STANDARD_VALUE
;
1297 for (Index
= 0; Index
< 3; Index
++) {
1298 SetArrayData (Value
, EFI_IFR_TYPE_NUM_SIZE_8
, Index
, BufferValue
--);
1303 Status
= EFI_UNSUPPORTED
;
1309 case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
:
1311 switch (QuestionId
) {
1313 Value
->u8
= DEFAULT_CLASS_MANUFACTURING_VALUE
;
1317 Status
= EFI_UNSUPPORTED
;
1323 case EFI_BROWSER_ACTION_CHANGING
:
1325 switch (QuestionId
) {
1328 if (Type
!= EFI_IFR_TYPE_REF
) {
1329 return EFI_INVALID_PARAMETER
;
1332 Value
->ref
.FormId
= 0x1234;
1337 // Initialize the container for dynamic opcodes
1339 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1340 ASSERT (StartOpCodeHandle
!= NULL
);
1342 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1343 ASSERT (EndOpCodeHandle
!= NULL
);
1346 // Create Hii Extend Label OpCode as the start opcode
1348 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1349 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1350 StartLabel
->Number
= LABEL_UPDATE1
;
1353 // Create Hii Extend Label OpCode as the end opcode
1355 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1356 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1357 EndLabel
->Number
= LABEL_END
;
1359 HiiCreateActionOpCode (
1360 StartOpCodeHandle
, // Container for dynamic created opcodes
1361 0x1237, // Question ID
1362 STRING_TOKEN(STR_EXIT_TEXT
), // Prompt text
1363 STRING_TOKEN(STR_EXIT_TEXT
), // Help text
1364 EFI_IFR_FLAG_CALLBACK
, // Question flag
1365 0 // Action String ID
1369 // Create Option OpCode
1371 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1372 ASSERT (OptionsOpCodeHandle
!= NULL
);
1374 HiiCreateOneOfOptionOpCode (
1375 OptionsOpCodeHandle
,
1376 STRING_TOKEN (STR_BOOT_OPTION1
),
1378 EFI_IFR_NUMERIC_SIZE_1
,
1382 HiiCreateOneOfOptionOpCode (
1383 OptionsOpCodeHandle
,
1384 STRING_TOKEN (STR_BOOT_OPTION2
),
1386 EFI_IFR_NUMERIC_SIZE_1
,
1391 // Prepare initial value for the dynamic created oneof Question
1393 PrivateData
->Configuration
.DynamicOneof
= 2;
1394 Status
= gRT
->SetVariable(
1396 &gDriverSampleFormSetGuid
,
1397 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1398 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1399 &PrivateData
->Configuration
1403 // Set initial vlaue of dynamic created oneof Question in Form Browser
1405 Configuration
= AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION
));
1406 ASSERT (Configuration
!= NULL
);
1407 if (HiiGetBrowserData (&gDriverSampleFormSetGuid
, VariableName
, sizeof (DRIVER_SAMPLE_CONFIGURATION
), (UINT8
*) Configuration
)) {
1408 Configuration
->DynamicOneof
= 2;
1411 // Update uncommitted data of Browser
1414 &gDriverSampleFormSetGuid
,
1416 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1417 (UINT8
*) Configuration
,
1421 FreePool (Configuration
);
1423 HiiCreateOneOfOpCode (
1424 StartOpCodeHandle
, // Container for dynamic created opcodes
1425 0x8001, // Question ID (or call it "key")
1426 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1427 (UINT16
) DYNAMIC_ONE_OF_VAR_OFFSET
, // Offset in Buffer Storage
1428 STRING_TOKEN (STR_ONE_OF_PROMPT
), // Question prompt text
1429 STRING_TOKEN (STR_ONE_OF_HELP
), // Question help text
1430 EFI_IFR_FLAG_CALLBACK
, // Question flag
1431 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question Value
1432 OptionsOpCodeHandle
, // Option Opcode list
1433 NULL
// Default Opcode is NULl
1436 HiiCreateOrderedListOpCode (
1437 StartOpCodeHandle
, // Container for dynamic created opcodes
1438 0x8002, // Question ID
1439 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1440 (UINT16
) DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1441 STRING_TOKEN (STR_BOOT_OPTIONS
), // Question prompt text
1442 STRING_TOKEN (STR_BOOT_OPTIONS
), // Question help text
1443 EFI_IFR_FLAG_RESET_REQUIRED
, // Question flag
1444 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1445 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1446 5, // Maximum container
1447 OptionsOpCodeHandle
, // Option Opcode list
1448 NULL
// Default Opcode is NULl
1451 HiiCreateTextOpCode (
1453 STRING_TOKEN(STR_TEXT_SAMPLE_HELP
),
1454 STRING_TOKEN(STR_TEXT_SAMPLE_HELP
),
1455 STRING_TOKEN(STR_TEXT_SAMPLE_STRING
)
1458 HiiCreateDateOpCode (
1463 STRING_TOKEN(STR_DATE_SAMPLE_HELP
),
1464 STRING_TOKEN(STR_DATE_SAMPLE_HELP
),
1466 QF_DATE_STORAGE_TIME
,
1470 HiiCreateTimeOpCode (
1475 STRING_TOKEN(STR_TIME_SAMPLE_HELP
),
1476 STRING_TOKEN(STR_TIME_SAMPLE_HELP
),
1478 QF_TIME_STORAGE_TIME
,
1482 HiiCreateGotoOpCode (
1483 StartOpCodeHandle
, // Container for dynamic created opcodes
1484 1, // Target Form ID
1485 STRING_TOKEN (STR_GOTO_FORM1
), // Prompt text
1486 STRING_TOKEN (STR_GOTO_HELP
), // Help text
1488 0x8003 // Question ID
1492 PrivateData
->HiiHandle
[0], // HII handle
1493 &gDriverSampleFormSetGuid
, // Formset GUID
1495 StartOpCodeHandle
, // Label for where to insert opcodes
1496 EndOpCodeHandle
// Replace data
1499 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1500 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1501 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1510 case EFI_BROWSER_ACTION_CHANGED
:
1511 switch (QuestionId
) {
1514 // User press "Exit now", request Browser to exit
1516 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
1521 // User press "Save now", request Browser to save the uncommitted data.
1523 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
1529 // User press "Submit current form and Exit now", request Browser to submit current form and exit
1531 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
1536 // User press "Discard current form now", request Browser to discard the uncommitted data.
1538 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
;
1543 // User press "Submit current form now", request Browser to save the uncommitted data.
1545 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
1551 // User press "Discard current form and Exit now", request Browser to discard the uncommitted data and exit.
1553 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
1558 // 1. Check to see whether system support keyword.
1560 Status
= PrivateData
->HiiKeywordHandler
->GetData (PrivateData
->HiiKeywordHandler
,
1561 L
"NAMESPACE=x-UEFI-ns",
1562 L
"KEYWORD=iSCSIBootEnable",
1567 if (EFI_ERROR (Status
)) {
1570 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1573 L
"This system not support this keyword!",
1574 L
"Press ENTER to continue ...",
1578 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1580 Status
= EFI_SUCCESS
;
1585 // 2. If system support this keyword, just try to change value.
1589 // Change value from '0' to '1' or from '1' to '0'
1591 TmpStr
= StrStr (Results
, L
"&VALUE=");
1592 ASSERT (TmpStr
!= NULL
);
1593 TmpStr
+= StrLen (L
"&VALUE=");
1595 if (*TmpStr
== L
'0') {
1602 // 3. Call the keyword handler protocol to change the value.
1604 Status
= PrivateData
->HiiKeywordHandler
->SetData (PrivateData
->HiiKeywordHandler
,
1609 if (EFI_ERROR (Status
)) {
1612 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1615 L
"Set keyword to the system failed!",
1616 L
"Press ENTER to continue ...",
1620 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1622 Status
= EFI_SUCCESS
;
1632 case EFI_BROWSER_ACTION_SUBMITTED
:
1634 if (QuestionId
== 0x1250) {
1636 // Sample CallBack for EFI_BROWSER_ACTION_SUBMITTED action:
1637 // Show up a pop-up to show SUBMITTED callback has been triggered.
1641 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1644 L
"EfiVarstore value has been submitted!",
1645 L
"Press ESC or ENTER to continue ...",
1649 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1655 Status
= EFI_UNSUPPORTED
;
1663 Main entry for this driver.
1665 @param ImageHandle Image handle this driver.
1666 @param SystemTable Pointer to SystemTable.
1668 @retval EFI_SUCESS This function always complete successfully.
1674 IN EFI_HANDLE ImageHandle
,
1675 IN EFI_SYSTEM_TABLE
*SystemTable
1679 EFI_HII_HANDLE HiiHandle
[2];
1680 EFI_SCREEN_DESCRIPTOR Screen
;
1681 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
1682 EFI_HII_STRING_PROTOCOL
*HiiString
;
1683 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
1684 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
1685 EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*HiiKeywordHandler
;
1688 DRIVER_SAMPLE_CONFIGURATION
*Configuration
;
1690 EFI_STRING ConfigRequestHdr
;
1691 EFI_STRING NameRequestHdr
;
1692 MY_EFI_VARSTORE_DATA
*VarStoreConfig
;
1693 EFI_INPUT_KEY HotKey
;
1694 EDKII_FORM_BROWSER_EXTENSION_PROTOCOL
*FormBrowserEx
;
1697 // Initialize the local variables.
1699 ConfigRequestHdr
= NULL
;
1703 // Initialize screen dimensions for SendForm().
1704 // Remove 3 characters from top and bottom
1706 ZeroMem (&Screen
, sizeof (EFI_SCREEN_DESCRIPTOR
));
1707 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &Screen
.RightColumn
, &Screen
.BottomRow
);
1710 Screen
.BottomRow
= Screen
.BottomRow
- 3;
1713 // Initialize driver private data
1715 mPrivateData
= AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA
));
1716 if (mPrivateData
== NULL
) {
1717 return EFI_OUT_OF_RESOURCES
;
1720 mPrivateData
->Signature
= DRIVER_SAMPLE_PRIVATE_SIGNATURE
;
1722 mPrivateData
->ConfigAccess
.ExtractConfig
= ExtractConfig
;
1723 mPrivateData
->ConfigAccess
.RouteConfig
= RouteConfig
;
1724 mPrivateData
->ConfigAccess
.Callback
= DriverCallback
;
1727 // Locate Hii Database protocol
1729 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**) &HiiDatabase
);
1730 if (EFI_ERROR (Status
)) {
1733 mPrivateData
->HiiDatabase
= HiiDatabase
;
1736 // Locate HiiString protocol
1738 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, (VOID
**) &HiiString
);
1739 if (EFI_ERROR (Status
)) {
1742 mPrivateData
->HiiString
= HiiString
;
1745 // Locate Formbrowser2 protocol
1747 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &FormBrowser2
);
1748 if (EFI_ERROR (Status
)) {
1751 mPrivateData
->FormBrowser2
= FormBrowser2
;
1754 // Locate ConfigRouting protocol
1756 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
1757 if (EFI_ERROR (Status
)) {
1760 mPrivateData
->HiiConfigRouting
= HiiConfigRouting
;
1763 // Locate keyword handler protocol
1765 Status
= gBS
->LocateProtocol (&gEfiConfigKeywordHandlerProtocolGuid
, NULL
, (VOID
**) &HiiKeywordHandler
);
1766 if (EFI_ERROR (Status
)) {
1769 mPrivateData
->HiiKeywordHandler
= HiiKeywordHandler
;
1771 Status
= gBS
->InstallMultipleProtocolInterfaces (
1773 &gEfiDevicePathProtocolGuid
,
1774 &mHiiVendorDevicePath0
,
1775 &gEfiHiiConfigAccessProtocolGuid
,
1776 &mPrivateData
->ConfigAccess
,
1779 ASSERT_EFI_ERROR (Status
);
1781 mPrivateData
->DriverHandle
[0] = DriverHandle
[0];
1784 // Publish our HII data
1786 HiiHandle
[0] = HiiAddPackages (
1787 &gDriverSampleFormSetGuid
,
1789 DriverSampleStrings
,
1793 if (HiiHandle
[0] == NULL
) {
1794 return EFI_OUT_OF_RESOURCES
;
1797 mPrivateData
->HiiHandle
[0] = HiiHandle
[0];
1800 // Publish another Fromset
1802 Status
= gBS
->InstallMultipleProtocolInterfaces (
1804 &gEfiDevicePathProtocolGuid
,
1805 &mHiiVendorDevicePath1
,
1806 &gEfiHiiConfigAccessProtocolGuid
,
1807 &mPrivateData
->ConfigAccess
,
1810 ASSERT_EFI_ERROR (Status
);
1812 mPrivateData
->DriverHandle
[1] = DriverHandle
[1];
1814 HiiHandle
[1] = HiiAddPackages (
1815 &gDriverSampleInventoryGuid
,
1817 DriverSampleStrings
,
1821 if (HiiHandle
[1] == NULL
) {
1822 DriverSampleUnload (ImageHandle
);
1823 return EFI_OUT_OF_RESOURCES
;
1826 mPrivateData
->HiiHandle
[1] = HiiHandle
[1];
1829 // Update the device path string.
1831 NewString
= ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL
*)&mHiiVendorDevicePath0
, FALSE
, FALSE
);
1832 if (HiiSetString (HiiHandle
[0], STRING_TOKEN (STR_DEVICE_PATH
), NewString
, NULL
) == 0) {
1833 DriverSampleUnload (ImageHandle
);
1834 return EFI_OUT_OF_RESOURCES
;
1836 if (NewString
!= NULL
) {
1837 FreePool (NewString
);
1841 // Very simple example of how one would update a string that is already
1842 // in the HII database
1844 NewString
= L
"700 Mhz";
1846 if (HiiSetString (HiiHandle
[0], STRING_TOKEN (STR_CPU_STRING2
), NewString
, NULL
) == 0) {
1847 DriverSampleUnload (ImageHandle
);
1848 return EFI_OUT_OF_RESOURCES
;
1851 HiiSetString (HiiHandle
[0], 0, NewString
, NULL
);
1854 // Initialize Name/Value name String ID
1856 mPrivateData
->NameStringId
[0] = STR_NAME_VALUE_VAR_NAME0
;
1857 mPrivateData
->NameStringId
[1] = STR_NAME_VALUE_VAR_NAME1
;
1858 mPrivateData
->NameStringId
[2] = STR_NAME_VALUE_VAR_NAME2
;
1861 // Initialize configuration data
1863 Configuration
= &mPrivateData
->Configuration
;
1864 ZeroMem (Configuration
, sizeof (DRIVER_SAMPLE_CONFIGURATION
));
1867 // Try to read NV config EFI variable first
1869 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, VariableName
, DriverHandle
[0]);
1870 ASSERT (ConfigRequestHdr
!= NULL
);
1872 NameRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, NULL
, DriverHandle
[0]);
1873 ASSERT (NameRequestHdr
!= NULL
);
1875 BufferSize
= sizeof (DRIVER_SAMPLE_CONFIGURATION
);
1876 Status
= gRT
->GetVariable (VariableName
, &gDriverSampleFormSetGuid
, NULL
, &BufferSize
, Configuration
);
1877 if (EFI_ERROR (Status
)) {
1879 // Store zero data Buffer Storage to EFI variable
1881 Status
= gRT
->SetVariable(
1883 &gDriverSampleFormSetGuid
,
1884 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1885 sizeof (DRIVER_SAMPLE_CONFIGURATION
),
1888 if (EFI_ERROR (Status
)) {
1889 DriverSampleUnload (ImageHandle
);
1893 // EFI variable for NV config doesn't exit, we should build this variable
1894 // based on default values stored in IFR
1896 ActionFlag
= HiiSetToDefaults (NameRequestHdr
, EFI_HII_DEFAULT_CLASS_STANDARD
);
1898 DriverSampleUnload (ImageHandle
);
1899 return EFI_INVALID_PARAMETER
;
1902 ActionFlag
= HiiSetToDefaults (ConfigRequestHdr
, EFI_HII_DEFAULT_CLASS_STANDARD
);
1904 DriverSampleUnload (ImageHandle
);
1905 return EFI_INVALID_PARAMETER
;
1909 // EFI variable does exist and Validate Current Setting
1911 ActionFlag
= HiiValidateSettings (NameRequestHdr
);
1913 DriverSampleUnload (ImageHandle
);
1914 return EFI_INVALID_PARAMETER
;
1917 ActionFlag
= HiiValidateSettings (ConfigRequestHdr
);
1919 DriverSampleUnload (ImageHandle
);
1920 return EFI_INVALID_PARAMETER
;
1923 FreePool (ConfigRequestHdr
);
1926 // Initialize efi varstore configuration data
1928 VarStoreConfig
= &mPrivateData
->VarStoreConfig
;
1929 ZeroMem (VarStoreConfig
, sizeof (MY_EFI_VARSTORE_DATA
));
1931 ConfigRequestHdr
= HiiConstructConfigHdr (&gDriverSampleFormSetGuid
, MyEfiVar
, DriverHandle
[0]);
1932 ASSERT (ConfigRequestHdr
!= NULL
);
1934 BufferSize
= sizeof (MY_EFI_VARSTORE_DATA
);
1935 Status
= gRT
->GetVariable (MyEfiVar
, &gDriverSampleFormSetGuid
, NULL
, &BufferSize
, VarStoreConfig
);
1936 if (EFI_ERROR (Status
)) {
1938 // Store zero data to EFI variable Storage.
1940 Status
= gRT
->SetVariable(
1942 &gDriverSampleFormSetGuid
,
1943 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1944 sizeof (MY_EFI_VARSTORE_DATA
),
1947 if (EFI_ERROR (Status
)) {
1948 DriverSampleUnload (ImageHandle
);
1952 // EFI variable for NV config doesn't exit, we should build this variable
1953 // based on default values stored in IFR
1955 ActionFlag
= HiiSetToDefaults (ConfigRequestHdr
, EFI_HII_DEFAULT_CLASS_STANDARD
);
1957 DriverSampleUnload (ImageHandle
);
1958 return EFI_INVALID_PARAMETER
;
1962 // EFI variable does exist and Validate Current Setting
1964 ActionFlag
= HiiValidateSettings (ConfigRequestHdr
);
1966 DriverSampleUnload (ImageHandle
);
1967 return EFI_INVALID_PARAMETER
;
1970 FreePool (ConfigRequestHdr
);
1972 Status
= gBS
->CreateEventEx (
1975 DriverSampleInternalEmptyFunction
,
1977 &gEfiIfrRefreshIdOpGuid
,
1980 ASSERT_EFI_ERROR (Status
);
1983 // Example of how to use BrowserEx protocol to register HotKey.
1985 Status
= gBS
->LocateProtocol (&gEdkiiFormBrowserExProtocolGuid
, NULL
, (VOID
**) &FormBrowserEx
);
1986 if (!EFI_ERROR (Status
)) {
1988 // First unregister the default hot key F9 and F10.
1990 HotKey
.UnicodeChar
= CHAR_NULL
;
1991 HotKey
.ScanCode
= SCAN_F9
;
1992 FormBrowserEx
->RegisterHotKey (&HotKey
, 0, 0, NULL
);
1993 HotKey
.ScanCode
= SCAN_F10
;
1994 FormBrowserEx
->RegisterHotKey (&HotKey
, 0, 0, NULL
);
1997 // Register the default HotKey F9 and F10 again.
1999 HotKey
.ScanCode
= SCAN_F10
;
2000 NewString
= HiiGetString (mPrivateData
->HiiHandle
[0], STRING_TOKEN (FUNCTION_TEN_STRING
), NULL
);
2001 ASSERT (NewString
!= NULL
);
2002 FormBrowserEx
->RegisterHotKey (&HotKey
, BROWSER_ACTION_SUBMIT
, 0, NewString
);
2003 HotKey
.ScanCode
= SCAN_F9
;
2004 NewString
= HiiGetString (mPrivateData
->HiiHandle
[0], STRING_TOKEN (FUNCTION_NINE_STRING
), NULL
);
2005 ASSERT (NewString
!= NULL
);
2006 FormBrowserEx
->RegisterHotKey (&HotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, NewString
);
2010 // In default, this driver is built into Flash device image,
2011 // the following code doesn't run.
2015 // Example of how to display only the item we sent to HII
2016 // When this driver is not built into Flash device image,
2017 // it need to call SendForm to show front page by itself.
2019 if (DISPLAY_ONLY_MY_ITEM
<= 1) {
2021 // Have the browser pull out our copy of the data, and only display our data
2023 Status
= FormBrowser2
->SendForm (
2025 &(HiiHandle
[DISPLAY_ONLY_MY_ITEM
]),
2033 HiiRemovePackages (HiiHandle
[0]);
2035 HiiRemovePackages (HiiHandle
[1]);
2042 Unloads the application and its installed protocol.
2044 @param[in] ImageHandle Handle that identifies the image to be unloaded.
2046 @retval EFI_SUCCESS The image has been unloaded.
2050 DriverSampleUnload (
2051 IN EFI_HANDLE ImageHandle
2056 ASSERT (mPrivateData
!= NULL
);
2058 if (DriverHandle
[0] != NULL
) {
2059 gBS
->UninstallMultipleProtocolInterfaces (
2061 &gEfiDevicePathProtocolGuid
,
2062 &mHiiVendorDevicePath0
,
2063 &gEfiHiiConfigAccessProtocolGuid
,
2064 &mPrivateData
->ConfigAccess
,
2067 DriverHandle
[0] = NULL
;
2070 if (DriverHandle
[1] != NULL
) {
2071 gBS
->UninstallMultipleProtocolInterfaces (
2073 &gEfiDevicePathProtocolGuid
,
2074 &mHiiVendorDevicePath1
,
2075 &gEfiHiiConfigAccessProtocolGuid
,
2076 &mPrivateData
->ConfigAccess
,
2079 DriverHandle
[1] = NULL
;
2082 if (mPrivateData
->HiiHandle
[0] != NULL
) {
2083 HiiRemovePackages (mPrivateData
->HiiHandle
[0]);
2086 if (mPrivateData
->HiiHandle
[1] != NULL
) {
2087 HiiRemovePackages (mPrivateData
->HiiHandle
[1]);
2090 for (Index
= 0; Index
< NAME_VALUE_NAME_NUMBER
; Index
++) {
2091 if (mPrivateData
->NameValueName
[Index
] != NULL
) {
2092 FreePool (mPrivateData
->NameValueName
[Index
]);
2095 FreePool (mPrivateData
);
2096 mPrivateData
= NULL
;
2098 gBS
->CloseEvent (mEvent
);