2 HII Library implementation that uses DXE protocols and services.
4 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "InternalHiiLib.h"
17 #define GUID_CONFIG_STRING_TYPE 0x00
18 #define NAME_CONFIG_STRING_TYPE 0x01
19 #define PATH_CONFIG_STRING_TYPE 0x02
21 #define ACTION_SET_DEFAUTL_VALUE 0x01
22 #define ACTION_VALIDATE_SETTING 0x02
24 #define HII_LIB_DEFAULT_VARSTORE_SIZE 0x200
27 LIST_ENTRY Entry
; // Link to Block array
35 EFI_VARSTORE_ID VarStoreId
;
37 } IFR_VARSTORAGE_DATA
;
40 // <ConfigHdr> Template
42 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";
44 EFI_FORM_BROWSER2_PROTOCOL
*mUefiFormBrowser2
= NULL
;
47 // Template used to mark the end of a list of packages
49 GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER mEndOfPakageList
= {
50 sizeof (EFI_HII_PACKAGE_HEADER
),
55 Extract Hii package list GUID for given HII handle.
57 If HiiHandle could not be found in the HII database, then ASSERT.
58 If Guid is NULL, then ASSERT.
60 @param Handle Hii handle
61 @param Guid Package list GUID
63 @retval EFI_SUCCESS Successfully extract GUID from Hii database.
68 InternalHiiExtractGuidFromHiiHandle (
69 IN EFI_HII_HANDLE Handle
,
75 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
77 ASSERT (Guid
!= NULL
);
78 ASSERT (Handle
!= NULL
);
81 // Get HII PackageList
84 HiiPackageList
= NULL
;
86 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
87 ASSERT (Status
!= EFI_NOT_FOUND
);
89 if (Status
== EFI_BUFFER_TOO_SMALL
) {
90 HiiPackageList
= AllocatePool (BufferSize
);
91 ASSERT (HiiPackageList
!= NULL
);
93 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
95 if (EFI_ERROR (Status
)) {
96 FreePool (HiiPackageList
);
103 CopyGuid (Guid
, &HiiPackageList
->PackageListGuid
);
105 FreePool (HiiPackageList
);
111 Registers a list of packages in the HII Database and returns the HII Handle
112 associated with that registration. If an HII Handle has already been registered
113 with the same PackageListGuid and DeviceHandle, then NULL is returned. If there
114 are not enough resources to perform the registration, then NULL is returned.
115 If an empty list of packages is passed in, then NULL is returned. If the size of
116 the list of package is 0, then NULL is returned.
118 The variable arguments are pointers which point to package header that defined
119 by UEFI VFR compiler and StringGather tool.
121 #pragma pack (push, 1)
124 EFI_HII_PACKAGE_HEADER PackageHeader;
125 } EDKII_AUTOGEN_PACKAGES_HEADER;
128 @param[in] PackageListGuid The GUID of the package list.
129 @param[in] DeviceHandle If not NULL, the Device Handle on which
130 an instance of DEVICE_PATH_PROTOCOL is installed.
131 This Device Handle uniquely defines the device that
132 the added packages are associated with.
133 @param[in] ... The variable argument list that contains pointers
134 to packages terminated by a NULL.
136 @retval NULL A HII Handle has already been registered in the HII Database with
137 the same PackageListGuid and DeviceHandle.
138 @retval NULL The HII Handle could not be created.
139 @retval NULL An empty list of packages was passed in.
140 @retval NULL All packages are empty.
141 @retval Other The HII Handle associated with the newly registered package list.
147 IN CONST EFI_GUID
*PackageListGuid
,
148 IN EFI_HANDLE DeviceHandle OPTIONAL
,
155 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
156 EFI_HII_HANDLE HiiHandle
;
160 ASSERT (PackageListGuid
!= NULL
);
163 // Calculate the length of all the packages in the variable argument list
165 for (Length
= 0, VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
166 Length
+= (ReadUnaligned32 (Package
) - sizeof (UINT32
));
171 // If there are no packages in the variable argument list or all the packages
172 // are empty, then return a NULL HII Handle
179 // Add the length of the Package List Header and the terminating Package Header
181 Length
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
) + sizeof (EFI_HII_PACKAGE_HEADER
);
184 // Allocate the storage for the entire Package List
186 PackageListHeader
= AllocateZeroPool (Length
);
189 // If the Package List can not be allocated, then return a NULL HII Handle
191 if (PackageListHeader
== NULL
) {
196 // Fill in the GUID and Length of the Package List Header
198 CopyGuid (&PackageListHeader
->PackageListGuid
, PackageListGuid
);
199 PackageListHeader
->PackageLength
= Length
;
202 // Initialize a pointer to the beginning if the Package List data
204 Data
= (UINT8
*)(PackageListHeader
+ 1);
207 // Copy the data from each package in the variable argument list
209 for (VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
210 Length
= ReadUnaligned32 (Package
) - sizeof (UINT32
);
211 CopyMem (Data
, Package
+ 1, Length
);
217 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list
219 CopyMem (Data
, &mEndOfPakageList
, sizeof (mEndOfPakageList
));
222 // Register the package list with the HII Database
224 Status
= gHiiDatabase
->NewPackageList (
230 if (EFI_ERROR (Status
)) {
235 // Free the allocated package list
237 FreePool (PackageListHeader
);
240 // Return the new HII Handle
246 Removes a package list from the HII database.
248 If HiiHandle is NULL, then ASSERT.
249 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.
251 @param[in] HiiHandle The handle that was previously registered in the HII database
257 IN EFI_HII_HANDLE HiiHandle
262 ASSERT (HiiHandle
!= NULL
);
263 Status
= gHiiDatabase
->RemovePackageList (gHiiDatabase
, HiiHandle
);
264 ASSERT_EFI_ERROR (Status
);
269 Retrieves the array of all the HII Handles or the HII handles of a specific
270 package list GUID in the HII Database.
271 This array is terminated with a NULL HII Handle.
272 This function allocates the returned array using AllocatePool().
273 The caller is responsible for freeing the array with FreePool().
275 @param[in] PackageListGuid An optional parameter that is used to request
276 HII Handles associated with a specific
277 Package List GUID. If this parameter is NULL,
278 then all the HII Handles in the HII Database
279 are returned. If this parameter is not NULL,
280 then zero or more HII Handles associated with
281 PackageListGuid are returned.
283 @retval NULL No HII handles were found in the HII database
284 @retval NULL The array of HII Handles could not be retrieved
285 @retval Other A pointer to the NULL terminated array of HII Handles
291 IN CONST EFI_GUID
*PackageListGuid OPTIONAL
295 UINTN HandleBufferLength
;
296 EFI_HII_HANDLE TempHiiHandleBuffer
;
297 EFI_HII_HANDLE
*HiiHandleBuffer
;
303 // Retrieve the size required for the buffer of all HII handles.
305 HandleBufferLength
= 0;
306 Status
= gHiiDatabase
->ListPackageLists (
308 EFI_HII_PACKAGE_TYPE_ALL
,
315 // If ListPackageLists() returns EFI_SUCCESS for a zero size,
316 // then there are no HII handles in the HII database. If ListPackageLists()
317 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII
318 // handles in the HII database.
320 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
322 // Return NULL if the size can not be retrieved, or if there are no HII
323 // handles in the HII Database
329 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator
331 HiiHandleBuffer
= AllocateZeroPool (HandleBufferLength
+ sizeof (EFI_HII_HANDLE
));
332 if (HiiHandleBuffer
== NULL
) {
334 // Return NULL if allocation fails.
340 // Retrieve the array of HII Handles in the HII Database
342 Status
= gHiiDatabase
->ListPackageLists (
344 EFI_HII_PACKAGE_TYPE_ALL
,
349 if (EFI_ERROR (Status
)) {
351 // Free the buffer and return NULL if the HII handles can not be retrieved.
353 FreePool (HiiHandleBuffer
);
357 if (PackageListGuid
== NULL
) {
359 // Return the NULL terminated array of HII handles in the HII Database
361 return HiiHandleBuffer
;
363 for (Index1
= 0, Index2
= 0; HiiHandleBuffer
[Index1
] != NULL
; Index1
++) {
364 Status
= InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer
[Index1
], &Guid
);
365 ASSERT_EFI_ERROR (Status
);
366 if (CompareGuid (&Guid
, PackageListGuid
)) {
367 HiiHandleBuffer
[Index2
++] = HiiHandleBuffer
[Index1
];
371 HiiHandleBuffer
[Index2
] = NULL
;
372 return HiiHandleBuffer
;
374 FreePool (HiiHandleBuffer
);
381 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
382 hex digits that appear between a '=' and a '&' in a config string.
384 If ConfigString is NULL, then ASSERT().
386 @param[in] ConfigString Pointer to a Null-terminated Unicode string.
388 @return Pointer to the Null-terminated Unicode result string.
393 InternalHiiLowerConfigString (
394 IN EFI_STRING ConfigString
400 ASSERT (ConfigString
!= NULL
);
403 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
405 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
406 if (*String
== L
'=') {
408 } else if (*String
== L
'&') {
410 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
411 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
419 Uses the BlockToConfig() service of the Config Routing Protocol to
420 convert <ConfigRequest> and a buffer to a <ConfigResp>
422 If ConfigRequest is NULL, then ASSERT().
423 If Block is NULL, then ASSERT().
425 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.
426 @param[in] Block Pointer to a block of data.
427 @param[in] BlockSize The zie, in bytes, of Block.
429 @retval NULL The <ConfigResp> string could not be generated.
430 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.
435 InternalHiiBlockToConfig (
436 IN CONST EFI_STRING ConfigRequest
,
437 IN CONST UINT8
*Block
,
442 EFI_STRING ConfigResp
;
445 ASSERT (ConfigRequest
!= NULL
);
446 ASSERT (Block
!= NULL
);
449 // Convert <ConfigRequest> to <ConfigResp>
451 Status
= gHiiConfigRouting
->BlockToConfig (
459 if (EFI_ERROR (Status
)) {
466 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve
467 or set uncommitted data. If sata i being retrieved, then the buffer is
468 allocated using AllocatePool(). The caller is then responsible for freeing
469 the buffer using FreePool().
471 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
472 parameter that may be NULL.
473 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
474 is an optional parameter that may be NULL.
475 @param[in] SetResultsData If not NULL, then this parameter specified the buffer
476 of uncommited data to set. If this parameter is NULL,
477 then the caller is requesting to get the uncommited data
478 from the Form Browser.
480 @retval NULL The uncommitted data could not be retrieved.
481 @retval Other A pointer to a buffer containing the uncommitted data.
486 InternalHiiBrowserCallback (
487 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
488 IN CONST CHAR16
*VariableName
, OPTIONAL
489 IN CONST EFI_STRING SetResultsData OPTIONAL
493 UINTN ResultsDataSize
;
494 EFI_STRING ResultsData
;
495 CHAR16 TempResultsData
;
500 if (mUefiFormBrowser2
== NULL
) {
501 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mUefiFormBrowser2
);
502 if (EFI_ERROR (Status
) || mUefiFormBrowser2
== NULL
) {
509 if (SetResultsData
!= NULL
) {
511 // Request to to set data in the uncommitted browser state information
513 ResultsData
= SetResultsData
;
516 // Retrieve the length of the buffer required ResultsData from the Browser Callback
518 Status
= mUefiFormBrowser2
->BrowserCallback (
527 if (!EFI_ERROR (Status
)) {
529 // No Resluts Data, only allocate one char for '\0'
531 ResultsData
= AllocateZeroPool (sizeof (CHAR16
));
535 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
540 // Allocate the ResultsData buffer
542 ResultsData
= AllocateZeroPool (ResultsDataSize
);
543 if (ResultsData
== NULL
) {
549 // Retrieve or set the ResultsData from the Browser Callback
551 Status
= mUefiFormBrowser2
->BrowserCallback (
555 (BOOLEAN
)(SetResultsData
== NULL
),
559 if (EFI_ERROR (Status
)) {
567 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing
568 information that includes a GUID, an optional Unicode string name, and a device
569 path. The string returned is allocated with AllocatePool(). The caller is
570 responsible for freeing the allocated string with FreePool().
572 The format of a <ConfigHdr> is as follows:
574 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
576 @param[in] Guid Pointer to an EFI_GUID that is the routing information
577 GUID. Each of the 16 bytes in Guid is converted to
578 a 2 Unicode character hexidecimal string. This is
579 an optional parameter that may be NULL.
580 @param[in] Name Pointer to a Null-terminated Unicode string that is
581 the routing information NAME. This is an optional
582 parameter that may be NULL. Each 16-bit Unicode
583 character in Name is converted to a 4 character Unicode
585 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
586 that is the routing information PATH. Each byte of
587 the Device Path associated with DriverHandle is converted
588 to a 2 Unicode character hexidecimal string.
590 @retval NULL DriverHandle does not support the Device Path Protocol.
591 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
596 HiiConstructConfigHdr (
597 IN CONST EFI_GUID
*Guid
, OPTIONAL
598 IN CONST CHAR16
*Name
, OPTIONAL
599 IN EFI_HANDLE DriverHandle
603 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
604 UINTN DevicePathSize
;
606 CHAR16
*ReturnString
;
611 // Compute the length of Name in Unicode characters.
612 // If Name is NULL, then the length is 0.
616 NameLength
= StrLen (Name
);
622 // Retrieve DevicePath Protocol associated with DriverHandle
624 if (DriverHandle
!= NULL
) {
625 DevicePath
= DevicePathFromHandle (DriverHandle
);
626 if (DevicePath
== NULL
) {
630 // Compute the size of the device path in bytes
632 DevicePathSize
= GetDevicePathSize (DevicePath
);
636 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
637 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
639 String
= AllocateZeroPool ((5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
));
640 if (String
== NULL
) {
645 // Start with L"GUID="
647 ReturnString
= StrCpy (String
, L
"GUID=");
648 String
+= StrLen (String
);
652 // Append Guid converted to <HexCh>32
654 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
655 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
662 StrCpy (String
, L
"&NAME=");
663 String
+= StrLen (String
);
667 // Append Name converted to <Char>NameLength
669 for (; *Name
!= L
'\0'; Name
++) {
670 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *Name
, 4);
677 StrCpy (String
, L
"&PATH=");
678 String
+= StrLen (String
);
681 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
683 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
684 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
688 // Null terminate the Unicode string
693 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
695 return InternalHiiLowerConfigString (ReturnString
);
699 Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path
700 to binary buffer from <ConfigHdr>.
702 This is a internal function.
704 @param String UEFI configuration string.
705 @param Flag Flag specifies what type buffer will be retrieved.
706 @param Buffer Binary of Guid, Name or Device path.
708 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
709 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
710 @retval EFI_SUCCESS The buffer data is retrieved and translated to
715 InternalHiiGetBufferFromString (
716 IN EFI_STRING String
,
722 EFI_STRING ConfigHdr
;
729 if (String
== NULL
|| Buffer
== NULL
) {
730 return EFI_INVALID_PARAMETER
;
737 // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element
738 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.
740 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
743 case GUID_CONFIG_STRING_TYPE
:
744 case PATH_CONFIG_STRING_TYPE
:
746 // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order
747 // as the device path and Guid resides in RAM memory.
748 // Translate the data into binary.
750 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
751 if (DataBuffer
== NULL
) {
752 return EFI_OUT_OF_RESOURCES
;
755 // Convert binary byte one by one
757 ZeroMem (TemStr
, sizeof (TemStr
));
758 for (Index
= 0; Index
< Length
; Index
++) {
759 TemStr
[0] = ConfigHdr
[Index
];
760 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
761 if ((Index
& 1) == 0) {
762 DataBuffer
[Index
/2] = DigitUint8
;
764 DataBuffer
[Index
/2] = (UINT8
) ((DataBuffer
[Index
/2] << 4) + DigitUint8
);
768 *Buffer
= DataBuffer
;
771 case NAME_CONFIG_STRING_TYPE
:
773 // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"
777 // Add the tailling char L'\0'
779 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
/4 + 1) * sizeof (CHAR16
));
780 if (DataBuffer
== NULL
) {
781 return EFI_OUT_OF_RESOURCES
;
784 // Convert character one by one
786 StringPtr
= (CHAR16
*) DataBuffer
;
787 ZeroMem (TemStr
, sizeof (TemStr
));
788 for (Index
= 0; Index
< Length
; Index
+= 4) {
789 StrnCpy (TemStr
, ConfigHdr
+ Index
, 4);
790 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
793 // Add tailing L'\0' character
795 StringPtr
[Index
/4] = L
'\0';
797 *Buffer
= DataBuffer
;
801 return EFI_INVALID_PARAMETER
;
808 This function checks VarOffset and VarWidth is in the block range.
810 @param BlockArray The block array is to be checked.
811 @param VarOffset Offset of var to the structure
812 @param VarWidth Width of var.
814 @retval TRUE This Var is in the block range.
815 @retval FALSE This Var is not in the block range.
819 IN IFR_BLOCK_DATA
*BlockArray
,
825 IFR_BLOCK_DATA
*BlockData
;
828 // No Request Block array, all vars are got.
830 if (BlockArray
== NULL
) {
835 // Check the input var is in the request block range.
837 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
838 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
839 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
848 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
850 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
852 @param ValueString String in <BlockConfig> format and points to the
853 first character of <Number>.
854 @param ValueData The output value. Caller takes the responsibility
856 @param ValueLength Length of the <Number>, in characters.
858 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
860 @retval EFI_SUCCESS Value of <Number> is outputted in Number
866 InternalHiiGetValueOfNumber (
867 IN EFI_STRING ValueString
,
868 OUT UINT8
**ValueData
,
869 OUT UINTN
*ValueLength
872 EFI_STRING StringPtr
;
879 ASSERT (ValueString
!= NULL
&& ValueData
!= NULL
&& ValueLength
!= NULL
);
880 ASSERT (*ValueString
!= L
'\0');
883 // Get the length of value string
885 StringPtr
= ValueString
;
886 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
889 Length
= StringPtr
- ValueString
;
892 // Allocate buffer to store the value
894 Buf
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
896 return EFI_OUT_OF_RESOURCES
;
900 // Convert character one by one to the value buffer
902 ZeroMem (TemStr
, sizeof (TemStr
));
903 for (Index
= 0; Index
< Length
; Index
++) {
904 TemStr
[0] = ValueString
[Length
- Index
- 1];
905 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
906 if ((Index
& 1) == 0) {
907 Buf
[Index
/2] = DigitUint8
;
909 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
914 // Set the converted value and string length.
917 *ValueLength
= Length
;
922 Get value from config request resp string.
924 @param ConfigElement ConfigResp string contains the current setting.
925 @param VarName The variable name which need to get value.
926 @param VarValue The return value.
928 @retval EFI_SUCCESS Get the value for the VarName
929 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
932 GetValueFromRequest (
933 IN CHAR16
*ConfigElement
,
944 // Find VarName related string.
946 StringPtr
= StrStr (ConfigElement
, VarName
);
947 ASSERT (StringPtr
!= NULL
);
950 // Skip the "VarName=" string
952 StringPtr
+= StrLen (VarName
) + 1;
957 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
958 if (EFI_ERROR (Status
)) {
963 CopyMem (VarValue
, TmpBuffer
, (((Length
+ 1) / 2) < sizeof (UINT64
)) ? ((Length
+ 1) / 2) : sizeof (UINT64
));
965 FreePool (TmpBuffer
);
971 This internal function parses IFR data to validate current setting.
973 Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;
974 else the VarBuffer and CurrentBlockArray is valid.
976 @param HiiPackageList Point to Hii package list.
977 @param PackageListLength The length of the pacakge.
978 @param VarGuid Guid of the buffer storage.
979 @param VarName Name of the buffer storage.
980 @param VarBuffer The data buffer for the storage.
981 @param CurrentBlockArray The block array from the config Requst string.
982 @param RequestElement The config string for this storage.
983 @param HiiHandle The HiiHandle for this formset.
984 @param NameValueType Whether current storage is name/value varstore or not.
986 @retval EFI_SUCCESS The current setting is valid.
987 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
988 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
991 ValidateQuestionFromVfr (
992 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
993 IN UINTN PackageListLength
,
994 IN EFI_GUID
*VarGuid
,
997 IN IFR_BLOCK_DATA
*CurrentBlockArray
,
998 IN CHAR16
*RequestElement
,
999 IN EFI_HII_HANDLE HiiHandle
,
1000 IN BOOLEAN NameValueType
1003 IFR_BLOCK_DATA VarBlockData
;
1007 EFI_IFR_TYPE_VALUE TmpValue
;
1009 EFI_HII_PACKAGE_HEADER PacakgeHeader
;
1010 UINT32 PackageOffset
;
1013 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1014 EFI_IFR_VARSTORE
*IfrVarStore
;
1015 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueStore
;
1016 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1017 IFR_VARSTORAGE_DATA VarStoreData
;
1018 EFI_IFR_ONE_OF
*IfrOneOf
;
1019 EFI_IFR_NUMERIC
*IfrNumeric
;
1020 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1021 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1022 EFI_IFR_STRING
*IfrString
;
1023 CHAR8
*VarStoreName
;
1025 CHAR16
*QuestionName
;
1029 // Initialize the local variables.
1032 VarStoreName
= NULL
;
1033 Status
= EFI_SUCCESS
;
1036 IfrNameValueStore
= NULL
;
1037 IfrEfiVarStore
= NULL
;
1038 ZeroMem (&VarStoreData
, sizeof (IFR_VARSTORAGE_DATA
));
1039 ZeroMem (&VarBlockData
, sizeof (VarBlockData
));
1042 // Check IFR value is in block data, then Validate Value
1044 PackageOffset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1045 while (PackageOffset
< PackageListLength
) {
1046 CopyMem (&PacakgeHeader
, (UINT8
*) HiiPackageList
+ PackageOffset
, sizeof (PacakgeHeader
));
1049 // Parse IFR opcode from the form package.
1051 if (PacakgeHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1052 IfrOffset
= sizeof (PacakgeHeader
);
1053 PackageData
= (UINT8
*) HiiPackageList
+ PackageOffset
;
1054 while (IfrOffset
< PacakgeHeader
.Length
) {
1055 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (PackageData
+ IfrOffset
);
1057 // Validate current setting to the value built in IFR opcode
1059 switch (IfrOpHdr
->OpCode
) {
1060 case EFI_IFR_VARSTORE_OP
:
1062 // VarStoreId has been found. No further found.
1064 if (VarStoreData
.VarStoreId
!= 0) {
1068 // Find the matched VarStoreId to the input VarGuid and VarName
1070 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1071 if (CompareGuid ((EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
, VarGuid
)) {
1072 VarStoreName
= (CHAR8
*) IfrVarStore
->Name
;
1073 for (Index
= 0; VarStoreName
[Index
] != 0; Index
++) {
1074 if ((CHAR16
) VarStoreName
[Index
] != VarName
[Index
]) {
1079 // The matched VarStore is found.
1081 if ((VarStoreName
[Index
] != 0) || (VarName
[Index
] != 0)) {
1088 if (IfrVarStore
!= NULL
) {
1089 VarStoreData
.VarStoreId
= IfrVarStore
->VarStoreId
;
1090 VarStoreData
.Size
= IfrVarStore
->Size
;
1093 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1095 // VarStoreId has been found. No further found.
1097 if (VarStoreData
.VarStoreId
!= 0) {
1101 // Find the matched VarStoreId to the input VarGuid
1103 IfrNameValueStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1104 if (!CompareGuid ((EFI_GUID
*) (VOID
*) &IfrNameValueStore
->Guid
, VarGuid
)) {
1105 IfrNameValueStore
= NULL
;
1108 if (IfrNameValueStore
!= NULL
) {
1109 VarStoreData
.VarStoreId
= IfrNameValueStore
->VarStoreId
;
1112 case EFI_IFR_VARSTORE_EFI_OP
:
1114 // VarStore is found. Don't need to search any more.
1116 if (VarStoreData
.VarStoreId
!= 0) {
1120 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1123 // If the length is small than the structure, this is from old efi
1124 // varstore definition. Old efi varstore get config directly from
1125 // GetVariable function.
1127 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1131 if (CompareGuid ((EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
, VarGuid
)) {
1132 VarStoreName
= (CHAR8
*) IfrEfiVarStore
->Name
;
1133 for (Index
= 0; VarStoreName
[Index
] != 0; Index
++) {
1134 if ((CHAR16
) VarStoreName
[Index
] != VarName
[Index
]) {
1139 // The matched VarStore is found.
1141 if ((VarStoreName
[Index
] != 0) || (VarName
[Index
] != 0)) {
1142 IfrEfiVarStore
= NULL
;
1145 IfrEfiVarStore
= NULL
;
1148 if (IfrEfiVarStore
!= NULL
) {
1150 // Find the matched VarStore
1152 VarStoreData
.VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1153 VarStoreData
.Size
= IfrEfiVarStore
->Size
;
1156 case EFI_IFR_FORM_OP
:
1157 case EFI_IFR_FORM_MAP_OP
:
1159 // Check the matched VarStoreId is found.
1161 if (VarStoreData
.VarStoreId
== 0) {
1165 case EFI_IFR_ONE_OF_OP
:
1167 // Check whether current value is the one of option.
1171 // OneOf question is not in IFR Form. This IFR form is not valid.
1173 if (VarStoreData
.VarStoreId
== 0) {
1174 return EFI_INVALID_PARAMETER
;
1177 // Check whether this question is for the requested varstore.
1179 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1180 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1184 if (NameValueType
) {
1185 QuestionName
= HiiGetString (HiiHandle
, IfrOneOf
->Question
.VarStoreInfo
.VarName
, NULL
);
1186 ASSERT (QuestionName
!= NULL
);
1188 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1190 // This question is not in the current configuration string. Skip it.
1195 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1196 if (EFI_ERROR (Status
)) {
1201 // Get Offset by Question header and Width by DataType Flags
1203 Offset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1204 Width
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1206 // Check whether this question is in current block array.
1208 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1210 // This question is not in the current configuration string. Skip it.
1215 // Check this var question is in the var storage
1217 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1219 // This question exceeds the var store size.
1221 return EFI_INVALID_PARAMETER
;
1225 // Get the current value for oneof opcode
1228 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1231 // Set Block Data, to be checked in the following Oneof option opcode.
1233 VarBlockData
.OpCode
= IfrOpHdr
->OpCode
;
1234 VarBlockData
.Scope
= IfrOpHdr
->Scope
;
1236 case EFI_IFR_NUMERIC_OP
:
1238 // Check the current value is in the numeric range.
1242 // Numeric question is not in IFR Form. This IFR form is not valid.
1244 if (VarStoreData
.VarStoreId
== 0) {
1245 return EFI_INVALID_PARAMETER
;
1248 // Check whether this question is for the requested varstore.
1250 IfrNumeric
= (EFI_IFR_NUMERIC
*) IfrOpHdr
;
1251 if (IfrNumeric
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1255 if (NameValueType
) {
1256 QuestionName
= HiiGetString (HiiHandle
, IfrNumeric
->Question
.VarStoreInfo
.VarName
, NULL
);
1257 ASSERT (QuestionName
!= NULL
);
1259 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1261 // This question is not in the current configuration string. Skip it.
1266 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1267 if (EFI_ERROR (Status
)) {
1272 // Get Offset by Question header and Width by DataType Flags
1274 Offset
= IfrNumeric
->Question
.VarStoreInfo
.VarOffset
;
1275 Width
= (UINT16
) (1 << (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1277 // Check whether this question is in current block array.
1279 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1281 // This question is not in the current configuration string. Skip it.
1286 // Check this var question is in the var storage
1288 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1290 // This question exceeds the var store size.
1292 return EFI_INVALID_PARAMETER
;
1296 // Check the current value is in the numeric range.
1299 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1301 if ((IfrNumeric
->Flags
& EFI_IFR_DISPLAY
) == 0) {
1302 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1303 case EFI_IFR_NUMERIC_SIZE_1
:
1304 if ((INT8
) VarValue
< (INT8
) IfrNumeric
->data
.u8
.MinValue
|| (INT8
) VarValue
> (INT8
) IfrNumeric
->data
.u8
.MaxValue
) {
1306 // Not in the valid range.
1308 return EFI_INVALID_PARAMETER
;
1311 case EFI_IFR_NUMERIC_SIZE_2
:
1312 if ((INT16
) VarValue
< (INT16
) IfrNumeric
->data
.u16
.MinValue
|| (INT16
) VarValue
> (INT16
) IfrNumeric
->data
.u16
.MaxValue
) {
1314 // Not in the valid range.
1316 return EFI_INVALID_PARAMETER
;
1319 case EFI_IFR_NUMERIC_SIZE_4
:
1320 if ((INT32
) VarValue
< (INT32
) IfrNumeric
->data
.u32
.MinValue
|| (INT32
) VarValue
> (INT32
) IfrNumeric
->data
.u32
.MaxValue
) {
1322 // Not in the valid range.
1324 return EFI_INVALID_PARAMETER
;
1327 case EFI_IFR_NUMERIC_SIZE_8
:
1328 if ((INT64
) VarValue
< (INT64
) IfrNumeric
->data
.u64
.MinValue
|| (INT64
) VarValue
> (INT64
) IfrNumeric
->data
.u64
.MaxValue
) {
1330 // Not in the valid range.
1332 return EFI_INVALID_PARAMETER
;
1337 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1338 case EFI_IFR_NUMERIC_SIZE_1
:
1339 if ((UINT8
) VarValue
< IfrNumeric
->data
.u8
.MinValue
|| (UINT8
) VarValue
> IfrNumeric
->data
.u8
.MaxValue
) {
1341 // Not in the valid range.
1343 return EFI_INVALID_PARAMETER
;
1346 case EFI_IFR_NUMERIC_SIZE_2
:
1347 if ((UINT16
) VarValue
< IfrNumeric
->data
.u16
.MinValue
|| (UINT16
) VarValue
> IfrNumeric
->data
.u16
.MaxValue
) {
1349 // Not in the valid range.
1351 return EFI_INVALID_PARAMETER
;
1354 case EFI_IFR_NUMERIC_SIZE_4
:
1355 if ((UINT32
) VarValue
< IfrNumeric
->data
.u32
.MinValue
|| (UINT32
) VarValue
> IfrNumeric
->data
.u32
.MaxValue
) {
1357 // Not in the valid range.
1359 return EFI_INVALID_PARAMETER
;
1362 case EFI_IFR_NUMERIC_SIZE_8
:
1363 if ((UINT64
) VarValue
< IfrNumeric
->data
.u64
.MinValue
|| (UINT64
) VarValue
> IfrNumeric
->data
.u64
.MaxValue
) {
1365 // Not in the valid range.
1367 return EFI_INVALID_PARAMETER
;
1373 case EFI_IFR_CHECKBOX_OP
:
1375 // Check value is BOOLEAN type, only 0 and 1 is valid.
1379 // CheckBox question is not in IFR Form. This IFR form is not valid.
1381 if (VarStoreData
.VarStoreId
== 0) {
1382 return EFI_INVALID_PARAMETER
;
1386 // Check whether this question is for the requested varstore.
1388 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1389 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1393 if (NameValueType
) {
1394 QuestionName
= HiiGetString (HiiHandle
, IfrCheckBox
->Question
.VarStoreInfo
.VarName
, NULL
);
1395 ASSERT (QuestionName
!= NULL
);
1397 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1399 // This question is not in the current configuration string. Skip it.
1404 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1405 if (EFI_ERROR (Status
)) {
1410 // Get Offset by Question header
1412 Offset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1413 Width
= (UINT16
) sizeof (BOOLEAN
);
1415 // Check whether this question is in current block array.
1417 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1419 // This question is not in the current configuration string. Skip it.
1424 // Check this var question is in the var storage
1426 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1428 // This question exceeds the var store size.
1430 return EFI_INVALID_PARAMETER
;
1433 // Check the current value is in the numeric range.
1436 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1439 // Boolean type, only 1 and 0 is valid.
1442 return EFI_INVALID_PARAMETER
;
1445 case EFI_IFR_STRING_OP
:
1447 // Check current string length is less than maxsize
1451 // CheckBox question is not in IFR Form. This IFR form is not valid.
1453 if (VarStoreData
.VarStoreId
== 0) {
1454 return EFI_INVALID_PARAMETER
;
1458 // Check whether this question is for the requested varstore.
1460 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1461 if (IfrString
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1465 // Get Width by OneOf Flags
1467 Width
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1468 if (NameValueType
) {
1469 QuestionName
= HiiGetString (HiiHandle
, IfrString
->Question
.VarStoreInfo
.VarName
, NULL
);
1470 ASSERT (QuestionName
!= NULL
);
1472 StringPtr
= StrStr (RequestElement
, QuestionName
);
1473 if (StringPtr
== NULL
) {
1475 // This question is not in the current configuration string. Skip it.
1486 // Check current string length is less than maxsize
1488 if (StrSize (StringPtr
) > Width
) {
1489 return EFI_INVALID_PARAMETER
;
1493 // Get Offset/Width by Question header and OneOf Flags
1495 Offset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1497 // Check whether this question is in current block array.
1499 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1501 // This question is not in the current configuration string. Skip it.
1506 // Check this var question is in the var storage
1508 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1510 // This question exceeds the var store size.
1512 return EFI_INVALID_PARAMETER
;
1516 // Check current string length is less than maxsize
1518 if (StrSize ((CHAR16
*) (VarBuffer
+ Offset
)) > Width
) {
1519 return EFI_INVALID_PARAMETER
;
1523 case EFI_IFR_ONE_OF_OPTION_OP
:
1525 // Opcode Scope is zero. This one of option is not to be checked.
1527 if (VarBlockData
.Scope
== 0) {
1532 // Only check for OneOf and OrderList opcode
1534 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1535 if (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
) {
1537 // Check current value is the value of one of option.
1539 ASSERT (IfrOneOfOption
->Type
<= EFI_IFR_TYPE_NUM_SIZE_64
);
1540 ZeroMem (&TmpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
1541 CopyMem (&TmpValue
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
1542 if (VarValue
== TmpValue
.u64
) {
1544 // The value is one of option value.
1545 // Set OpCode to Zero, don't need check again.
1547 VarBlockData
.OpCode
= 0;
1551 case EFI_IFR_END_OP
:
1553 // Decrease opcode scope for the validated opcode
1555 if (VarBlockData
.Scope
> 0) {
1556 VarBlockData
.Scope
--;
1560 // OneOf value doesn't belong to one of option value.
1562 if ((VarBlockData
.Scope
== 0) && (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
)) {
1563 return EFI_INVALID_PARAMETER
;
1568 // Increase Scope for the validated opcode
1570 if (VarBlockData
.Scope
> 0) {
1571 VarBlockData
.Scope
= (UINT8
) (VarBlockData
.Scope
+ IfrOpHdr
->Scope
);
1576 // Go to the next opcode
1578 IfrOffset
+= IfrOpHdr
->Length
;
1581 // Only one form is in a package list.
1587 // Go to next package.
1589 PackageOffset
+= PacakgeHeader
.Length
;
1596 This internal function parses IFR data to validate current setting.
1598 @param ConfigElement ConfigResp element string contains the current setting.
1599 @param CurrentBlockArray Current block array.
1600 @param VarBuffer Data buffer for this varstore.
1602 @retval EFI_SUCCESS The current setting is valid.
1603 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1604 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1608 IN CHAR16
*ConfigElement
,
1609 OUT IFR_BLOCK_DATA
**CurrentBlockArray
,
1610 OUT UINT8
**VarBuffer
1613 IFR_BLOCK_DATA
*BlockData
;
1614 IFR_BLOCK_DATA
*NewBlockData
;
1615 EFI_STRING StringPtr
;
1621 UINTN MaxBufferSize
;
1623 IFR_BLOCK_DATA
*BlockArray
;
1627 // Initialize the local variables.
1629 Status
= EFI_SUCCESS
;
1631 NewBlockData
= NULL
;
1634 MaxBufferSize
= HII_LIB_DEFAULT_VARSTORE_SIZE
;
1635 DataBuffer
= AllocateZeroPool (MaxBufferSize
);
1636 if (DataBuffer
== NULL
) {
1637 return EFI_OUT_OF_RESOURCES
;
1643 BlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1644 if (BlockArray
== NULL
) {
1645 Status
= EFI_OUT_OF_RESOURCES
;
1648 InitializeListHead (&BlockArray
->Entry
);
1650 StringPtr
= StrStr (ConfigElement
, L
"&OFFSET=");
1651 ASSERT (StringPtr
!= NULL
);
1654 // Parse each <RequestElement> if exists
1655 // Only <BlockName> format is supported by this help function.
1656 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1658 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1660 // Skip the &OFFSET= string
1662 StringPtr
+= StrLen (L
"&OFFSET=");
1667 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1668 if (EFI_ERROR (Status
)) {
1675 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1677 FreePool (TmpBuffer
);
1680 StringPtr
+= Length
;
1681 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1682 Status
= EFI_INVALID_PARAMETER
;
1685 StringPtr
+= StrLen (L
"&WIDTH=");
1690 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1691 if (EFI_ERROR (Status
)) {
1698 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1700 FreePool (TmpBuffer
);
1703 StringPtr
+= Length
;
1704 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1705 Status
= EFI_INVALID_PARAMETER
;
1709 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1710 Status
= EFI_INVALID_PARAMETER
;
1713 StringPtr
+= StrLen (L
"&VALUE=");
1718 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1719 if (EFI_ERROR (Status
)) {
1723 StringPtr
+= Length
;
1724 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1725 Status
= EFI_INVALID_PARAMETER
;
1730 // Check whether VarBuffer is enough
1732 if ((UINTN
) (Offset
+ Width
) > MaxBufferSize
) {
1733 DataBuffer
= ReallocatePool (
1735 Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
,
1738 if (DataBuffer
== NULL
) {
1739 Status
= EFI_OUT_OF_RESOURCES
;
1742 MaxBufferSize
= Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
;
1746 // Update the Block with configuration info
1748 CopyMem (DataBuffer
+ Offset
, TmpBuffer
, Width
);
1749 FreePool (TmpBuffer
);
1753 // Set new Block Data
1755 NewBlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1756 if (NewBlockData
== NULL
) {
1757 Status
= EFI_OUT_OF_RESOURCES
;
1760 NewBlockData
->Offset
= Offset
;
1761 NewBlockData
->Width
= Width
;
1764 // Insert the new block data into the block data array.
1766 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1767 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1768 if (NewBlockData
->Offset
== BlockData
->Offset
) {
1769 if (NewBlockData
->Width
> BlockData
->Width
) {
1770 BlockData
->Width
= NewBlockData
->Width
;
1772 FreePool (NewBlockData
);
1774 } else if (NewBlockData
->Offset
< BlockData
->Offset
) {
1776 // Insert new block data as the previous one of this link.
1778 InsertTailList (Link
, &NewBlockData
->Entry
);
1784 // Insert new block data into the array tail.
1786 if (Link
== &BlockArray
->Entry
) {
1787 InsertTailList (Link
, &NewBlockData
->Entry
);
1791 // If '\0', parsing is finished.
1793 if (*StringPtr
== 0) {
1797 // Go to next ConfigBlock
1802 // Merge the aligned block data into the single block data.
1804 Link
= BlockArray
->Entry
.ForwardLink
;
1805 while ((Link
!= &BlockArray
->Entry
) && (Link
->ForwardLink
!= &BlockArray
->Entry
)) {
1806 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1807 NewBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1808 if ((NewBlockData
->Offset
>= BlockData
->Offset
) && (NewBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1809 if ((NewBlockData
->Offset
+ NewBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1810 BlockData
->Width
= (UINT16
) (NewBlockData
->Offset
+ NewBlockData
->Width
- BlockData
->Offset
);
1812 RemoveEntryList (Link
->ForwardLink
);
1813 FreePool (NewBlockData
);
1816 Link
= Link
->ForwardLink
;
1819 *VarBuffer
= DataBuffer
;
1820 *CurrentBlockArray
= BlockArray
;
1824 if (DataBuffer
!= NULL
) {
1825 FreePool (DataBuffer
);
1828 if (BlockArray
!= NULL
) {
1830 // Free Link Array CurrentBlockArray
1832 while (!IsListEmpty (&BlockArray
->Entry
)) {
1833 BlockData
= BASE_CR (BlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1834 RemoveEntryList (&BlockData
->Entry
);
1835 FreePool (BlockData
);
1837 FreePool (BlockArray
);
1844 This internal function parses IFR data to validate current setting.
1846 @param ConfigResp ConfigResp string contains the current setting.
1847 @param HiiPackageList Point to Hii package list.
1848 @param PackageListLength The length of the pacakge.
1849 @param VarGuid Guid of the buffer storage.
1850 @param VarName Name of the buffer storage.
1851 @param HiiHandle The HiiHandle for this package.
1853 @retval EFI_SUCCESS The current setting is valid.
1854 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1855 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1859 InternalHiiValidateCurrentSetting (
1860 IN EFI_STRING ConfigResp
,
1861 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
1862 IN UINTN PackageListLength
,
1863 IN EFI_GUID
*VarGuid
,
1865 IN EFI_HII_HANDLE HiiHandle
1870 IFR_BLOCK_DATA
*CurrentBlockArray
;
1871 IFR_BLOCK_DATA
*BlockData
;
1873 BOOLEAN NameValueType
;
1875 CurrentBlockArray
= NULL
;
1878 Status
= EFI_SUCCESS
;
1881 // If StringPtr != NULL, get the request elements.
1883 if (StrStr (ConfigResp
, L
"&OFFSET=") != NULL
) {
1884 Status
= GetBlockDataInfo(ConfigResp
, &CurrentBlockArray
, &VarBuffer
);
1885 if (EFI_ERROR (Status
)) {
1888 NameValueType
= FALSE
;
1891 // Skip header part.
1893 StringPtr
= StrStr (ConfigResp
, L
"PATH=");
1894 ASSERT (StringPtr
!= NULL
);
1896 if (StrStr (StringPtr
, L
"&") != NULL
) {
1897 NameValueType
= TRUE
;
1900 // Not found Request element, return success.
1906 Status
= ValidateQuestionFromVfr(
1918 if (VarBuffer
!= NULL
) {
1919 FreePool (VarBuffer
);
1922 if (CurrentBlockArray
!= NULL
) {
1924 // Free Link Array CurrentBlockArray
1926 while (!IsListEmpty (&CurrentBlockArray
->Entry
)) {
1927 BlockData
= BASE_CR (CurrentBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1928 RemoveEntryList (&BlockData
->Entry
);
1929 FreePool (BlockData
);
1931 FreePool (CurrentBlockArray
);
1938 Check whether the ConfigRequest string has the request elements.
1939 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1940 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1942 @param ConfigRequest The input config request string.
1944 @retval TRUE The input include config request elements.
1945 @retval FALSE The input string not includes.
1949 GetElementsFromRequest (
1950 IN EFI_STRING ConfigRequest
1953 EFI_STRING TmpRequest
;
1955 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1956 ASSERT (TmpRequest
!= NULL
);
1958 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1966 This function parses the input ConfigRequest string and its matched IFR code
1967 string for setting default value and validating current setting.
1969 1. For setting default action, Reset the default value specified by DefaultId
1970 to the driver configuration got by Request string.
1971 2. For validating current setting, Validate the current configuration
1972 by parsing HII form IFR opcode.
1974 NULL request string support depends on the ExportConfig interface of
1975 HiiConfigRouting protocol in UEFI specification.
1977 @param Request A null-terminated Unicode string in
1978 <MultiConfigRequest> format. It can be NULL.
1979 If it is NULL, all current configuration for the
1980 entirety of the current HII database will be validated.
1981 If it is NULL, all configuration for the
1982 entirety of the current HII database will be reset.
1983 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.
1984 @param ActionType Action supports setting defaults and validate current setting.
1986 @retval TURE Action runs successfully.
1987 @retval FALSE Action is not valid or Action can't be executed successfully..
1991 InternalHiiIfrValueAction (
1992 IN CONST EFI_STRING Request
, OPTIONAL
1993 IN UINT16 DefaultId
,
1997 EFI_STRING ConfigAltResp
;
1998 EFI_STRING ConfigAltHdr
;
1999 EFI_STRING ConfigResp
;
2000 EFI_STRING Progress
;
2001 EFI_STRING StringPtr
;
2002 EFI_STRING StringHdr
;
2004 EFI_HANDLE DriverHandle
;
2005 EFI_HANDLE TempDriverHandle
;
2006 EFI_HII_HANDLE
*HiiHandleBuffer
;
2007 EFI_HII_HANDLE HiiHandle
;
2012 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
2013 UINTN PackageListLength
;
2014 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2015 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2017 ConfigAltResp
= NULL
;
2022 ConfigAltHdr
= NULL
;
2023 HiiHandleBuffer
= NULL
;
2025 TempDriverHandle
= NULL
;
2027 HiiPackageList
= NULL
;
2030 // Only support set default and validate setting action.
2032 if ((ActionType
!= ACTION_SET_DEFAUTL_VALUE
) && (ActionType
!= ACTION_VALIDATE_SETTING
)) {
2037 // Get the full requested value and deault value string.
2039 if (Request
!= NULL
) {
2040 Status
= gHiiConfigRouting
->ExtractConfig (
2047 Status
= gHiiConfigRouting
->ExportConfig (
2053 if (EFI_ERROR (Status
)) {
2057 StringPtr
= ConfigAltResp
;
2059 while (StringPtr
!= L
'\0') {
2061 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
2063 StringHdr
= StringPtr
;
2068 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2069 Status
= EFI_INVALID_PARAMETER
;
2072 StringPtr
+= StrLen (L
"GUID=");
2073 Status
= InternalHiiGetBufferFromString (StringPtr
, GUID_CONFIG_STRING_TYPE
, (UINT8
**) &VarGuid
);
2074 if (EFI_ERROR (Status
)) {
2079 // Get Name value VarName
2081 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2084 if (*StringPtr
== L
'\0') {
2085 Status
= EFI_INVALID_PARAMETER
;
2088 StringPtr
+= StrLen (L
"&NAME=");
2089 Status
= InternalHiiGetBufferFromString (StringPtr
, NAME_CONFIG_STRING_TYPE
, (UINT8
**) &VarName
);
2090 if (EFI_ERROR (Status
)) {
2095 // Get Path value DevicePath
2097 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2100 if (*StringPtr
== L
'\0') {
2101 Status
= EFI_INVALID_PARAMETER
;
2104 StringPtr
+= StrLen (L
"&PATH=");
2105 Status
= InternalHiiGetBufferFromString (StringPtr
, PATH_CONFIG_STRING_TYPE
, (UINT8
**) &DevicePath
);
2106 if (EFI_ERROR (Status
)) {
2111 // Get the Driver handle by the got device path.
2113 TempDevicePath
= DevicePath
;
2114 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDevicePath
, &DriverHandle
);
2115 if (EFI_ERROR (Status
)) {
2120 // Find the matched Hii Handle for the found Driver handle
2122 HiiHandleBuffer
= HiiGetHiiHandles (NULL
);
2123 if (HiiHandleBuffer
== NULL
) {
2124 Status
= EFI_NOT_FOUND
;
2128 for (Index
= 0; HiiHandleBuffer
[Index
] != NULL
; Index
++) {
2129 gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, HiiHandleBuffer
[Index
], &TempDriverHandle
);
2130 if (TempDriverHandle
== DriverHandle
) {
2135 HiiHandle
= HiiHandleBuffer
[Index
];
2136 FreePool (HiiHandleBuffer
);
2138 if (HiiHandle
== NULL
) {
2140 // This request string has no its Hii package.
2141 // Its default value and validating can't execute by parsing IFR data.
2142 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
2144 Status
= EFI_SUCCESS
;
2145 goto NextConfigAltResp
;
2149 // 2. Get HiiPackage by HiiHandle
2151 PackageListLength
= 0;
2152 HiiPackageList
= NULL
;
2153 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2156 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
2158 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2159 Status
= EFI_INVALID_PARAMETER
;
2163 HiiPackageList
= AllocatePool (PackageListLength
);
2164 if (HiiPackageList
== NULL
) {
2165 Status
= EFI_OUT_OF_RESOURCES
;
2170 // Get PackageList on HiiHandle
2172 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2173 if (EFI_ERROR (Status
)) {
2178 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2179 // Get the default configuration string according to the default ID.
2181 Status
= gHiiConfigRouting
->GetAltConfig (
2187 (ActionType
== ACTION_SET_DEFAUTL_VALUE
) ? &DefaultId
:NULL
, // it can be NULL to get the current setting.
2192 // The required setting can't be found. So, it is not required to be validated and set.
2194 if (EFI_ERROR (Status
)) {
2195 Status
= EFI_SUCCESS
;
2196 goto NextConfigAltResp
;
2199 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
2201 if (!GetElementsFromRequest (ConfigResp
)) {
2202 goto NextConfigAltResp
;
2206 // 4. Set the default configuration information or Validate current setting by parse IFR code.
2207 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2209 if (ActionType
== ACTION_SET_DEFAUTL_VALUE
) {
2211 // Set the default configuration information.
2213 Status
= gHiiConfigRouting
->RouteConfig (gHiiConfigRouting
, ConfigResp
, &Progress
);
2216 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2218 Status
= InternalHiiValidateCurrentSetting (ConfigResp
, HiiPackageList
, PackageListLength
, VarGuid
, VarName
, HiiHandle
);
2221 if (EFI_ERROR (Status
)) {
2227 // Free the allocated pacakge buffer and the got ConfigResp string.
2229 if (HiiPackageList
!= NULL
) {
2230 FreePool (HiiPackageList
);
2231 HiiPackageList
= NULL
;
2234 if (ConfigResp
!= NULL
) {
2235 FreePool (ConfigResp
);
2240 // Free the allocated buffer.
2248 FreePool (DevicePath
);
2252 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
2256 // Get and Skip ConfigHdr
2258 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2261 if (*StringPtr
== L
'\0') {
2266 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"
2267 // | 1 | StrLen (ConfigHdr) | 8 | 1 |
2269 ConfigAltHdr
= AllocateZeroPool ((1 + StringPtr
- StringHdr
+ 8 + 1) * sizeof (CHAR16
));
2270 if (ConfigAltHdr
== NULL
) {
2271 Status
= EFI_OUT_OF_RESOURCES
;
2274 StrCpy (ConfigAltHdr
, L
"&");
2275 StrnCat (ConfigAltHdr
, StringHdr
, StringPtr
- StringHdr
);
2276 StrCat (ConfigAltHdr
, L
"&ALTCFG=");
2279 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
2281 while ((StringHdr
= StrStr (StringPtr
, ConfigAltHdr
)) != NULL
) {
2282 StringPtr
= StringHdr
+ StrLen (ConfigAltHdr
);
2283 if (*StringPtr
== L
'\0') {
2289 // Free the allocated ConfigAltHdr string
2291 FreePool (ConfigAltHdr
);
2292 if (*StringPtr
== L
'\0') {
2297 // Find &GUID as the next ConfigHdr
2299 StringPtr
= StrStr (StringPtr
, L
"&GUID");
2300 if (StringPtr
== NULL
) {
2311 if (VarGuid
!= NULL
) {
2315 if (VarName
!= NULL
) {
2319 if (DevicePath
!= NULL
) {
2320 FreePool (DevicePath
);
2323 if (ConfigResp
!= NULL
) {
2324 FreePool (ConfigResp
);
2327 if (ConfigAltResp
!= NULL
) {
2328 FreePool (ConfigAltResp
);
2331 if (HiiPackageList
!= NULL
) {
2332 FreePool (HiiPackageList
);
2335 if (EFI_ERROR (Status
)) {
2343 Validate the current configuration by parsing HII form IFR opcode.
2345 NULL request string support depends on the ExportConfig interface of
2346 HiiConfigRouting protocol in UEFI specification.
2348 @param Request A null-terminated Unicode string in
2349 <MultiConfigRequest> format. It can be NULL.
2350 If it is NULL, all current configuration for the
2351 entirety of the current HII database will be validated.
2353 @retval TRUE Current configuration is valid.
2354 @retval FALSE Current configuration is invalid.
2358 HiiValidateSettings (
2359 IN CONST EFI_STRING Request OPTIONAL
2362 return InternalHiiIfrValueAction (Request
, 0, ACTION_VALIDATE_SETTING
);
2366 Reset the default value specified by DefaultId to the driver
2367 configuration got by Request string.
2369 NULL request string support depends on the ExportConfig interface of
2370 HiiConfigRouting protocol in UEFI specification.
2372 @param Request A null-terminated Unicode string in
2373 <MultiConfigRequest> format. It can be NULL.
2374 If it is NULL, all configuration for the
2375 entirety of the current HII database will be reset.
2376 @param DefaultId Specifies the type of defaults to retrieve.
2378 @retval TURE The default value is set successfully.
2379 @retval FALSE The default value can't be found and set.
2384 IN CONST EFI_STRING Request
, OPTIONAL
2388 return InternalHiiIfrValueAction (Request
, DefaultId
, ACTION_SET_DEFAUTL_VALUE
);
2392 Determines if two values in config strings match.
2394 Compares the substring between StartSearchString and StopSearchString in
2395 FirstString to the substring between StartSearchString and StopSearchString
2396 in SecondString. If the two substrings match, then TRUE is returned. If the
2397 two substrings do not match, then FALSE is returned.
2399 If FirstString is NULL, then ASSERT().
2400 If SecondString is NULL, then ASSERT().
2401 If StartSearchString is NULL, then ASSERT().
2402 If StopSearchString is NULL, then ASSERT().
2404 @param FirstString Pointer to the first Null-terminated Unicode string.
2405 @param SecondString Pointer to the second Null-terminated Unicode string.
2406 @param StartSearchString Pointer to the Null-terminated Unicode string that
2407 marks the start of the value string to compare.
2408 @param StopSearchString Pointer to the Null-terminated Unicode string that
2409 marks the end of the value string to compare.
2411 @retval FALSE StartSearchString is not present in FirstString.
2412 @retval FALSE StartSearchString is not present in SecondString.
2413 @retval FALSE StopSearchString is not present in FirstString.
2414 @retval FALSE StopSearchString is not present in SecondString.
2415 @retval FALSE The length of the substring in FirstString is not the
2416 same length as the substring in SecondString.
2417 @retval FALSE The value string in FirstString does not matche the
2418 value string in SecondString.
2419 @retval TRUE The value string in FirstString matches the value
2420 string in SecondString.
2425 InternalHiiCompareSubString (
2426 IN CHAR16
*FirstString
,
2427 IN CHAR16
*SecondString
,
2428 IN CHAR16
*StartSearchString
,
2429 IN CHAR16
*StopSearchString
2432 CHAR16
*EndFirstString
;
2433 CHAR16
*EndSecondString
;
2435 ASSERT (FirstString
!= NULL
);
2436 ASSERT (SecondString
!= NULL
);
2437 ASSERT (StartSearchString
!= NULL
);
2438 ASSERT (StopSearchString
!= NULL
);
2440 FirstString
= StrStr (FirstString
, StartSearchString
);
2441 if (FirstString
== NULL
) {
2445 SecondString
= StrStr (SecondString
, StartSearchString
);
2446 if (SecondString
== NULL
) {
2450 EndFirstString
= StrStr (FirstString
, StopSearchString
);
2451 if (EndFirstString
== NULL
) {
2455 EndSecondString
= StrStr (SecondString
, StopSearchString
);
2456 if (EndSecondString
== NULL
) {
2460 if ((EndFirstString
- FirstString
) != (EndSecondString
- SecondString
)) {
2464 return (BOOLEAN
)(StrnCmp (FirstString
, SecondString
, EndFirstString
- FirstString
) == 0);
2468 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
2470 If ConfigHdr is NULL, then ASSERT().
2472 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
2473 @param[in] Guid GUID of the storage.
2474 @param[in] Name NAME of the storage.
2476 @retval TRUE Routing information matches <ConfigHdr>.
2477 @retval FALSE Routing information does not match <ConfigHdr>.
2482 HiiIsConfigHdrMatch (
2483 IN CONST EFI_STRING ConfigHdr
,
2484 IN CONST EFI_GUID
*Guid
, OPTIONAL
2485 IN CONST CHAR16
*Name OPTIONAL
2488 EFI_STRING CompareConfigHdr
;
2491 ASSERT (ConfigHdr
!= NULL
);
2494 // Use Guid and Name to generate a <ConfigHdr> string
2496 CompareConfigHdr
= HiiConstructConfigHdr (Guid
, Name
, NULL
);
2497 if (CompareConfigHdr
== NULL
) {
2504 // Compare GUID value strings
2506 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"GUID=", L
"&NAME=");
2509 if (Result
&& Name
!= NULL
) {
2511 // Compare NAME value strings
2513 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"&NAME=", L
"&PATH=");
2517 // Free the <ConfigHdr> string
2519 FreePool (CompareConfigHdr
);
2525 Retrieves uncommitted data from the Form Browser and converts it to a binary
2528 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2529 parameter that may be NULL.
2530 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2531 is an optional parameter that may be NULL.
2532 @param[in] BufferSize Length in bytes of buffer to hold retrieved data.
2533 @param[out] Buffer Buffer of data to be updated.
2535 @retval FALSE The uncommitted data could not be retrieved.
2536 @retval TRUE The uncommitted data was retrieved.
2542 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2543 IN CONST CHAR16
*VariableName
, OPTIONAL
2544 IN UINTN BufferSize
,
2548 EFI_STRING ResultsData
;
2550 EFI_STRING ConfigResp
;
2555 // Retrieve the results data from the Browser Callback
2557 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, NULL
);
2558 if (ResultsData
== NULL
) {
2563 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
2565 Size
= (StrLen (mConfigHdrTemplate
) + 1) * sizeof (CHAR16
);
2566 Size
= Size
+ (StrLen (ResultsData
) + 1) * sizeof (CHAR16
);
2567 ConfigResp
= AllocateZeroPool (Size
);
2568 UnicodeSPrint (ConfigResp
, Size
, L
"%s&%s", mConfigHdrTemplate
, ResultsData
);
2571 // Free the allocated buffer
2573 FreePool (ResultsData
);
2574 if (ConfigResp
== NULL
) {
2579 // Convert <ConfigResp> to a buffer
2581 Status
= gHiiConfigRouting
->ConfigToBlock (
2589 // Free the allocated buffer
2591 FreePool (ConfigResp
);
2593 if (EFI_ERROR (Status
)) {
2601 Updates uncommitted data in the Form Browser.
2603 If Buffer is NULL, then ASSERT().
2605 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2606 parameter that may be NULL.
2607 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2608 is an optional parameter that may be NULL.
2609 @param[in] BufferSize Length, in bytes, of Buffer.
2610 @param[in] Buffer Buffer of data to commit.
2611 @param[in] RequestElement An optional field to specify which part of the
2612 buffer data will be send back to Browser. If NULL,
2613 the whole buffer of data will be committed to
2615 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
2617 @retval FALSE The uncommitted data could not be updated.
2618 @retval TRUE The uncommitted data was updated.
2624 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2625 IN CONST CHAR16
*VariableName
, OPTIONAL
2626 IN UINTN BufferSize
,
2627 IN CONST UINT8
*Buffer
,
2628 IN CONST CHAR16
*RequestElement OPTIONAL
2632 EFI_STRING ConfigRequest
;
2633 EFI_STRING ConfigResp
;
2634 EFI_STRING ResultsData
;
2636 ASSERT (Buffer
!= NULL
);
2639 // Construct <ConfigRequest>
2641 if (RequestElement
== NULL
) {
2643 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2644 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2646 Size
= (StrLen (mConfigHdrTemplate
) + 32 + 1) * sizeof (CHAR16
);
2647 ConfigRequest
= AllocateZeroPool (Size
);
2648 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate
, (UINT64
)BufferSize
);
2651 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2652 // followed by <RequestElement> followed by a Null-terminator
2654 Size
= StrLen (mConfigHdrTemplate
) * sizeof (CHAR16
);
2655 Size
= Size
+ (StrLen (RequestElement
) + 1) * sizeof (CHAR16
);
2656 ConfigRequest
= AllocateZeroPool (Size
);
2657 UnicodeSPrint (ConfigRequest
, Size
, L
"%s%s", mConfigHdrTemplate
, RequestElement
);
2659 if (ConfigRequest
== NULL
) {
2664 // Convert <ConfigRequest> to <ConfigResp>
2666 ConfigResp
= InternalHiiBlockToConfig (ConfigRequest
, Buffer
, BufferSize
);
2667 FreePool (ConfigRequest
);
2668 if (ConfigResp
== NULL
) {
2673 // Set data in the uncommitted browser state information
2675 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, ConfigResp
+ StrLen(mConfigHdrTemplate
) + 1);
2676 FreePool (ConfigResp
);
2678 return (BOOLEAN
)(ResultsData
!= NULL
);
2681 /////////////////////////////////////////
2682 /////////////////////////////////////////
2684 /////////////////////////////////////////
2685 /////////////////////////////////////////
2687 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
2693 } HII_LIB_OPCODE_BUFFER
;
2696 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
2698 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth
[] = {
2699 1, // EFI_IFR_TYPE_NUM_SIZE_8
2700 2, // EFI_IFR_TYPE_NUM_SIZE_16
2701 4, // EFI_IFR_TYPE_NUM_SIZE_32
2702 8, // EFI_IFR_TYPE_NUM_SIZE_64
2703 1, // EFI_IFR_TYPE_BOOLEAN
2704 3, // EFI_IFR_TYPE_TIME
2705 4, // EFI_IFR_TYPE_DATE
2706 2 // EFI_IFR_TYPE_STRING
2710 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
2711 HiiFreeOpCodeHandle().
2713 @retval NULL There are not enough resources to allocate a new OpCode Handle.
2714 @retval Other A new OpCode handle.
2719 HiiAllocateOpCodeHandle (
2723 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2725 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER
));
2726 if (OpCodeBuffer
== NULL
) {
2729 OpCodeBuffer
->Buffer
= (UINT8
*)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE
);
2730 if (OpCodeBuffer
->Buffer
== NULL
) {
2731 FreePool (OpCodeBuffer
);
2734 OpCodeBuffer
->BufferSize
= HII_LIB_OPCODE_ALLOCATION_SIZE
;
2735 OpCodeBuffer
->Position
= 0;
2736 return (VOID
*)OpCodeBuffer
;
2740 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
2741 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
2742 Handle are also freed.
2744 If OpCodeHandle is NULL, then ASSERT().
2746 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2751 HiiFreeOpCodeHandle (
2755 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2757 ASSERT (OpCodeHandle
!= NULL
);
2759 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2760 if (OpCodeBuffer
->Buffer
!= NULL
) {
2761 FreePool (OpCodeBuffer
->Buffer
);
2763 FreePool (OpCodeBuffer
);
2767 Internal function gets the current position of opcode buffer.
2769 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2771 @return Current position of opcode buffer.
2775 InternalHiiOpCodeHandlePosition (
2776 IN VOID
*OpCodeHandle
2779 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Position
;
2783 Internal function gets the start pointer of opcode buffer.
2785 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2787 @return Pointer to the opcode buffer base.
2791 InternalHiiOpCodeHandleBuffer (
2792 IN VOID
*OpCodeHandle
2795 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Buffer
;
2799 Internal function reserves the enough buffer for current opcode.
2800 When the buffer is not enough, Opcode buffer will be extended.
2802 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2803 @param[in] Size Size of current opcode.
2805 @return Pointer to the current opcode.
2809 InternalHiiGrowOpCodeHandle (
2810 IN VOID
*OpCodeHandle
,
2814 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2817 ASSERT (OpCodeHandle
!= NULL
);
2819 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2820 if (OpCodeBuffer
->Position
+ Size
> OpCodeBuffer
->BufferSize
) {
2821 Buffer
= ReallocatePool (
2822 OpCodeBuffer
->BufferSize
,
2823 OpCodeBuffer
->BufferSize
+ (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
),
2824 OpCodeBuffer
->Buffer
2826 ASSERT (Buffer
!= NULL
);
2827 OpCodeBuffer
->Buffer
= Buffer
;
2828 OpCodeBuffer
->BufferSize
+= (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
);
2830 Buffer
= OpCodeBuffer
->Buffer
+ OpCodeBuffer
->Position
;
2831 OpCodeBuffer
->Position
+= Size
;
2836 Internal function creates opcode based on the template opcode.
2838 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2839 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2840 @param[in] OpCode OpCode IFR value.
2841 @param[in] OpCodeSize Size of opcode.
2842 @param[in] ExtensionSize Size of extended opcode.
2843 @param[in] Scope Scope bit of opcode.
2845 @return Pointer to the current opcode with opcode data.
2849 InternalHiiCreateOpCodeExtended (
2850 IN VOID
*OpCodeHandle
,
2851 IN VOID
*OpCodeTemplate
,
2853 IN UINTN OpCodeSize
,
2854 IN UINTN ExtensionSize
,
2858 EFI_IFR_OP_HEADER
*Header
;
2861 ASSERT (OpCodeTemplate
!= NULL
);
2862 ASSERT ((OpCodeSize
+ ExtensionSize
) <= 0x7F);
2864 Header
= (EFI_IFR_OP_HEADER
*)OpCodeTemplate
;
2865 Header
->OpCode
= OpCode
;
2866 Header
->Scope
= Scope
;
2867 Header
->Length
= (UINT8
)(OpCodeSize
+ ExtensionSize
);
2868 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, Header
->Length
);
2869 return (UINT8
*)CopyMem (Buffer
, Header
, OpCodeSize
);
2873 Internal function creates opcode based on the template opcode for the normal opcode.
2875 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2876 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2877 @param[in] OpCode OpCode IFR value.
2878 @param[in] OpCodeSize Size of opcode.
2880 @return Pointer to the current opcode with opcode data.
2884 InternalHiiCreateOpCode (
2885 IN VOID
*OpCodeHandle
,
2886 IN VOID
*OpCodeTemplate
,
2891 return InternalHiiCreateOpCodeExtended (OpCodeHandle
, OpCodeTemplate
, OpCode
, OpCodeSize
, 0, 0);
2895 Append raw opcodes to an OpCodeHandle.
2897 If OpCodeHandle is NULL, then ASSERT().
2898 If RawBuffer is NULL, then ASSERT();
2900 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2901 @param[in] RawBuffer Buffer of opcodes to append.
2902 @param[in] RawBufferSize The size, in bytes, of Buffer.
2904 @retval NULL There is not enough space left in Buffer to add the opcode.
2905 @retval Other A pointer to the appended opcodes.
2910 HiiCreateRawOpCodes (
2911 IN VOID
*OpCodeHandle
,
2912 IN UINT8
*RawBuffer
,
2913 IN UINTN RawBufferSize
2918 ASSERT (RawBuffer
!= NULL
);
2920 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, RawBufferSize
);
2921 return (UINT8
*)CopyMem (Buffer
, RawBuffer
, RawBufferSize
);
2925 Append opcodes from one OpCode Handle to another OpCode handle.
2927 If OpCodeHandle is NULL, then ASSERT().
2928 If RawOpCodeHandle is NULL, then ASSERT();
2930 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2931 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
2933 @retval NULL There is not enough space left in Buffer to add the opcode.
2934 @retval Other A pointer to the appended opcodes.
2939 InternalHiiAppendOpCodes (
2940 IN VOID
*OpCodeHandle
,
2941 IN VOID
*RawOpCodeHandle
2944 HII_LIB_OPCODE_BUFFER
*RawOpCodeBuffer
;
2946 ASSERT (RawOpCodeHandle
!= NULL
);
2948 RawOpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)RawOpCodeHandle
;
2949 return HiiCreateRawOpCodes (OpCodeHandle
, RawOpCodeBuffer
->Buffer
, RawOpCodeBuffer
->Position
);
2953 Create EFI_IFR_END_OP opcode.
2955 If OpCodeHandle is NULL, then ASSERT().
2957 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2959 @retval NULL There is not enough space left in Buffer to add the opcode.
2960 @retval Other A pointer to the created opcode.
2965 HiiCreateEndOpCode (
2966 IN VOID
*OpCodeHandle
2971 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_END_OP
, sizeof (OpCode
));
2975 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
2977 If OpCodeHandle is NULL, then ASSERT().
2978 If Type is invalid, then ASSERT().
2979 If Flags is invalid, then ASSERT().
2981 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2982 @param[in] StringId StringId for the option
2983 @param[in] Flags Flags for the option
2984 @param[in] Type Type for the option
2985 @param[in] Value Value for the option
2987 @retval NULL There is not enough space left in Buffer to add the opcode.
2988 @retval Other A pointer to the created opcode.
2993 HiiCreateOneOfOptionOpCode (
2994 IN VOID
*OpCodeHandle
,
3001 EFI_IFR_ONE_OF_OPTION OpCode
;
3003 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
3005 ZeroMem (&OpCode
, sizeof (OpCode
));
3006 OpCode
.Option
= StringId
;
3007 OpCode
.Flags
= (UINT8
) (Flags
& (EFI_IFR_OPTION_DEFAULT
| EFI_IFR_OPTION_DEFAULT_MFG
));
3009 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
3011 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OPTION_OP
, OFFSET_OF(EFI_IFR_ONE_OF_OPTION
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
3015 Create EFI_IFR_DEFAULT_OP opcode.
3017 If OpCodeHandle is NULL, then ASSERT().
3018 If Type is invalid, then ASSERT().
3020 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3021 @param[in] DefaultId DefaultId for the default
3022 @param[in] Type Type for the default
3023 @param[in] Value Value for the default
3025 @retval NULL There is not enough space left in Buffer to add the opcode.
3026 @retval Other A pointer to the created opcode.
3031 HiiCreateDefaultOpCode (
3032 IN VOID
*OpCodeHandle
,
3033 IN UINT16 DefaultId
,
3038 EFI_IFR_DEFAULT OpCode
;
3040 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
3042 ZeroMem (&OpCode
, sizeof (OpCode
));
3044 OpCode
.DefaultId
= DefaultId
;
3045 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
3047 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DEFAULT_OP
, OFFSET_OF(EFI_IFR_DEFAULT
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
3051 Create EFI_IFR_GUID opcode.
3053 If OpCodeHandle is NULL, then ASSERT().
3054 If Guid is NULL, then ASSERT().
3055 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
3057 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3058 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
3059 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
3060 optional parameter that may be NULL. If this
3061 parameter is NULL, then the GUID extension
3062 region of the created opcode is filled with zeros.
3063 If this parameter is not NULL, then the GUID
3064 extension region of GuidData will be copied to
3065 the GUID extension region of the created opcode.
3066 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
3067 must be >= sizeof(EFI_IFR_GUID).
3069 @retval NULL There is not enough space left in Buffer to add the opcode.
3070 @retval Other A pointer to the created opcode.
3075 HiiCreateGuidOpCode (
3076 IN VOID
*OpCodeHandle
,
3077 IN CONST EFI_GUID
*Guid
,
3078 IN CONST VOID
*GuidOpCode
, OPTIONAL
3082 EFI_IFR_GUID OpCode
;
3083 EFI_IFR_GUID
*OpCodePointer
;
3085 ASSERT (Guid
!= NULL
);
3086 ASSERT (OpCodeSize
>= sizeof (OpCode
));
3088 ZeroMem (&OpCode
, sizeof (OpCode
));
3089 CopyGuid ((EFI_GUID
*)(VOID
*)&OpCode
.Guid
, Guid
);
3091 OpCodePointer
= (EFI_IFR_GUID
*)InternalHiiCreateOpCodeExtended (
3096 OpCodeSize
- sizeof (OpCode
),
3099 if (OpCodePointer
!= NULL
&& GuidOpCode
!= NULL
) {
3100 CopyMem (OpCodePointer
+ 1, (EFI_IFR_GUID
*)GuidOpCode
+ 1, OpCodeSize
- sizeof (OpCode
));
3102 return (UINT8
*)OpCodePointer
;
3106 Create EFI_IFR_ACTION_OP opcode.
3108 If OpCodeHandle is NULL, then ASSERT().
3109 If any reserved bits are set in QuestionFlags, then ASSERT().
3111 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3112 @param[in] QuestionId Question ID
3113 @param[in] Prompt String ID for Prompt
3114 @param[in] Help String ID for Help
3115 @param[in] QuestionFlags Flags in Question Header
3116 @param[in] QuestionConfig String ID for configuration
3118 @retval NULL There is not enough space left in Buffer to add the opcode.
3119 @retval Other A pointer to the created opcode.
3124 HiiCreateActionOpCode (
3125 IN VOID
*OpCodeHandle
,
3126 IN EFI_QUESTION_ID QuestionId
,
3127 IN EFI_STRING_ID Prompt
,
3128 IN EFI_STRING_ID Help
,
3129 IN UINT8 QuestionFlags
,
3130 IN EFI_STRING_ID QuestionConfig
3133 EFI_IFR_ACTION OpCode
;
3135 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3137 ZeroMem (&OpCode
, sizeof (OpCode
));
3138 OpCode
.Question
.QuestionId
= QuestionId
;
3139 OpCode
.Question
.Header
.Prompt
= Prompt
;
3140 OpCode
.Question
.Header
.Help
= Help
;
3141 OpCode
.Question
.Flags
= QuestionFlags
;
3142 OpCode
.QuestionConfig
= QuestionConfig
;
3144 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ACTION_OP
, sizeof (OpCode
));
3148 Create EFI_IFR_SUBTITLE_OP opcode.
3150 If OpCodeHandle is NULL, then ASSERT().
3151 If any reserved bits are set in Flags, then ASSERT().
3152 If Scope > 1, then ASSERT().
3154 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3155 @param[in] Prompt String ID for Prompt
3156 @param[in] Help String ID for Help
3157 @param[in] Flags Subtitle opcode flags
3158 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
3159 0 if this opcode is within the current scope.
3161 @retval NULL There is not enough space left in Buffer to add the opcode.
3162 @retval Other A pointer to the created opcode.
3167 HiiCreateSubTitleOpCode (
3168 IN VOID
*OpCodeHandle
,
3169 IN EFI_STRING_ID Prompt
,
3170 IN EFI_STRING_ID Help
,
3175 EFI_IFR_SUBTITLE OpCode
;
3177 ASSERT (Scope
<= 1);
3178 ASSERT ((Flags
& (~(EFI_IFR_FLAGS_HORIZONTAL
))) == 0);
3180 ZeroMem (&OpCode
, sizeof (OpCode
));
3181 OpCode
.Statement
.Prompt
= Prompt
;
3182 OpCode
.Statement
.Help
= Help
;
3183 OpCode
.Flags
= Flags
;
3185 return InternalHiiCreateOpCodeExtended (
3188 EFI_IFR_SUBTITLE_OP
,
3196 Create EFI_IFR_REF_OP opcode.
3198 If OpCodeHandle is NULL, then ASSERT().
3199 If any reserved bits are set in QuestionFlags, then ASSERT().
3201 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3202 @param[in] FormId Destination Form ID
3203 @param[in] Prompt String ID for Prompt
3204 @param[in] Help String ID for Help
3205 @param[in] QuestionFlags Flags in Question Header
3206 @param[in] QuestionId Question ID
3208 @retval NULL There is not enough space left in Buffer to add the opcode.
3209 @retval Other A pointer to the created opcode.
3214 HiiCreateGotoOpCode (
3215 IN VOID
*OpCodeHandle
,
3216 IN EFI_FORM_ID FormId
,
3217 IN EFI_STRING_ID Prompt
,
3218 IN EFI_STRING_ID Help
,
3219 IN UINT8 QuestionFlags
,
3220 IN EFI_QUESTION_ID QuestionId
3225 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3227 ZeroMem (&OpCode
, sizeof (OpCode
));
3228 OpCode
.Question
.Header
.Prompt
= Prompt
;
3229 OpCode
.Question
.Header
.Help
= Help
;
3230 OpCode
.Question
.QuestionId
= QuestionId
;
3231 OpCode
.Question
.Flags
= QuestionFlags
;
3232 OpCode
.FormId
= FormId
;
3234 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, sizeof (OpCode
));
3238 Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.
3240 When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.
3241 When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.
3242 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.
3243 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.
3245 If OpCodeHandle is NULL, then ASSERT().
3246 If any reserved bits are set in QuestionFlags, then ASSERT().
3248 @param[in] OpCodeHandle The handle to the buffer of opcodes.
3249 @param[in] RefFormId The Destination Form ID.
3250 @param[in] Prompt The string ID for Prompt.
3251 @param[in] Help The string ID for Help.
3252 @param[in] QuestionFlags The flags in Question Header
3253 @param[in] QuestionId Question ID.
3254 @param[in] RefQuestionId The question on the form to which this link is referring.
3255 If its value is zero, then the link refers to the top of the form.
3256 @param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is
3257 zero, then the link is to the current form set.
3258 @param[in] RefDevicePath The string identifier that specifies the string containing the text representation of
3259 the device path to which the form set containing the form specified by FormId.
3260 If its value is zero, then the link refers to the current page.
3262 @retval NULL There is not enough space left in Buffer to add the opcode.
3263 @retval Other A pointer to the created opcode.
3268 HiiCreateGotoExOpCode (
3269 IN VOID
*OpCodeHandle
,
3270 IN EFI_FORM_ID RefFormId
,
3271 IN EFI_STRING_ID Prompt
,
3272 IN EFI_STRING_ID Help
,
3273 IN UINT8 QuestionFlags
,
3274 IN EFI_QUESTION_ID QuestionId
,
3275 IN EFI_QUESTION_ID RefQuestionId
,
3276 IN EFI_GUID
*RefFormSetId
, OPTIONAL
3277 IN EFI_STRING_ID RefDevicePath
3280 EFI_IFR_REF4 OpCode
;
3283 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3285 ZeroMem (&OpCode
, sizeof (OpCode
));
3286 OpCode
.Question
.Header
.Prompt
= Prompt
;
3287 OpCode
.Question
.Header
.Help
= Help
;
3288 OpCode
.Question
.QuestionId
= QuestionId
;
3289 OpCode
.Question
.Flags
= QuestionFlags
;
3290 OpCode
.FormId
= RefFormId
;
3291 OpCode
.QuestionId
= RefQuestionId
;
3292 OpCode
.DevicePath
= RefDevicePath
;
3293 if (RefFormSetId
!= NULL
) {
3294 CopyMem (&OpCode
.FormSetId
, RefFormSetId
, sizeof (OpCode
.FormSetId
));
3298 // Cacluate OpCodeSize based on the input Ref value.
3299 // Try to use the small OpCode to save size.
3301 OpCodeSize
= sizeof (EFI_IFR_REF
);
3302 if (RefDevicePath
!= 0) {
3303 OpCodeSize
= sizeof (EFI_IFR_REF4
);
3304 } else if (RefFormSetId
!= NULL
) {
3305 OpCodeSize
= sizeof (EFI_IFR_REF3
);
3306 } else if (RefQuestionId
!= 0) {
3307 OpCodeSize
= sizeof (EFI_IFR_REF2
);
3310 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, OpCodeSize
);
3314 Create EFI_IFR_CHECKBOX_OP opcode.
3316 If OpCodeHandle is NULL, then ASSERT().
3317 If any reserved bits are set in QuestionFlags, then ASSERT().
3318 If any reserved bits are set in CheckBoxFlags, then ASSERT().
3320 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3321 @param[in] QuestionId Question ID
3322 @param[in] VarStoreId Storage ID
3323 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3324 for this name/value pair.
3325 @param[in] Prompt String ID for Prompt
3326 @param[in] Help String ID for Help
3327 @param[in] QuestionFlags Flags in Question Header
3328 @param[in] CheckBoxFlags Flags for checkbox opcode
3329 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3330 is an optional parameter that may be NULL.
3332 @retval NULL There is not enough space left in Buffer to add the opcode.
3333 @retval Other A pointer to the created opcode.
3338 HiiCreateCheckBoxOpCode (
3339 IN VOID
*OpCodeHandle
,
3340 IN EFI_QUESTION_ID QuestionId
,
3341 IN EFI_VARSTORE_ID VarStoreId
,
3342 IN UINT16 VarOffset
,
3343 IN EFI_STRING_ID Prompt
,
3344 IN EFI_STRING_ID Help
,
3345 IN UINT8 QuestionFlags
,
3346 IN UINT8 CheckBoxFlags
,
3347 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3350 EFI_IFR_CHECKBOX OpCode
;
3353 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3355 ZeroMem (&OpCode
, sizeof (OpCode
));
3356 OpCode
.Question
.QuestionId
= QuestionId
;
3357 OpCode
.Question
.VarStoreId
= VarStoreId
;
3358 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3359 OpCode
.Question
.Header
.Prompt
= Prompt
;
3360 OpCode
.Question
.Header
.Help
= Help
;
3361 OpCode
.Question
.Flags
= QuestionFlags
;
3362 OpCode
.Flags
= CheckBoxFlags
;
3364 if (DefaultsOpCodeHandle
== NULL
) {
3365 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
));
3368 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3369 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
), 0, 1);
3370 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3371 HiiCreateEndOpCode (OpCodeHandle
);
3372 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3376 Create EFI_IFR_NUMERIC_OP opcode.
3378 If OpCodeHandle is NULL, then ASSERT().
3379 If any reserved bits are set in QuestionFlags, then ASSERT().
3380 If any reserved bits are set in NumericFlags, then ASSERT().
3382 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3383 @param[in] QuestionId Question ID
3384 @param[in] VarStoreId Storage ID
3385 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3386 for this name/value pair.
3387 @param[in] Prompt String ID for Prompt
3388 @param[in] Help String ID for Help
3389 @param[in] QuestionFlags Flags in Question Header
3390 @param[in] NumericFlags Flags for numeric opcode
3391 @param[in] Minimum Numeric minimum value
3392 @param[in] Maximum Numeric maximum value
3393 @param[in] Step Numeric step for edit
3394 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3395 is an optional parameter that may be NULL.
3397 @retval NULL There is not enough space left in Buffer to add the opcode.
3398 @retval Other A pointer to the created opcode.
3403 HiiCreateNumericOpCode (
3404 IN VOID
*OpCodeHandle
,
3405 IN EFI_QUESTION_ID QuestionId
,
3406 IN EFI_VARSTORE_ID VarStoreId
,
3407 IN UINT16 VarOffset
,
3408 IN EFI_STRING_ID Prompt
,
3409 IN EFI_STRING_ID Help
,
3410 IN UINT8 QuestionFlags
,
3411 IN UINT8 NumericFlags
,
3415 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3418 EFI_IFR_NUMERIC OpCode
;
3422 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3425 ZeroMem (&OpCode
, sizeof (OpCode
));
3426 OpCode
.Question
.QuestionId
= QuestionId
;
3427 OpCode
.Question
.VarStoreId
= VarStoreId
;
3428 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3429 OpCode
.Question
.Header
.Prompt
= Prompt
;
3430 OpCode
.Question
.Header
.Help
= Help
;
3431 OpCode
.Question
.Flags
= QuestionFlags
;
3432 OpCode
.Flags
= NumericFlags
;
3434 switch (NumericFlags
& EFI_IFR_NUMERIC_SIZE
) {
3435 case EFI_IFR_NUMERIC_SIZE_1
:
3436 OpCode
.data
.u8
.MinValue
= (UINT8
)Minimum
;
3437 OpCode
.data
.u8
.MaxValue
= (UINT8
)Maximum
;
3438 OpCode
.data
.u8
.Step
= (UINT8
)Step
;
3442 case EFI_IFR_NUMERIC_SIZE_2
:
3443 OpCode
.data
.u16
.MinValue
= (UINT16
)Minimum
;
3444 OpCode
.data
.u16
.MaxValue
= (UINT16
)Maximum
;
3445 OpCode
.data
.u16
.Step
= (UINT16
)Step
;
3449 case EFI_IFR_NUMERIC_SIZE_4
:
3450 OpCode
.data
.u32
.MinValue
= (UINT32
)Minimum
;
3451 OpCode
.data
.u32
.MaxValue
= (UINT32
)Maximum
;
3452 OpCode
.data
.u32
.Step
= (UINT32
)Step
;
3456 case EFI_IFR_NUMERIC_SIZE_8
:
3457 OpCode
.data
.u64
.MinValue
= Minimum
;
3458 OpCode
.data
.u64
.MaxValue
= Maximum
;
3459 OpCode
.data
.u64
.Step
= Step
;
3464 Length
+= OFFSET_OF (EFI_IFR_NUMERIC
, data
);
3466 if (DefaultsOpCodeHandle
== NULL
) {
3467 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
);
3470 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3471 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
, 0, 1);
3472 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3473 HiiCreateEndOpCode (OpCodeHandle
);
3474 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3478 Create EFI_IFR_STRING_OP opcode.
3480 If OpCodeHandle is NULL, then ASSERT().
3481 If any reserved bits are set in QuestionFlags, then ASSERT().
3482 If any reserved bits are set in StringFlags, then ASSERT().
3484 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3485 @param[in] QuestionId Question ID
3486 @param[in] VarStoreId Storage ID
3487 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3488 for this name/value pair.
3489 @param[in] Prompt String ID for Prompt
3490 @param[in] Help String ID for Help
3491 @param[in] QuestionFlags Flags in Question Header
3492 @param[in] StringFlags Flags for string opcode
3493 @param[in] MinSize String minimum length
3494 @param[in] MaxSize String maximum length
3495 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3496 is an optional parameter that may be NULL.
3498 @retval NULL There is not enough space left in Buffer to add the opcode.
3499 @retval Other A pointer to the created opcode.
3504 HiiCreateStringOpCode (
3505 IN VOID
*OpCodeHandle
,
3506 IN EFI_QUESTION_ID QuestionId
,
3507 IN EFI_VARSTORE_ID VarStoreId
,
3508 IN UINT16 VarOffset
,
3509 IN EFI_STRING_ID Prompt
,
3510 IN EFI_STRING_ID Help
,
3511 IN UINT8 QuestionFlags
,
3512 IN UINT8 StringFlags
,
3515 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3518 EFI_IFR_STRING OpCode
;
3521 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3523 ZeroMem (&OpCode
, sizeof (OpCode
));
3524 OpCode
.Question
.Header
.Prompt
= Prompt
;
3525 OpCode
.Question
.Header
.Help
= Help
;
3526 OpCode
.Question
.QuestionId
= QuestionId
;
3527 OpCode
.Question
.VarStoreId
= VarStoreId
;
3528 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3529 OpCode
.Question
.Flags
= QuestionFlags
;
3530 OpCode
.MinSize
= MinSize
;
3531 OpCode
.MaxSize
= MaxSize
;
3532 OpCode
.Flags
= (UINT8
) (StringFlags
& EFI_IFR_STRING_MULTI_LINE
);
3534 if (DefaultsOpCodeHandle
== NULL
) {
3535 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
));
3538 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3539 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
), 0, 1);
3540 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3541 HiiCreateEndOpCode (OpCodeHandle
);
3542 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3546 Create EFI_IFR_ONE_OF_OP opcode.
3548 If OpCodeHandle is NULL, then ASSERT().
3549 If any reserved bits are set in QuestionFlags, then ASSERT().
3550 If any reserved bits are set in OneOfFlags, then ASSERT().
3552 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3553 @param[in] QuestionId Question ID
3554 @param[in] VarStoreId Storage ID
3555 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3556 for this name/value pair.
3557 @param[in] Prompt String ID for Prompt
3558 @param[in] Help String ID for Help
3559 @param[in] QuestionFlags Flags in Question Header
3560 @param[in] OneOfFlags Flags for oneof opcode
3561 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3562 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3563 is an optional parameter that may be NULL.
3565 @retval NULL There is not enough space left in Buffer to add the opcode.
3566 @retval Other A pointer to the created opcode.
3571 HiiCreateOneOfOpCode (
3572 IN VOID
*OpCodeHandle
,
3573 IN EFI_QUESTION_ID QuestionId
,
3574 IN EFI_VARSTORE_ID VarStoreId
,
3575 IN UINT16 VarOffset
,
3576 IN EFI_STRING_ID Prompt
,
3577 IN EFI_STRING_ID Help
,
3578 IN UINT8 QuestionFlags
,
3579 IN UINT8 OneOfFlags
,
3580 IN VOID
*OptionsOpCodeHandle
,
3581 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3584 EFI_IFR_ONE_OF OpCode
;
3588 ASSERT (OptionsOpCodeHandle
!= NULL
);
3589 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3591 ZeroMem (&OpCode
, sizeof (OpCode
));
3592 OpCode
.Question
.Header
.Prompt
= Prompt
;
3593 OpCode
.Question
.Header
.Help
= Help
;
3594 OpCode
.Question
.QuestionId
= QuestionId
;
3595 OpCode
.Question
.VarStoreId
= VarStoreId
;
3596 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3597 OpCode
.Question
.Flags
= QuestionFlags
;
3598 OpCode
.Flags
= OneOfFlags
;
3600 Length
= OFFSET_OF (EFI_IFR_ONE_OF
, data
);
3601 Length
+= (1 << (OneOfFlags
& EFI_IFR_NUMERIC_SIZE
)) * 3;
3603 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3604 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OP
, Length
, 0, 1);
3605 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3606 if (DefaultsOpCodeHandle
!= NULL
) {
3607 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3609 HiiCreateEndOpCode (OpCodeHandle
);
3610 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3614 Create EFI_IFR_ORDERED_LIST_OP opcode.
3616 If OpCodeHandle is NULL, then ASSERT().
3617 If any reserved bits are set in QuestionFlags, then ASSERT().
3618 If any reserved bits are set in OrderedListFlags, then ASSERT().
3620 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3621 @param[in] QuestionId Question ID
3622 @param[in] VarStoreId Storage ID
3623 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3624 for this name/value pair.
3625 @param[in] Prompt String ID for Prompt
3626 @param[in] Help String ID for Help
3627 @param[in] QuestionFlags Flags in Question Header
3628 @param[in] OrderedListFlags Flags for ordered list opcode
3629 @param[in] DataType Type for option value
3630 @param[in] MaxContainers Maximum count for options in this ordered list
3631 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3632 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3633 is an optional parameter that may be NULL.
3635 @retval NULL There is not enough space left in Buffer to add the opcode.
3636 @retval Other A pointer to the created opcode.
3641 HiiCreateOrderedListOpCode (
3642 IN VOID
*OpCodeHandle
,
3643 IN EFI_QUESTION_ID QuestionId
,
3644 IN EFI_VARSTORE_ID VarStoreId
,
3645 IN UINT16 VarOffset
,
3646 IN EFI_STRING_ID Prompt
,
3647 IN EFI_STRING_ID Help
,
3648 IN UINT8 QuestionFlags
,
3649 IN UINT8 OrderedListFlags
,
3651 IN UINT8 MaxContainers
,
3652 IN VOID
*OptionsOpCodeHandle
,
3653 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3656 EFI_IFR_ORDERED_LIST OpCode
;
3659 ASSERT (OptionsOpCodeHandle
!= NULL
);
3660 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3662 ZeroMem (&OpCode
, sizeof (OpCode
));
3663 OpCode
.Question
.Header
.Prompt
= Prompt
;
3664 OpCode
.Question
.Header
.Help
= Help
;
3665 OpCode
.Question
.QuestionId
= QuestionId
;
3666 OpCode
.Question
.VarStoreId
= VarStoreId
;
3667 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3668 OpCode
.Question
.Flags
= QuestionFlags
;
3669 OpCode
.MaxContainers
= MaxContainers
;
3670 OpCode
.Flags
= OrderedListFlags
;
3672 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3673 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ORDERED_LIST_OP
, sizeof (OpCode
), 0, 1);
3674 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3675 if (DefaultsOpCodeHandle
!= NULL
) {
3676 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3678 HiiCreateEndOpCode (OpCodeHandle
);
3679 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3683 Create EFI_IFR_TEXT_OP opcode.
3685 If OpCodeHandle is NULL, then ASSERT().
3687 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3688 @param[in] Prompt String ID for Prompt.
3689 @param[in] Help String ID for Help.
3690 @param[in] TextTwo String ID for TextTwo.
3692 @retval NULL There is not enough space left in Buffer to add the opcode.
3693 @retval Other A pointer to the created opcode.
3698 HiiCreateTextOpCode (
3699 IN VOID
*OpCodeHandle
,
3700 IN EFI_STRING_ID Prompt
,
3701 IN EFI_STRING_ID Help
,
3702 IN EFI_STRING_ID TextTwo
3705 EFI_IFR_TEXT OpCode
;
3707 ZeroMem (&OpCode
, sizeof (OpCode
));
3708 OpCode
.Statement
.Prompt
= Prompt
;
3709 OpCode
.Statement
.Help
= Help
;
3710 OpCode
.TextTwo
= TextTwo
;
3712 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TEXT_OP
, sizeof (OpCode
));
3716 Create EFI_IFR_DATE_OP opcode.
3718 If OpCodeHandle is NULL, then ASSERT().
3719 If any reserved bits are set in QuestionFlags, then ASSERT().
3720 If any reserved bits are set in DateFlags, then ASSERT().
3722 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3723 @param[in] QuestionId Question ID
3724 @param[in] VarStoreId Storage ID, optional. If DateFlags is not
3725 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3726 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3727 for this name/value pair, optional. If DateFlags is not
3728 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3729 @param[in] Prompt String ID for Prompt
3730 @param[in] Help String ID for Help
3731 @param[in] QuestionFlags Flags in Question Header
3732 @param[in] DateFlags Flags for date opcode
3733 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3734 is an optional parameter that may be NULL.
3736 @retval NULL There is not enough space left in Buffer to add the opcode.
3737 @retval Other A pointer to the created opcode.
3742 HiiCreateDateOpCode (
3743 IN VOID
*OpCodeHandle
,
3744 IN EFI_QUESTION_ID QuestionId
,
3745 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
3746 IN UINT16 VarOffset
, OPTIONAL
3747 IN EFI_STRING_ID Prompt
,
3748 IN EFI_STRING_ID Help
,
3749 IN UINT8 QuestionFlags
,
3751 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3754 EFI_IFR_DATE OpCode
;
3757 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3758 ASSERT ((DateFlags
& (~(EFI_QF_DATE_YEAR_SUPPRESS
| EFI_QF_DATE_MONTH_SUPPRESS
| EFI_QF_DATE_DAY_SUPPRESS
| EFI_QF_DATE_STORAGE
))) == 0);
3760 ZeroMem (&OpCode
, sizeof (OpCode
));
3761 OpCode
.Question
.Header
.Prompt
= Prompt
;
3762 OpCode
.Question
.Header
.Help
= Help
;
3763 OpCode
.Question
.QuestionId
= QuestionId
;
3764 OpCode
.Question
.VarStoreId
= VarStoreId
;
3765 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3766 OpCode
.Question
.Flags
= QuestionFlags
;
3767 OpCode
.Flags
= DateFlags
;
3769 if (DefaultsOpCodeHandle
== NULL
) {
3770 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
));
3773 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3774 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
), 0, 1);
3775 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3776 HiiCreateEndOpCode (OpCodeHandle
);
3777 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3781 Create EFI_IFR_TIME_OP opcode.
3783 If OpCodeHandle is NULL, then ASSERT().
3784 If any reserved bits are set in QuestionFlags, then ASSERT().
3785 If any reserved bits are set in TimeFlags, then ASSERT().
3787 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3788 @param[in] QuestionId Question ID
3789 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not
3790 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3791 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3792 for this name/value pair, optional. If TimeFlags is not
3793 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3794 @param[in] Prompt String ID for Prompt
3795 @param[in] Help String ID for Help
3796 @param[in] QuestionFlags Flags in Question Header
3797 @param[in] TimeFlags Flags for time opcode
3798 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3799 is an optional parameter that may be NULL.
3801 @retval NULL There is not enough space left in Buffer to add the opcode.
3802 @retval Other A pointer to the created opcode.
3807 HiiCreateTimeOpCode (
3808 IN VOID
*OpCodeHandle
,
3809 IN EFI_QUESTION_ID QuestionId
,
3810 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
3811 IN UINT16 VarOffset
, OPTIONAL
3812 IN EFI_STRING_ID Prompt
,
3813 IN EFI_STRING_ID Help
,
3814 IN UINT8 QuestionFlags
,
3816 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3819 EFI_IFR_TIME OpCode
;
3822 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3823 ASSERT ((TimeFlags
& (~(QF_TIME_HOUR_SUPPRESS
| QF_TIME_MINUTE_SUPPRESS
| QF_TIME_SECOND_SUPPRESS
| QF_TIME_STORAGE
))) == 0);
3825 ZeroMem (&OpCode
, sizeof (OpCode
));
3826 OpCode
.Question
.Header
.Prompt
= Prompt
;
3827 OpCode
.Question
.Header
.Help
= Help
;
3828 OpCode
.Question
.QuestionId
= QuestionId
;
3829 OpCode
.Question
.VarStoreId
= VarStoreId
;
3830 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3831 OpCode
.Question
.Flags
= QuestionFlags
;
3832 OpCode
.Flags
= TimeFlags
;
3834 if (DefaultsOpCodeHandle
== NULL
) {
3835 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
));
3838 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3839 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
), 0, 1);
3840 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3841 HiiCreateEndOpCode (OpCodeHandle
);
3842 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3846 This is the internal worker function to update the data in
3847 a form specified by FormSetGuid, FormId and Label.
3849 @param[in] FormSetGuid The optional Formset GUID.
3850 @param[in] FormId The Form ID.
3851 @param[in] Package The package header.
3852 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR
3853 opcodes to be inserted or replaced in the form.
3854 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode
3855 that marks the end of a replace operation in the form.
3856 @param[out] TempPackage The resultant package.
3858 @retval EFI_SUCCESS The function completes successfully.
3859 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.
3864 InternalHiiUpdateFormPackageData (
3865 IN EFI_GUID
*FormSetGuid
, OPTIONAL
3866 IN EFI_FORM_ID FormId
,
3867 IN EFI_HII_PACKAGE_HEADER
*Package
,
3868 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
,
3869 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
, OPTIONAL
3870 OUT EFI_HII_PACKAGE_HEADER
*TempPackage
3875 EFI_HII_PACKAGE_HEADER PackageHeader
;
3877 EFI_IFR_OP_HEADER
*IfrOpHdr
;
3878 EFI_IFR_OP_HEADER
*UpdateIfrOpHdr
;
3882 UINTN UpdatePackageLength
;
3884 CopyMem (TempPackage
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3885 UpdatePackageLength
= sizeof (EFI_HII_PACKAGE_HEADER
);
3886 BufferPos
= (UINT8
*) (TempPackage
+ 1);
3888 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3889 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
3890 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
3891 GetFormSet
= (BOOLEAN
) ((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
3895 while (Offset
< PackageHeader
.Length
) {
3896 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3897 BufferPos
+= IfrOpHdr
->Length
;
3898 UpdatePackageLength
+= IfrOpHdr
->Length
;
3901 // Find the matched FormSet and Form
3903 if ((IfrOpHdr
->OpCode
== EFI_IFR_FORM_SET_OP
) && (FormSetGuid
!= NULL
)) {
3904 if (CompareGuid((GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
)) {
3909 } else if (IfrOpHdr
->OpCode
== EFI_IFR_FORM_OP
|| IfrOpHdr
->OpCode
== EFI_IFR_FORM_MAP_OP
) {
3910 if (CompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
3918 // The matched Form is found, and Update data in this form
3920 if (GetFormSet
&& GetForm
) {
3921 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
;
3922 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3923 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3925 // Remove the original data when End OpCode buffer exist.
3927 if (OpCodeBufferEnd
!= NULL
) {
3928 Offset
+= IfrOpHdr
->Length
;
3929 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3930 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferEnd
->Buffer
;
3931 while (Offset
< PackageHeader
.Length
) {
3933 // Search the matched end opcode
3935 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3936 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3940 // Go to the next Op-Code
3942 Offset
+= IfrOpHdr
->Length
;
3943 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3946 if (Offset
>= PackageHeader
.Length
) {
3948 // The end opcode is not found.
3950 return EFI_NOT_FOUND
;
3955 // Insert the updated data
3957 AddSize
= ((EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
)->Length
;
3958 CopyMem (BufferPos
, OpCodeBufferStart
->Buffer
+ AddSize
, OpCodeBufferStart
->Position
- AddSize
);
3959 BufferPos
+= OpCodeBufferStart
->Position
- AddSize
;
3960 UpdatePackageLength
+= OpCodeBufferStart
->Position
- AddSize
;
3962 if (OpCodeBufferEnd
!= NULL
) {
3964 // Add the end opcode
3966 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3967 BufferPos
+= IfrOpHdr
->Length
;
3968 UpdatePackageLength
+= IfrOpHdr
->Length
;
3972 // Copy the left package data.
3974 Offset
+= IfrOpHdr
->Length
;
3975 CopyMem (BufferPos
, (UINT8
*) Package
+ Offset
, PackageHeader
.Length
- Offset
);
3976 UpdatePackageLength
+= PackageHeader
.Length
- Offset
;
3987 // Go to the next Op-Code
3989 Offset
+= IfrOpHdr
->Length
;
3990 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3995 // The updated opcode buffer is not found.
3997 return EFI_NOT_FOUND
;
4000 // Update the package length.
4002 PackageHeader
.Length
= (UINT32
) UpdatePackageLength
;
4003 CopyMem (TempPackage
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4009 This function updates a form that has previously been registered with the HII
4010 Database. This function will perform at most one update operation.
4012 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
4013 comparisons of IFR opcodes are performed from the beginning of the form being
4014 updated until an IFR opcode is found that exactly matches the first IFR opcode
4015 specified by StartOpCodeHandle. The following rules are used to determine if
4016 an insert, replace, or delete operation is performed.
4018 1) If no matches are found, then NULL is returned.
4019 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
4020 from StartOpCodeHandle except the first opcode are inserted immediately after
4021 the matching IFR opcode in the form to be updated.
4022 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
4023 from the matching IFR opcode until an IFR opcode exactly matches the first
4024 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
4025 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
4026 is found, then all of the IFR opcodes between the start match and the end
4027 match are deleted from the form being updated and all of the IFR opcodes
4028 from StartOpCodeHandle except the first opcode are inserted immediately after
4029 the matching start IFR opcode. If StartOpCcodeHandle only contains one
4030 IFR instruction, then the result of this operation will delete all of the IFR
4031 opcodes between the start end matches.
4033 If HiiHandle is NULL, then ASSERT().
4034 If StartOpCodeHandle is NULL, then ASSERT().
4036 @param[in] HiiHandle The HII Handle of the form to update.
4037 @param[in] FormSetGuid The Formset GUID of the form to update. This
4038 is an optional parameter that may be NULL.
4039 If it is NULL, all FormSet will be updated.
4040 @param[in] FormId The ID of the form to update.
4041 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
4042 opcodes to be inserted or replaced in the form.
4043 The first IFR instruction in StartOpCodeHandle
4044 is used to find matching IFR opcode in the
4046 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
4047 that marks the end of a replace operation in
4048 the form. This is an optional parameter that
4049 may be NULL. If it is NULL, then an the IFR
4050 opcodes specified by StartOpCodeHandle are
4051 inserted into the form.
4053 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
4054 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
4055 1) The form specified by HiiHandle, FormSetGuid,
4056 and FormId could not be found in the HII Database.
4057 2) No IFR opcodes in the target form match the first
4058 IFR opcode in StartOpCodeHandle.
4059 3) EndOpCOde is not NULL, and no IFR opcodes in the
4060 target form following a matching start opcode match
4061 the first IFR opcode in EndOpCodeHandle.
4062 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
4068 IN EFI_HII_HANDLE HiiHandle
,
4069 IN EFI_GUID
*FormSetGuid
, OPTIONAL
4070 IN EFI_FORM_ID FormId
,
4071 IN VOID
*StartOpCodeHandle
,
4072 IN VOID
*EndOpCodeHandle OPTIONAL
4076 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4077 UINT32 PackageListLength
;
4079 EFI_HII_PACKAGE_LIST_HEADER
*UpdatePackageList
;
4081 UINT8
*UpdateBufferPos
;
4082 EFI_HII_PACKAGE_HEADER
*Package
;
4083 EFI_HII_PACKAGE_HEADER
*TempPacakge
;
4084 EFI_HII_PACKAGE_HEADER PackageHeader
;
4086 HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
;
4087 HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
;
4090 // Input update data can't be NULL.
4092 ASSERT (HiiHandle
!= NULL
);
4093 ASSERT (StartOpCodeHandle
!= NULL
);
4094 UpdatePackageList
= NULL
;
4096 HiiPackageList
= NULL
;
4099 // Retrieve buffer data from Opcode Handle
4101 OpCodeBufferStart
= (HII_LIB_OPCODE_BUFFER
*) StartOpCodeHandle
;
4102 OpCodeBufferEnd
= (HII_LIB_OPCODE_BUFFER
*) EndOpCodeHandle
;
4105 // Get the original package list
4108 HiiPackageList
= NULL
;
4109 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4111 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
4113 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4117 HiiPackageList
= AllocatePool (BufferSize
);
4118 if (HiiPackageList
== NULL
) {
4119 Status
= EFI_OUT_OF_RESOURCES
;
4123 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4124 if (EFI_ERROR (Status
)) {
4129 // Calculate and allocate space for retrieval of IFR data
4131 BufferSize
+= OpCodeBufferStart
->Position
;
4132 UpdatePackageList
= AllocateZeroPool (BufferSize
);
4133 if (UpdatePackageList
== NULL
) {
4134 Status
= EFI_OUT_OF_RESOURCES
;
4139 // Allocate temp buffer to store the temp updated package buffer
4141 TempPacakge
= AllocateZeroPool (BufferSize
);
4142 if (TempPacakge
== NULL
) {
4143 Status
= EFI_OUT_OF_RESOURCES
;
4147 UpdateBufferPos
= (UINT8
*) UpdatePackageList
;
4150 // Copy the package list header
4152 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
4153 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4156 // Go through each package to find the matched package and update one by one
4159 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4160 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
4161 while (Offset
< PackageListLength
) {
4162 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
4163 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4164 Offset
+= Package
->Length
;
4166 if (Package
->Type
== EFI_HII_PACKAGE_FORMS
) {
4168 // Check this package is the matched package.
4170 Status
= InternalHiiUpdateFormPackageData (FormSetGuid
, FormId
, Package
, OpCodeBufferStart
, OpCodeBufferEnd
, TempPacakge
);
4172 // The matched package is found. Its package buffer will be updated by the input new data.
4174 if (!EFI_ERROR(Status
)) {
4180 // Add updated package buffer
4182 Package
= TempPacakge
;
4187 // Add pacakge buffer
4189 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4190 CopyMem (UpdateBufferPos
, Package
, PackageHeader
.Length
);
4191 UpdateBufferPos
+= PackageHeader
.Length
;
4196 // Update package list length
4198 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdatePackageList
;
4199 WriteUnaligned32 (&UpdatePackageList
->PackageLength
, (UINT32
) BufferSize
);
4202 // Update Package to show form
4204 Status
= gHiiDatabase
->UpdatePackageList (gHiiDatabase
, HiiHandle
, UpdatePackageList
);
4207 // Not matched form is found and updated.
4209 Status
= EFI_NOT_FOUND
;
4213 if (HiiPackageList
!= NULL
) {
4214 FreePool (HiiPackageList
);
4217 if (UpdatePackageList
!= NULL
) {
4218 FreePool (UpdatePackageList
);
4221 if (TempPacakge
!= NULL
) {
4222 FreePool (TempPacakge
);