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 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1302 case EFI_IFR_NUMERIC_SIZE_1
:
1303 if ((UINT8
) VarValue
< IfrNumeric
->data
.u8
.MinValue
|| (UINT8
) VarValue
> IfrNumeric
->data
.u8
.MaxValue
) {
1305 // Not in the valid range.
1307 return EFI_INVALID_PARAMETER
;
1310 case EFI_IFR_NUMERIC_SIZE_2
:
1311 if ((UINT16
) VarValue
< IfrNumeric
->data
.u16
.MinValue
|| (UINT16
) VarValue
> IfrNumeric
->data
.u16
.MaxValue
) {
1313 // Not in the valid range.
1315 return EFI_INVALID_PARAMETER
;
1318 case EFI_IFR_NUMERIC_SIZE_4
:
1319 if ((UINT32
) VarValue
< IfrNumeric
->data
.u32
.MinValue
|| (UINT32
) VarValue
> IfrNumeric
->data
.u32
.MaxValue
) {
1321 // Not in the valid range.
1323 return EFI_INVALID_PARAMETER
;
1326 case EFI_IFR_NUMERIC_SIZE_8
:
1327 if ((UINT64
) VarValue
< IfrNumeric
->data
.u64
.MinValue
|| (UINT64
) VarValue
> IfrNumeric
->data
.u64
.MaxValue
) {
1329 // Not in the valid range.
1331 return EFI_INVALID_PARAMETER
;
1337 case EFI_IFR_CHECKBOX_OP
:
1339 // Check value is BOOLEAN type, only 0 and 1 is valid.
1343 // CheckBox question is not in IFR Form. This IFR form is not valid.
1345 if (VarStoreData
.VarStoreId
== 0) {
1346 return EFI_INVALID_PARAMETER
;
1350 // Check whether this question is for the requested varstore.
1352 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1353 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1357 if (NameValueType
) {
1358 QuestionName
= HiiGetString (HiiHandle
, IfrCheckBox
->Question
.VarStoreInfo
.VarName
, NULL
);
1359 ASSERT (QuestionName
!= NULL
);
1361 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1363 // This question is not in the current configuration string. Skip it.
1368 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1369 if (EFI_ERROR (Status
)) {
1374 // Get Offset by Question header
1376 Offset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1377 Width
= (UINT16
) sizeof (BOOLEAN
);
1379 // Check whether this question is in current block array.
1381 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1383 // This question is not in the current configuration string. Skip it.
1388 // Check this var question is in the var storage
1390 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1392 // This question exceeds the var store size.
1394 return EFI_INVALID_PARAMETER
;
1397 // Check the current value is in the numeric range.
1400 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1403 // Boolean type, only 1 and 0 is valid.
1406 return EFI_INVALID_PARAMETER
;
1409 case EFI_IFR_STRING_OP
:
1411 // Check current string length is less than maxsize
1415 // CheckBox question is not in IFR Form. This IFR form is not valid.
1417 if (VarStoreData
.VarStoreId
== 0) {
1418 return EFI_INVALID_PARAMETER
;
1422 // Check whether this question is for the requested varstore.
1424 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1425 if (IfrString
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1429 // Get Width by OneOf Flags
1431 Width
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1432 if (NameValueType
) {
1433 QuestionName
= HiiGetString (HiiHandle
, IfrString
->Question
.VarStoreInfo
.VarName
, NULL
);
1434 ASSERT (QuestionName
!= NULL
);
1436 StringPtr
= StrStr (RequestElement
, QuestionName
);
1437 if (StringPtr
== NULL
) {
1439 // This question is not in the current configuration string. Skip it.
1450 // Check current string length is less than maxsize
1452 if (StrSize (StringPtr
) > Width
) {
1453 return EFI_INVALID_PARAMETER
;
1457 // Get Offset/Width by Question header and OneOf Flags
1459 Offset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1461 // Check whether this question is in current block array.
1463 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1465 // This question is not in the current configuration string. Skip it.
1470 // Check this var question is in the var storage
1472 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1474 // This question exceeds the var store size.
1476 return EFI_INVALID_PARAMETER
;
1480 // Check current string length is less than maxsize
1482 if (StrSize ((CHAR16
*) (VarBuffer
+ Offset
)) > Width
) {
1483 return EFI_INVALID_PARAMETER
;
1487 case EFI_IFR_ONE_OF_OPTION_OP
:
1489 // Opcode Scope is zero. This one of option is not to be checked.
1491 if (VarBlockData
.Scope
== 0) {
1496 // Only check for OneOf and OrderList opcode
1498 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1499 if (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
) {
1501 // Check current value is the value of one of option.
1503 ASSERT (IfrOneOfOption
->Type
<= EFI_IFR_TYPE_NUM_SIZE_64
);
1504 ZeroMem (&TmpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
1505 CopyMem (&TmpValue
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
1506 if (VarValue
== TmpValue
.u64
) {
1508 // The value is one of option value.
1509 // Set OpCode to Zero, don't need check again.
1511 VarBlockData
.OpCode
= 0;
1515 case EFI_IFR_END_OP
:
1517 // Decrease opcode scope for the validated opcode
1519 if (VarBlockData
.Scope
> 0) {
1520 VarBlockData
.Scope
--;
1524 // OneOf value doesn't belong to one of option value.
1526 if ((VarBlockData
.Scope
== 0) && (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
)) {
1527 return EFI_INVALID_PARAMETER
;
1532 // Increase Scope for the validated opcode
1534 if (VarBlockData
.Scope
> 0) {
1535 VarBlockData
.Scope
= (UINT8
) (VarBlockData
.Scope
+ IfrOpHdr
->Scope
);
1540 // Go to the next opcode
1542 IfrOffset
+= IfrOpHdr
->Length
;
1545 // Only one form is in a package list.
1551 // Go to next package.
1553 PackageOffset
+= PacakgeHeader
.Length
;
1560 This internal function parses IFR data to validate current setting.
1562 @param ConfigElement ConfigResp element string contains the current setting.
1563 @param CurrentBlockArray Current block array.
1564 @param VarBuffer Data buffer for this varstore.
1566 @retval EFI_SUCCESS The current setting is valid.
1567 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1568 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1572 IN CHAR16
*ConfigElement
,
1573 OUT IFR_BLOCK_DATA
**CurrentBlockArray
,
1574 OUT UINT8
**VarBuffer
1577 IFR_BLOCK_DATA
*BlockData
;
1578 IFR_BLOCK_DATA
*NewBlockData
;
1579 EFI_STRING StringPtr
;
1585 UINTN MaxBufferSize
;
1587 IFR_BLOCK_DATA
*BlockArray
;
1591 // Initialize the local variables.
1593 Status
= EFI_SUCCESS
;
1595 NewBlockData
= NULL
;
1598 MaxBufferSize
= HII_LIB_DEFAULT_VARSTORE_SIZE
;
1599 DataBuffer
= AllocateZeroPool (MaxBufferSize
);
1600 if (DataBuffer
== NULL
) {
1601 return EFI_OUT_OF_RESOURCES
;
1607 BlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1608 if (BlockArray
== NULL
) {
1609 Status
= EFI_OUT_OF_RESOURCES
;
1612 InitializeListHead (&BlockArray
->Entry
);
1614 StringPtr
= StrStr (ConfigElement
, L
"&OFFSET=");
1615 ASSERT (StringPtr
!= NULL
);
1618 // Parse each <RequestElement> if exists
1619 // Only <BlockName> format is supported by this help function.
1620 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1622 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1624 // Skip the &OFFSET= string
1626 StringPtr
+= StrLen (L
"&OFFSET=");
1631 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1632 if (EFI_ERROR (Status
)) {
1639 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1641 FreePool (TmpBuffer
);
1644 StringPtr
+= Length
;
1645 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1646 Status
= EFI_INVALID_PARAMETER
;
1649 StringPtr
+= StrLen (L
"&WIDTH=");
1654 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1655 if (EFI_ERROR (Status
)) {
1662 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1664 FreePool (TmpBuffer
);
1667 StringPtr
+= Length
;
1668 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1669 Status
= EFI_INVALID_PARAMETER
;
1673 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1674 Status
= EFI_INVALID_PARAMETER
;
1677 StringPtr
+= StrLen (L
"&VALUE=");
1682 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1683 if (EFI_ERROR (Status
)) {
1687 StringPtr
+= Length
;
1688 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1689 Status
= EFI_INVALID_PARAMETER
;
1694 // Check whether VarBuffer is enough
1696 if ((UINTN
) (Offset
+ Width
) > MaxBufferSize
) {
1697 DataBuffer
= ReallocatePool (
1699 Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
,
1702 if (DataBuffer
== NULL
) {
1703 Status
= EFI_OUT_OF_RESOURCES
;
1706 MaxBufferSize
= Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
;
1710 // Update the Block with configuration info
1712 CopyMem (DataBuffer
+ Offset
, TmpBuffer
, Width
);
1713 FreePool (TmpBuffer
);
1717 // Set new Block Data
1719 NewBlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1720 if (NewBlockData
== NULL
) {
1721 Status
= EFI_OUT_OF_RESOURCES
;
1724 NewBlockData
->Offset
= Offset
;
1725 NewBlockData
->Width
= Width
;
1728 // Insert the new block data into the block data array.
1730 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1731 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1732 if (NewBlockData
->Offset
== BlockData
->Offset
) {
1733 if (NewBlockData
->Width
> BlockData
->Width
) {
1734 BlockData
->Width
= NewBlockData
->Width
;
1736 FreePool (NewBlockData
);
1738 } else if (NewBlockData
->Offset
< BlockData
->Offset
) {
1740 // Insert new block data as the previous one of this link.
1742 InsertTailList (Link
, &NewBlockData
->Entry
);
1748 // Insert new block data into the array tail.
1750 if (Link
== &BlockArray
->Entry
) {
1751 InsertTailList (Link
, &NewBlockData
->Entry
);
1755 // If '\0', parsing is finished.
1757 if (*StringPtr
== 0) {
1761 // Go to next ConfigBlock
1766 // Merge the aligned block data into the single block data.
1768 Link
= BlockArray
->Entry
.ForwardLink
;
1769 while ((Link
!= &BlockArray
->Entry
) && (Link
->ForwardLink
!= &BlockArray
->Entry
)) {
1770 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1771 NewBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1772 if ((NewBlockData
->Offset
>= BlockData
->Offset
) && (NewBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1773 if ((NewBlockData
->Offset
+ NewBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1774 BlockData
->Width
= (UINT16
) (NewBlockData
->Offset
+ NewBlockData
->Width
- BlockData
->Offset
);
1776 RemoveEntryList (Link
->ForwardLink
);
1777 FreePool (NewBlockData
);
1780 Link
= Link
->ForwardLink
;
1783 *VarBuffer
= DataBuffer
;
1784 *CurrentBlockArray
= BlockArray
;
1788 if (DataBuffer
!= NULL
) {
1789 FreePool (DataBuffer
);
1792 if (BlockArray
!= NULL
) {
1794 // Free Link Array CurrentBlockArray
1796 while (!IsListEmpty (&BlockArray
->Entry
)) {
1797 BlockData
= BASE_CR (BlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1798 RemoveEntryList (&BlockData
->Entry
);
1799 FreePool (BlockData
);
1801 FreePool (BlockArray
);
1808 This internal function parses IFR data to validate current setting.
1810 @param ConfigResp ConfigResp string contains the current setting.
1811 @param HiiPackageList Point to Hii package list.
1812 @param PackageListLength The length of the pacakge.
1813 @param VarGuid Guid of the buffer storage.
1814 @param VarName Name of the buffer storage.
1815 @param HiiHandle The HiiHandle for this package.
1817 @retval EFI_SUCCESS The current setting is valid.
1818 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1819 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1823 InternalHiiValidateCurrentSetting (
1824 IN EFI_STRING ConfigResp
,
1825 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
1826 IN UINTN PackageListLength
,
1827 IN EFI_GUID
*VarGuid
,
1829 IN EFI_HII_HANDLE HiiHandle
1834 IFR_BLOCK_DATA
*CurrentBlockArray
;
1835 IFR_BLOCK_DATA
*BlockData
;
1837 BOOLEAN NameValueType
;
1839 CurrentBlockArray
= NULL
;
1842 Status
= EFI_SUCCESS
;
1845 // If StringPtr != NULL, get the request elements.
1847 if (StrStr (ConfigResp
, L
"&OFFSET=") != NULL
) {
1848 Status
= GetBlockDataInfo(ConfigResp
, &CurrentBlockArray
, &VarBuffer
);
1849 if (EFI_ERROR (Status
)) {
1852 NameValueType
= FALSE
;
1855 // Skip header part.
1857 StringPtr
= StrStr (ConfigResp
, L
"PATH=");
1858 ASSERT (StringPtr
!= NULL
);
1860 if (StrStr (StringPtr
, L
"&") != NULL
) {
1861 NameValueType
= TRUE
;
1864 // Not found Request element, return success.
1870 Status
= ValidateQuestionFromVfr(
1882 if (VarBuffer
!= NULL
) {
1883 FreePool (VarBuffer
);
1886 if (CurrentBlockArray
!= NULL
) {
1888 // Free Link Array CurrentBlockArray
1890 while (!IsListEmpty (&CurrentBlockArray
->Entry
)) {
1891 BlockData
= BASE_CR (CurrentBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1892 RemoveEntryList (&BlockData
->Entry
);
1893 FreePool (BlockData
);
1895 FreePool (CurrentBlockArray
);
1902 Check whether the ConfigRequest string has the request elements.
1903 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1904 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1906 @param ConfigRequest The input config request string.
1908 @retval TRUE The input include config request elements.
1909 @retval FALSE The input string not includes.
1913 GetElementsFromRequest (
1914 IN EFI_STRING ConfigRequest
1917 EFI_STRING TmpRequest
;
1919 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1920 ASSERT (TmpRequest
!= NULL
);
1922 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1930 This function parses the input ConfigRequest string and its matched IFR code
1931 string for setting default value and validating current setting.
1933 1. For setting default action, Reset the default value specified by DefaultId
1934 to the driver configuration got by Request string.
1935 2. For validating current setting, Validate the current configuration
1936 by parsing HII form IFR opcode.
1938 NULL request string support depends on the ExportConfig interface of
1939 HiiConfigRouting protocol in UEFI specification.
1941 @param Request A null-terminated Unicode string in
1942 <MultiConfigRequest> format. It can be NULL.
1943 If it is NULL, all current configuration for the
1944 entirety of the current HII database will be validated.
1945 If it is NULL, all configuration for the
1946 entirety of the current HII database will be reset.
1947 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.
1948 @param ActionType Action supports setting defaults and validate current setting.
1950 @retval TURE Action runs successfully.
1951 @retval FALSE Action is not valid or Action can't be executed successfully..
1955 InternalHiiIfrValueAction (
1956 IN CONST EFI_STRING Request
, OPTIONAL
1957 IN UINT16 DefaultId
,
1961 EFI_STRING ConfigAltResp
;
1962 EFI_STRING ConfigAltHdr
;
1963 EFI_STRING ConfigResp
;
1964 EFI_STRING Progress
;
1965 EFI_STRING StringPtr
;
1966 EFI_STRING StringHdr
;
1968 EFI_HANDLE DriverHandle
;
1969 EFI_HANDLE TempDriverHandle
;
1970 EFI_HII_HANDLE
*HiiHandleBuffer
;
1971 EFI_HII_HANDLE HiiHandle
;
1976 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1977 UINTN PackageListLength
;
1978 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1979 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1981 ConfigAltResp
= NULL
;
1986 ConfigAltHdr
= NULL
;
1987 HiiHandleBuffer
= NULL
;
1989 TempDriverHandle
= NULL
;
1991 HiiPackageList
= NULL
;
1994 // Only support set default and validate setting action.
1996 if ((ActionType
!= ACTION_SET_DEFAUTL_VALUE
) && (ActionType
!= ACTION_VALIDATE_SETTING
)) {
2001 // Get the full requested value and deault value string.
2003 if (Request
!= NULL
) {
2004 Status
= gHiiConfigRouting
->ExtractConfig (
2011 Status
= gHiiConfigRouting
->ExportConfig (
2017 if (EFI_ERROR (Status
)) {
2021 StringPtr
= ConfigAltResp
;
2023 while (StringPtr
!= L
'\0') {
2025 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
2027 StringHdr
= StringPtr
;
2032 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2033 Status
= EFI_INVALID_PARAMETER
;
2036 StringPtr
+= StrLen (L
"GUID=");
2037 Status
= InternalHiiGetBufferFromString (StringPtr
, GUID_CONFIG_STRING_TYPE
, (UINT8
**) &VarGuid
);
2038 if (EFI_ERROR (Status
)) {
2043 // Get Name value VarName
2045 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2048 if (*StringPtr
== L
'\0') {
2049 Status
= EFI_INVALID_PARAMETER
;
2052 StringPtr
+= StrLen (L
"&NAME=");
2053 Status
= InternalHiiGetBufferFromString (StringPtr
, NAME_CONFIG_STRING_TYPE
, (UINT8
**) &VarName
);
2054 if (EFI_ERROR (Status
)) {
2059 // Get Path value DevicePath
2061 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2064 if (*StringPtr
== L
'\0') {
2065 Status
= EFI_INVALID_PARAMETER
;
2068 StringPtr
+= StrLen (L
"&PATH=");
2069 Status
= InternalHiiGetBufferFromString (StringPtr
, PATH_CONFIG_STRING_TYPE
, (UINT8
**) &DevicePath
);
2070 if (EFI_ERROR (Status
)) {
2075 // Get the Driver handle by the got device path.
2077 TempDevicePath
= DevicePath
;
2078 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDevicePath
, &DriverHandle
);
2079 if (EFI_ERROR (Status
)) {
2084 // Find the matched Hii Handle for the found Driver handle
2086 HiiHandleBuffer
= HiiGetHiiHandles (NULL
);
2087 if (HiiHandleBuffer
== NULL
) {
2088 Status
= EFI_NOT_FOUND
;
2092 for (Index
= 0; HiiHandleBuffer
[Index
] != NULL
; Index
++) {
2093 gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, HiiHandleBuffer
[Index
], &TempDriverHandle
);
2094 if (TempDriverHandle
== DriverHandle
) {
2099 HiiHandle
= HiiHandleBuffer
[Index
];
2100 FreePool (HiiHandleBuffer
);
2102 if (HiiHandle
== NULL
) {
2104 // This request string has no its Hii package.
2105 // Its default value and validating can't execute by parsing IFR data.
2106 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
2108 Status
= EFI_SUCCESS
;
2109 goto NextConfigAltResp
;
2113 // 2. Get HiiPackage by HiiHandle
2115 PackageListLength
= 0;
2116 HiiPackageList
= NULL
;
2117 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2120 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
2122 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2123 Status
= EFI_INVALID_PARAMETER
;
2127 HiiPackageList
= AllocatePool (PackageListLength
);
2128 if (HiiPackageList
== NULL
) {
2129 Status
= EFI_OUT_OF_RESOURCES
;
2134 // Get PackageList on HiiHandle
2136 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2137 if (EFI_ERROR (Status
)) {
2142 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2143 // Get the default configuration string according to the default ID.
2145 Status
= gHiiConfigRouting
->GetAltConfig (
2151 (ActionType
== ACTION_SET_DEFAUTL_VALUE
) ? &DefaultId
:NULL
, // it can be NULL to get the current setting.
2156 // The required setting can't be found. So, it is not required to be validated and set.
2158 if (EFI_ERROR (Status
)) {
2159 Status
= EFI_SUCCESS
;
2160 goto NextConfigAltResp
;
2163 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
2165 if (!GetElementsFromRequest (ConfigResp
)) {
2166 goto NextConfigAltResp
;
2170 // 4. Set the default configuration information or Validate current setting by parse IFR code.
2171 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2173 if (ActionType
== ACTION_SET_DEFAUTL_VALUE
) {
2175 // Set the default configuration information.
2177 Status
= gHiiConfigRouting
->RouteConfig (gHiiConfigRouting
, ConfigResp
, &Progress
);
2180 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2182 Status
= InternalHiiValidateCurrentSetting (ConfigResp
, HiiPackageList
, PackageListLength
, VarGuid
, VarName
, HiiHandle
);
2185 if (EFI_ERROR (Status
)) {
2191 // Free the allocated pacakge buffer and the got ConfigResp string.
2193 if (HiiPackageList
!= NULL
) {
2194 FreePool (HiiPackageList
);
2195 HiiPackageList
= NULL
;
2198 if (ConfigResp
!= NULL
) {
2199 FreePool (ConfigResp
);
2204 // Free the allocated buffer.
2212 FreePool (DevicePath
);
2216 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
2220 // Get and Skip ConfigHdr
2222 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2225 if (*StringPtr
== L
'\0') {
2230 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"
2231 // | 1 | StrLen (ConfigHdr) | 8 | 1 |
2233 ConfigAltHdr
= AllocateZeroPool ((1 + StringPtr
- StringHdr
+ 8 + 1) * sizeof (CHAR16
));
2234 if (ConfigAltHdr
== NULL
) {
2235 Status
= EFI_OUT_OF_RESOURCES
;
2238 StrCpy (ConfigAltHdr
, L
"&");
2239 StrnCat (ConfigAltHdr
, StringHdr
, StringPtr
- StringHdr
);
2240 StrCat (ConfigAltHdr
, L
"&ALTCFG=");
2243 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
2245 while ((StringHdr
= StrStr (StringPtr
, ConfigAltHdr
)) != NULL
) {
2246 StringPtr
= StringHdr
+ StrLen (ConfigAltHdr
);
2247 if (*StringPtr
== L
'\0') {
2253 // Free the allocated ConfigAltHdr string
2255 FreePool (ConfigAltHdr
);
2256 if (*StringPtr
== L
'\0') {
2261 // Find &GUID as the next ConfigHdr
2263 StringPtr
= StrStr (StringPtr
, L
"&GUID");
2264 if (StringPtr
== NULL
) {
2275 if (VarGuid
!= NULL
) {
2279 if (VarName
!= NULL
) {
2283 if (DevicePath
!= NULL
) {
2284 FreePool (DevicePath
);
2287 if (ConfigResp
!= NULL
) {
2288 FreePool (ConfigResp
);
2291 if (ConfigAltResp
!= NULL
) {
2292 FreePool (ConfigAltResp
);
2295 if (HiiPackageList
!= NULL
) {
2296 FreePool (HiiPackageList
);
2299 if (EFI_ERROR (Status
)) {
2307 Validate the current configuration by parsing HII form IFR opcode.
2309 NULL request string support depends on the ExportConfig interface of
2310 HiiConfigRouting protocol in UEFI specification.
2312 @param Request A null-terminated Unicode string in
2313 <MultiConfigRequest> format. It can be NULL.
2314 If it is NULL, all current configuration for the
2315 entirety of the current HII database will be validated.
2317 @retval TRUE Current configuration is valid.
2318 @retval FALSE Current configuration is invalid.
2322 HiiValidateSettings (
2323 IN CONST EFI_STRING Request OPTIONAL
2326 return InternalHiiIfrValueAction (Request
, 0, ACTION_VALIDATE_SETTING
);
2330 Reset the default value specified by DefaultId to the driver
2331 configuration got by Request string.
2333 NULL request string support depends on the ExportConfig interface of
2334 HiiConfigRouting protocol in UEFI specification.
2336 @param Request A null-terminated Unicode string in
2337 <MultiConfigRequest> format. It can be NULL.
2338 If it is NULL, all configuration for the
2339 entirety of the current HII database will be reset.
2340 @param DefaultId Specifies the type of defaults to retrieve.
2342 @retval TURE The default value is set successfully.
2343 @retval FALSE The default value can't be found and set.
2348 IN CONST EFI_STRING Request
, OPTIONAL
2352 return InternalHiiIfrValueAction (Request
, DefaultId
, ACTION_SET_DEFAUTL_VALUE
);
2356 Determines if two values in config strings match.
2358 Compares the substring between StartSearchString and StopSearchString in
2359 FirstString to the substring between StartSearchString and StopSearchString
2360 in SecondString. If the two substrings match, then TRUE is returned. If the
2361 two substrings do not match, then FALSE is returned.
2363 If FirstString is NULL, then ASSERT().
2364 If SecondString is NULL, then ASSERT().
2365 If StartSearchString is NULL, then ASSERT().
2366 If StopSearchString is NULL, then ASSERT().
2368 @param FirstString Pointer to the first Null-terminated Unicode string.
2369 @param SecondString Pointer to the second Null-terminated Unicode string.
2370 @param StartSearchString Pointer to the Null-terminated Unicode string that
2371 marks the start of the value string to compare.
2372 @param StopSearchString Pointer to the Null-terminated Unicode string that
2373 marks the end of the value string to compare.
2375 @retval FALSE StartSearchString is not present in FirstString.
2376 @retval FALSE StartSearchString is not present in SecondString.
2377 @retval FALSE StopSearchString is not present in FirstString.
2378 @retval FALSE StopSearchString is not present in SecondString.
2379 @retval FALSE The length of the substring in FirstString is not the
2380 same length as the substring in SecondString.
2381 @retval FALSE The value string in FirstString does not matche the
2382 value string in SecondString.
2383 @retval TRUE The value string in FirstString matches the value
2384 string in SecondString.
2389 InternalHiiCompareSubString (
2390 IN CHAR16
*FirstString
,
2391 IN CHAR16
*SecondString
,
2392 IN CHAR16
*StartSearchString
,
2393 IN CHAR16
*StopSearchString
2396 CHAR16
*EndFirstString
;
2397 CHAR16
*EndSecondString
;
2399 ASSERT (FirstString
!= NULL
);
2400 ASSERT (SecondString
!= NULL
);
2401 ASSERT (StartSearchString
!= NULL
);
2402 ASSERT (StopSearchString
!= NULL
);
2404 FirstString
= StrStr (FirstString
, StartSearchString
);
2405 if (FirstString
== NULL
) {
2409 SecondString
= StrStr (SecondString
, StartSearchString
);
2410 if (SecondString
== NULL
) {
2414 EndFirstString
= StrStr (FirstString
, StopSearchString
);
2415 if (EndFirstString
== NULL
) {
2419 EndSecondString
= StrStr (SecondString
, StopSearchString
);
2420 if (EndSecondString
== NULL
) {
2424 if ((EndFirstString
- FirstString
) != (EndSecondString
- SecondString
)) {
2428 return (BOOLEAN
)(StrnCmp (FirstString
, SecondString
, EndFirstString
- FirstString
) == 0);
2432 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
2434 If ConfigHdr is NULL, then ASSERT().
2436 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
2437 @param[in] Guid GUID of the storage.
2438 @param[in] Name NAME of the storage.
2440 @retval TRUE Routing information matches <ConfigHdr>.
2441 @retval FALSE Routing information does not match <ConfigHdr>.
2446 HiiIsConfigHdrMatch (
2447 IN CONST EFI_STRING ConfigHdr
,
2448 IN CONST EFI_GUID
*Guid
, OPTIONAL
2449 IN CONST CHAR16
*Name OPTIONAL
2452 EFI_STRING CompareConfigHdr
;
2455 ASSERT (ConfigHdr
!= NULL
);
2458 // Use Guid and Name to generate a <ConfigHdr> string
2460 CompareConfigHdr
= HiiConstructConfigHdr (Guid
, Name
, NULL
);
2461 if (CompareConfigHdr
== NULL
) {
2468 // Compare GUID value strings
2470 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"GUID=", L
"&NAME=");
2473 if (Result
&& Name
!= NULL
) {
2475 // Compare NAME value strings
2477 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"&NAME=", L
"&PATH=");
2481 // Free the <ConfigHdr> string
2483 FreePool (CompareConfigHdr
);
2489 Retrieves uncommitted data from the Form Browser and converts it to a binary
2492 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2493 parameter that may be NULL.
2494 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2495 is an optional parameter that may be NULL.
2496 @param[in] BufferSize Length in bytes of buffer to hold retrieved data.
2497 @param[out] Buffer Buffer of data to be updated.
2499 @retval FALSE The uncommitted data could not be retrieved.
2500 @retval TRUE The uncommitted data was retrieved.
2506 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2507 IN CONST CHAR16
*VariableName
, OPTIONAL
2508 IN UINTN BufferSize
,
2512 EFI_STRING ResultsData
;
2514 EFI_STRING ConfigResp
;
2519 // Retrieve the results data from the Browser Callback
2521 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, NULL
);
2522 if (ResultsData
== NULL
) {
2527 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
2529 Size
= (StrLen (mConfigHdrTemplate
) + 1) * sizeof (CHAR16
);
2530 Size
= Size
+ (StrLen (ResultsData
) + 1) * sizeof (CHAR16
);
2531 ConfigResp
= AllocateZeroPool (Size
);
2532 UnicodeSPrint (ConfigResp
, Size
, L
"%s&%s", mConfigHdrTemplate
, ResultsData
);
2535 // Free the allocated buffer
2537 FreePool (ResultsData
);
2538 if (ConfigResp
== NULL
) {
2543 // Convert <ConfigResp> to a buffer
2545 Status
= gHiiConfigRouting
->ConfigToBlock (
2553 // Free the allocated buffer
2555 FreePool (ConfigResp
);
2557 if (EFI_ERROR (Status
)) {
2565 Updates uncommitted data in the Form Browser.
2567 If Buffer is NULL, then ASSERT().
2569 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2570 parameter that may be NULL.
2571 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2572 is an optional parameter that may be NULL.
2573 @param[in] BufferSize Length, in bytes, of Buffer.
2574 @param[in] Buffer Buffer of data to commit.
2575 @param[in] RequestElement An optional field to specify which part of the
2576 buffer data will be send back to Browser. If NULL,
2577 the whole buffer of data will be committed to
2579 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
2581 @retval FALSE The uncommitted data could not be updated.
2582 @retval TRUE The uncommitted data was updated.
2588 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2589 IN CONST CHAR16
*VariableName
, OPTIONAL
2590 IN UINTN BufferSize
,
2591 IN CONST UINT8
*Buffer
,
2592 IN CONST CHAR16
*RequestElement OPTIONAL
2596 EFI_STRING ConfigRequest
;
2597 EFI_STRING ConfigResp
;
2598 EFI_STRING ResultsData
;
2600 ASSERT (Buffer
!= NULL
);
2603 // Construct <ConfigRequest>
2605 if (RequestElement
== NULL
) {
2607 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2608 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2610 Size
= (StrLen (mConfigHdrTemplate
) + 32 + 1) * sizeof (CHAR16
);
2611 ConfigRequest
= AllocateZeroPool (Size
);
2612 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate
, (UINT64
)BufferSize
);
2615 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2616 // followed by <RequestElement> followed by a Null-terminator
2618 Size
= StrLen (mConfigHdrTemplate
) * sizeof (CHAR16
);
2619 Size
= Size
+ (StrLen (RequestElement
) + 1) * sizeof (CHAR16
);
2620 ConfigRequest
= AllocateZeroPool (Size
);
2621 UnicodeSPrint (ConfigRequest
, Size
, L
"%s%s", mConfigHdrTemplate
, RequestElement
);
2623 if (ConfigRequest
== NULL
) {
2628 // Convert <ConfigRequest> to <ConfigResp>
2630 ConfigResp
= InternalHiiBlockToConfig (ConfigRequest
, Buffer
, BufferSize
);
2631 FreePool (ConfigRequest
);
2632 if (ConfigResp
== NULL
) {
2637 // Set data in the uncommitted browser state information
2639 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, ConfigResp
+ StrLen(mConfigHdrTemplate
) + 1);
2640 FreePool (ConfigResp
);
2642 return (BOOLEAN
)(ResultsData
!= NULL
);
2645 /////////////////////////////////////////
2646 /////////////////////////////////////////
2648 /////////////////////////////////////////
2649 /////////////////////////////////////////
2651 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
2657 } HII_LIB_OPCODE_BUFFER
;
2660 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
2662 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth
[] = {
2663 1, // EFI_IFR_TYPE_NUM_SIZE_8
2664 2, // EFI_IFR_TYPE_NUM_SIZE_16
2665 4, // EFI_IFR_TYPE_NUM_SIZE_32
2666 8, // EFI_IFR_TYPE_NUM_SIZE_64
2667 1, // EFI_IFR_TYPE_BOOLEAN
2668 3, // EFI_IFR_TYPE_TIME
2669 4, // EFI_IFR_TYPE_DATE
2670 2 // EFI_IFR_TYPE_STRING
2674 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
2675 HiiFreeOpCodeHandle().
2677 @retval NULL There are not enough resources to allocate a new OpCode Handle.
2678 @retval Other A new OpCode handle.
2683 HiiAllocateOpCodeHandle (
2687 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2689 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER
));
2690 if (OpCodeBuffer
== NULL
) {
2693 OpCodeBuffer
->Buffer
= (UINT8
*)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE
);
2694 if (OpCodeBuffer
->Buffer
== NULL
) {
2695 FreePool (OpCodeBuffer
);
2698 OpCodeBuffer
->BufferSize
= HII_LIB_OPCODE_ALLOCATION_SIZE
;
2699 OpCodeBuffer
->Position
= 0;
2700 return (VOID
*)OpCodeBuffer
;
2704 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
2705 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
2706 Handle are also freed.
2708 If OpCodeHandle is NULL, then ASSERT().
2710 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2715 HiiFreeOpCodeHandle (
2719 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2721 ASSERT (OpCodeHandle
!= NULL
);
2723 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2724 if (OpCodeBuffer
->Buffer
!= NULL
) {
2725 FreePool (OpCodeBuffer
->Buffer
);
2727 FreePool (OpCodeBuffer
);
2731 Internal function gets the current position of opcode buffer.
2733 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2735 @return Current position of opcode buffer.
2739 InternalHiiOpCodeHandlePosition (
2740 IN VOID
*OpCodeHandle
2743 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Position
;
2747 Internal function gets the start pointer of opcode buffer.
2749 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2751 @return Pointer to the opcode buffer base.
2755 InternalHiiOpCodeHandleBuffer (
2756 IN VOID
*OpCodeHandle
2759 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Buffer
;
2763 Internal function reserves the enough buffer for current opcode.
2764 When the buffer is not enough, Opcode buffer will be extended.
2766 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2767 @param[in] Size Size of current opcode.
2769 @return Pointer to the current opcode.
2773 InternalHiiGrowOpCodeHandle (
2774 IN VOID
*OpCodeHandle
,
2778 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2781 ASSERT (OpCodeHandle
!= NULL
);
2783 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2784 if (OpCodeBuffer
->Position
+ Size
> OpCodeBuffer
->BufferSize
) {
2785 Buffer
= ReallocatePool (
2786 OpCodeBuffer
->BufferSize
,
2787 OpCodeBuffer
->BufferSize
+ (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
),
2788 OpCodeBuffer
->Buffer
2790 ASSERT (Buffer
!= NULL
);
2791 OpCodeBuffer
->Buffer
= Buffer
;
2792 OpCodeBuffer
->BufferSize
+= (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
);
2794 Buffer
= OpCodeBuffer
->Buffer
+ OpCodeBuffer
->Position
;
2795 OpCodeBuffer
->Position
+= Size
;
2800 Internal function creates opcode based on the template opcode.
2802 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2803 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2804 @param[in] OpCode OpCode IFR value.
2805 @param[in] OpCodeSize Size of opcode.
2806 @param[in] ExtensionSize Size of extended opcode.
2807 @param[in] Scope Scope bit of opcode.
2809 @return Pointer to the current opcode with opcode data.
2813 InternalHiiCreateOpCodeExtended (
2814 IN VOID
*OpCodeHandle
,
2815 IN VOID
*OpCodeTemplate
,
2817 IN UINTN OpCodeSize
,
2818 IN UINTN ExtensionSize
,
2822 EFI_IFR_OP_HEADER
*Header
;
2825 ASSERT (OpCodeTemplate
!= NULL
);
2826 ASSERT ((OpCodeSize
+ ExtensionSize
) <= 0x7F);
2828 Header
= (EFI_IFR_OP_HEADER
*)OpCodeTemplate
;
2829 Header
->OpCode
= OpCode
;
2830 Header
->Scope
= Scope
;
2831 Header
->Length
= (UINT8
)(OpCodeSize
+ ExtensionSize
);
2832 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, Header
->Length
);
2833 return (UINT8
*)CopyMem (Buffer
, Header
, OpCodeSize
);
2837 Internal function creates opcode based on the template opcode for the normal opcode.
2839 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2840 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2841 @param[in] OpCode OpCode IFR value.
2842 @param[in] OpCodeSize Size of opcode.
2844 @return Pointer to the current opcode with opcode data.
2848 InternalHiiCreateOpCode (
2849 IN VOID
*OpCodeHandle
,
2850 IN VOID
*OpCodeTemplate
,
2855 return InternalHiiCreateOpCodeExtended (OpCodeHandle
, OpCodeTemplate
, OpCode
, OpCodeSize
, 0, 0);
2859 Append raw opcodes to an OpCodeHandle.
2861 If OpCodeHandle is NULL, then ASSERT().
2862 If RawBuffer is NULL, then ASSERT();
2864 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2865 @param[in] RawBuffer Buffer of opcodes to append.
2866 @param[in] RawBufferSize The size, in bytes, of Buffer.
2868 @retval NULL There is not enough space left in Buffer to add the opcode.
2869 @retval Other A pointer to the appended opcodes.
2874 HiiCreateRawOpCodes (
2875 IN VOID
*OpCodeHandle
,
2876 IN UINT8
*RawBuffer
,
2877 IN UINTN RawBufferSize
2882 ASSERT (RawBuffer
!= NULL
);
2884 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, RawBufferSize
);
2885 return (UINT8
*)CopyMem (Buffer
, RawBuffer
, RawBufferSize
);
2889 Append opcodes from one OpCode Handle to another OpCode handle.
2891 If OpCodeHandle is NULL, then ASSERT().
2892 If RawOpCodeHandle is NULL, then ASSERT();
2894 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2895 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
2897 @retval NULL There is not enough space left in Buffer to add the opcode.
2898 @retval Other A pointer to the appended opcodes.
2903 InternalHiiAppendOpCodes (
2904 IN VOID
*OpCodeHandle
,
2905 IN VOID
*RawOpCodeHandle
2908 HII_LIB_OPCODE_BUFFER
*RawOpCodeBuffer
;
2910 ASSERT (RawOpCodeHandle
!= NULL
);
2912 RawOpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)RawOpCodeHandle
;
2913 return HiiCreateRawOpCodes (OpCodeHandle
, RawOpCodeBuffer
->Buffer
, RawOpCodeBuffer
->Position
);
2917 Create EFI_IFR_END_OP opcode.
2919 If OpCodeHandle is NULL, then ASSERT().
2921 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2923 @retval NULL There is not enough space left in Buffer to add the opcode.
2924 @retval Other A pointer to the created opcode.
2929 HiiCreateEndOpCode (
2930 IN VOID
*OpCodeHandle
2935 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_END_OP
, sizeof (OpCode
));
2939 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
2941 If OpCodeHandle is NULL, then ASSERT().
2942 If Type is invalid, then ASSERT().
2943 If Flags is invalid, then ASSERT().
2945 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2946 @param[in] StringId StringId for the option
2947 @param[in] Flags Flags for the option
2948 @param[in] Type Type for the option
2949 @param[in] Value Value for the option
2951 @retval NULL There is not enough space left in Buffer to add the opcode.
2952 @retval Other A pointer to the created opcode.
2957 HiiCreateOneOfOptionOpCode (
2958 IN VOID
*OpCodeHandle
,
2965 EFI_IFR_ONE_OF_OPTION OpCode
;
2967 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
2969 ZeroMem (&OpCode
, sizeof (OpCode
));
2970 OpCode
.Option
= StringId
;
2971 OpCode
.Flags
= (UINT8
) (Flags
& (EFI_IFR_OPTION_DEFAULT
| EFI_IFR_OPTION_DEFAULT_MFG
));
2973 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
2975 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OPTION_OP
, OFFSET_OF(EFI_IFR_ONE_OF_OPTION
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
2979 Create EFI_IFR_DEFAULT_OP opcode.
2981 If OpCodeHandle is NULL, then ASSERT().
2982 If Type is invalid, then ASSERT().
2984 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2985 @param[in] DefaultId DefaultId for the default
2986 @param[in] Type Type for the default
2987 @param[in] Value Value for the default
2989 @retval NULL There is not enough space left in Buffer to add the opcode.
2990 @retval Other A pointer to the created opcode.
2995 HiiCreateDefaultOpCode (
2996 IN VOID
*OpCodeHandle
,
2997 IN UINT16 DefaultId
,
3002 EFI_IFR_DEFAULT OpCode
;
3004 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
3006 ZeroMem (&OpCode
, sizeof (OpCode
));
3008 OpCode
.DefaultId
= DefaultId
;
3009 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
3011 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DEFAULT_OP
, OFFSET_OF(EFI_IFR_DEFAULT
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
3015 Create EFI_IFR_GUID opcode.
3017 If OpCodeHandle is NULL, then ASSERT().
3018 If Guid is NULL, then ASSERT().
3019 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
3021 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3022 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
3023 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
3024 optional parameter that may be NULL. If this
3025 parameter is NULL, then the GUID extension
3026 region of the created opcode is filled with zeros.
3027 If this parameter is not NULL, then the GUID
3028 extension region of GuidData will be copied to
3029 the GUID extension region of the created opcode.
3030 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
3031 must be >= sizeof(EFI_IFR_GUID).
3033 @retval NULL There is not enough space left in Buffer to add the opcode.
3034 @retval Other A pointer to the created opcode.
3039 HiiCreateGuidOpCode (
3040 IN VOID
*OpCodeHandle
,
3041 IN CONST EFI_GUID
*Guid
,
3042 IN CONST VOID
*GuidOpCode
, OPTIONAL
3046 EFI_IFR_GUID OpCode
;
3047 EFI_IFR_GUID
*OpCodePointer
;
3049 ASSERT (Guid
!= NULL
);
3050 ASSERT (OpCodeSize
>= sizeof (OpCode
));
3052 ZeroMem (&OpCode
, sizeof (OpCode
));
3053 CopyGuid ((EFI_GUID
*)(VOID
*)&OpCode
.Guid
, Guid
);
3055 OpCodePointer
= (EFI_IFR_GUID
*)InternalHiiCreateOpCodeExtended (
3060 OpCodeSize
- sizeof (OpCode
),
3063 if (OpCodePointer
!= NULL
&& GuidOpCode
!= NULL
) {
3064 CopyMem (OpCodePointer
+ 1, (EFI_IFR_GUID
*)GuidOpCode
+ 1, OpCodeSize
- sizeof (OpCode
));
3066 return (UINT8
*)OpCodePointer
;
3070 Create EFI_IFR_ACTION_OP opcode.
3072 If OpCodeHandle is NULL, then ASSERT().
3073 If any reserved bits are set in QuestionFlags, then ASSERT().
3075 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3076 @param[in] QuestionId Question ID
3077 @param[in] Prompt String ID for Prompt
3078 @param[in] Help String ID for Help
3079 @param[in] QuestionFlags Flags in Question Header
3080 @param[in] QuestionConfig String ID for configuration
3082 @retval NULL There is not enough space left in Buffer to add the opcode.
3083 @retval Other A pointer to the created opcode.
3088 HiiCreateActionOpCode (
3089 IN VOID
*OpCodeHandle
,
3090 IN EFI_QUESTION_ID QuestionId
,
3091 IN EFI_STRING_ID Prompt
,
3092 IN EFI_STRING_ID Help
,
3093 IN UINT8 QuestionFlags
,
3094 IN EFI_STRING_ID QuestionConfig
3097 EFI_IFR_ACTION OpCode
;
3099 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3101 ZeroMem (&OpCode
, sizeof (OpCode
));
3102 OpCode
.Question
.QuestionId
= QuestionId
;
3103 OpCode
.Question
.Header
.Prompt
= Prompt
;
3104 OpCode
.Question
.Header
.Help
= Help
;
3105 OpCode
.Question
.Flags
= QuestionFlags
;
3106 OpCode
.QuestionConfig
= QuestionConfig
;
3108 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ACTION_OP
, sizeof (OpCode
));
3112 Create EFI_IFR_SUBTITLE_OP opcode.
3114 If OpCodeHandle is NULL, then ASSERT().
3115 If any reserved bits are set in Flags, then ASSERT().
3116 If Scope > 1, then ASSERT().
3118 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3119 @param[in] Prompt String ID for Prompt
3120 @param[in] Help String ID for Help
3121 @param[in] Flags Subtitle opcode flags
3122 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
3123 0 if this opcode is within the current scope.
3125 @retval NULL There is not enough space left in Buffer to add the opcode.
3126 @retval Other A pointer to the created opcode.
3131 HiiCreateSubTitleOpCode (
3132 IN VOID
*OpCodeHandle
,
3133 IN EFI_STRING_ID Prompt
,
3134 IN EFI_STRING_ID Help
,
3139 EFI_IFR_SUBTITLE OpCode
;
3141 ASSERT (Scope
<= 1);
3142 ASSERT ((Flags
& (~(EFI_IFR_FLAGS_HORIZONTAL
))) == 0);
3144 ZeroMem (&OpCode
, sizeof (OpCode
));
3145 OpCode
.Statement
.Prompt
= Prompt
;
3146 OpCode
.Statement
.Help
= Help
;
3147 OpCode
.Flags
= Flags
;
3149 return InternalHiiCreateOpCodeExtended (
3152 EFI_IFR_SUBTITLE_OP
,
3160 Create EFI_IFR_REF_OP opcode.
3162 If OpCodeHandle is NULL, then ASSERT().
3163 If any reserved bits are set in QuestionFlags, then ASSERT().
3165 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3166 @param[in] FormId Destination Form ID
3167 @param[in] Prompt String ID for Prompt
3168 @param[in] Help String ID for Help
3169 @param[in] QuestionFlags Flags in Question Header
3170 @param[in] QuestionId Question ID
3172 @retval NULL There is not enough space left in Buffer to add the opcode.
3173 @retval Other A pointer to the created opcode.
3178 HiiCreateGotoOpCode (
3179 IN VOID
*OpCodeHandle
,
3180 IN EFI_FORM_ID FormId
,
3181 IN EFI_STRING_ID Prompt
,
3182 IN EFI_STRING_ID Help
,
3183 IN UINT8 QuestionFlags
,
3184 IN EFI_QUESTION_ID QuestionId
3189 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3191 ZeroMem (&OpCode
, sizeof (OpCode
));
3192 OpCode
.Question
.Header
.Prompt
= Prompt
;
3193 OpCode
.Question
.Header
.Help
= Help
;
3194 OpCode
.Question
.QuestionId
= QuestionId
;
3195 OpCode
.Question
.Flags
= QuestionFlags
;
3196 OpCode
.FormId
= FormId
;
3198 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, sizeof (OpCode
));
3202 Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.
3204 When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.
3205 When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.
3206 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.
3207 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.
3209 If OpCodeHandle is NULL, then ASSERT().
3210 If any reserved bits are set in QuestionFlags, then ASSERT().
3212 @param[in] OpCodeHandle The handle to the buffer of opcodes.
3213 @param[in] RefFormId The Destination Form ID.
3214 @param[in] Prompt The string ID for Prompt.
3215 @param[in] Help The string ID for Help.
3216 @param[in] QuestionFlags The flags in Question Header
3217 @param[in] QuestionId Question ID.
3218 @param[in] RefQuestionId The question on the form to which this link is referring.
3219 If its value is zero, then the link refers to the top of the form.
3220 @param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is
3221 zero, then the link is to the current form set.
3222 @param[in] RefDevicePath The string identifier that specifies the string containing the text representation of
3223 the device path to which the form set containing the form specified by FormId.
3224 If its value is zero, then the link refers to the current page.
3226 @retval NULL There is not enough space left in Buffer to add the opcode.
3227 @retval Other A pointer to the created opcode.
3232 HiiCreateGotoExOpCode (
3233 IN VOID
*OpCodeHandle
,
3234 IN EFI_FORM_ID RefFormId
,
3235 IN EFI_STRING_ID Prompt
,
3236 IN EFI_STRING_ID Help
,
3237 IN UINT8 QuestionFlags
,
3238 IN EFI_QUESTION_ID QuestionId
,
3239 IN EFI_QUESTION_ID RefQuestionId
,
3240 IN EFI_GUID
*RefFormSetId
, OPTIONAL
3241 IN EFI_STRING_ID RefDevicePath
3244 EFI_IFR_REF4 OpCode
;
3247 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3249 ZeroMem (&OpCode
, sizeof (OpCode
));
3250 OpCode
.Question
.Header
.Prompt
= Prompt
;
3251 OpCode
.Question
.Header
.Help
= Help
;
3252 OpCode
.Question
.QuestionId
= QuestionId
;
3253 OpCode
.Question
.Flags
= QuestionFlags
;
3254 OpCode
.FormId
= RefFormId
;
3255 OpCode
.QuestionId
= RefQuestionId
;
3256 OpCode
.DevicePath
= RefDevicePath
;
3257 if (RefFormSetId
!= NULL
) {
3258 CopyMem (&OpCode
.FormSetId
, RefFormSetId
, sizeof (OpCode
.FormSetId
));
3262 // Cacluate OpCodeSize based on the input Ref value.
3263 // Try to use the small OpCode to save size.
3265 OpCodeSize
= sizeof (EFI_IFR_REF
);
3266 if (RefDevicePath
!= 0) {
3267 OpCodeSize
= sizeof (EFI_IFR_REF4
);
3268 } else if (RefFormSetId
!= NULL
) {
3269 OpCodeSize
= sizeof (EFI_IFR_REF3
);
3270 } else if (RefQuestionId
!= 0) {
3271 OpCodeSize
= sizeof (EFI_IFR_REF2
);
3274 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, OpCodeSize
);
3278 Create EFI_IFR_CHECKBOX_OP opcode.
3280 If OpCodeHandle is NULL, then ASSERT().
3281 If any reserved bits are set in QuestionFlags, then ASSERT().
3282 If any reserved bits are set in CheckBoxFlags, then ASSERT().
3284 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3285 @param[in] QuestionId Question ID
3286 @param[in] VarStoreId Storage ID
3287 @param[in] VarOffset Offset in Storage
3288 @param[in] Prompt String ID for Prompt
3289 @param[in] Help String ID for Help
3290 @param[in] QuestionFlags Flags in Question Header
3291 @param[in] CheckBoxFlags Flags for checkbox opcode
3292 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3293 is an optional parameter that may be NULL.
3295 @retval NULL There is not enough space left in Buffer to add the opcode.
3296 @retval Other A pointer to the created opcode.
3301 HiiCreateCheckBoxOpCode (
3302 IN VOID
*OpCodeHandle
,
3303 IN EFI_QUESTION_ID QuestionId
,
3304 IN EFI_VARSTORE_ID VarStoreId
,
3305 IN UINT16 VarOffset
,
3306 IN EFI_STRING_ID Prompt
,
3307 IN EFI_STRING_ID Help
,
3308 IN UINT8 QuestionFlags
,
3309 IN UINT8 CheckBoxFlags
,
3310 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3313 EFI_IFR_CHECKBOX OpCode
;
3316 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3318 ZeroMem (&OpCode
, sizeof (OpCode
));
3319 OpCode
.Question
.QuestionId
= QuestionId
;
3320 OpCode
.Question
.VarStoreId
= VarStoreId
;
3321 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3322 OpCode
.Question
.Header
.Prompt
= Prompt
;
3323 OpCode
.Question
.Header
.Help
= Help
;
3324 OpCode
.Question
.Flags
= QuestionFlags
;
3325 OpCode
.Flags
= CheckBoxFlags
;
3327 if (DefaultsOpCodeHandle
== NULL
) {
3328 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
));
3331 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3332 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
), 0, 1);
3333 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3334 HiiCreateEndOpCode (OpCodeHandle
);
3335 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3339 Create EFI_IFR_NUMERIC_OP opcode.
3341 If OpCodeHandle is NULL, then ASSERT().
3342 If any reserved bits are set in QuestionFlags, then ASSERT().
3343 If any reserved bits are set in NumericFlags, then ASSERT().
3345 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3346 @param[in] QuestionId Question ID
3347 @param[in] VarStoreId Storage ID
3348 @param[in] VarOffset Offset in Storage
3349 @param[in] Prompt String ID for Prompt
3350 @param[in] Help String ID for Help
3351 @param[in] QuestionFlags Flags in Question Header
3352 @param[in] NumericFlags Flags for numeric opcode
3353 @param[in] Minimum Numeric minimum value
3354 @param[in] Maximum Numeric maximum value
3355 @param[in] Step Numeric step for edit
3356 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3357 is an optional parameter that may be NULL.
3359 @retval NULL There is not enough space left in Buffer to add the opcode.
3360 @retval Other A pointer to the created opcode.
3365 HiiCreateNumericOpCode (
3366 IN VOID
*OpCodeHandle
,
3367 IN EFI_QUESTION_ID QuestionId
,
3368 IN EFI_VARSTORE_ID VarStoreId
,
3369 IN UINT16 VarOffset
,
3370 IN EFI_STRING_ID Prompt
,
3371 IN EFI_STRING_ID Help
,
3372 IN UINT8 QuestionFlags
,
3373 IN UINT8 NumericFlags
,
3377 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3380 EFI_IFR_NUMERIC OpCode
;
3384 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3387 ZeroMem (&OpCode
, sizeof (OpCode
));
3388 OpCode
.Question
.QuestionId
= QuestionId
;
3389 OpCode
.Question
.VarStoreId
= VarStoreId
;
3390 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3391 OpCode
.Question
.Header
.Prompt
= Prompt
;
3392 OpCode
.Question
.Header
.Help
= Help
;
3393 OpCode
.Question
.Flags
= QuestionFlags
;
3394 OpCode
.Flags
= NumericFlags
;
3396 switch (NumericFlags
& EFI_IFR_NUMERIC_SIZE
) {
3397 case EFI_IFR_NUMERIC_SIZE_1
:
3398 OpCode
.data
.u8
.MinValue
= (UINT8
)Minimum
;
3399 OpCode
.data
.u8
.MaxValue
= (UINT8
)Maximum
;
3400 OpCode
.data
.u8
.Step
= (UINT8
)Step
;
3404 case EFI_IFR_NUMERIC_SIZE_2
:
3405 OpCode
.data
.u16
.MinValue
= (UINT16
)Minimum
;
3406 OpCode
.data
.u16
.MaxValue
= (UINT16
)Maximum
;
3407 OpCode
.data
.u16
.Step
= (UINT16
)Step
;
3411 case EFI_IFR_NUMERIC_SIZE_4
:
3412 OpCode
.data
.u32
.MinValue
= (UINT32
)Minimum
;
3413 OpCode
.data
.u32
.MaxValue
= (UINT32
)Maximum
;
3414 OpCode
.data
.u32
.Step
= (UINT32
)Step
;
3418 case EFI_IFR_NUMERIC_SIZE_8
:
3419 OpCode
.data
.u64
.MinValue
= Minimum
;
3420 OpCode
.data
.u64
.MaxValue
= Maximum
;
3421 OpCode
.data
.u64
.Step
= Step
;
3426 Length
+= OFFSET_OF (EFI_IFR_NUMERIC
, data
);
3428 if (DefaultsOpCodeHandle
== NULL
) {
3429 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
);
3432 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3433 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
, 0, 1);
3434 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3435 HiiCreateEndOpCode (OpCodeHandle
);
3436 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3440 Create EFI_IFR_STRING_OP opcode.
3442 If OpCodeHandle is NULL, then ASSERT().
3443 If any reserved bits are set in QuestionFlags, then ASSERT().
3444 If any reserved bits are set in StringFlags, then ASSERT().
3446 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3447 @param[in] QuestionId Question ID
3448 @param[in] VarStoreId Storage ID
3449 @param[in] VarOffset Offset in Storage
3450 @param[in] Prompt String ID for Prompt
3451 @param[in] Help String ID for Help
3452 @param[in] QuestionFlags Flags in Question Header
3453 @param[in] StringFlags Flags for string opcode
3454 @param[in] MinSize String minimum length
3455 @param[in] MaxSize String maximum length
3456 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3457 is an optional parameter that may be NULL.
3459 @retval NULL There is not enough space left in Buffer to add the opcode.
3460 @retval Other A pointer to the created opcode.
3465 HiiCreateStringOpCode (
3466 IN VOID
*OpCodeHandle
,
3467 IN EFI_QUESTION_ID QuestionId
,
3468 IN EFI_VARSTORE_ID VarStoreId
,
3469 IN UINT16 VarOffset
,
3470 IN EFI_STRING_ID Prompt
,
3471 IN EFI_STRING_ID Help
,
3472 IN UINT8 QuestionFlags
,
3473 IN UINT8 StringFlags
,
3476 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3479 EFI_IFR_STRING OpCode
;
3482 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3484 ZeroMem (&OpCode
, sizeof (OpCode
));
3485 OpCode
.Question
.Header
.Prompt
= Prompt
;
3486 OpCode
.Question
.Header
.Help
= Help
;
3487 OpCode
.Question
.QuestionId
= QuestionId
;
3488 OpCode
.Question
.VarStoreId
= VarStoreId
;
3489 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3490 OpCode
.Question
.Flags
= QuestionFlags
;
3491 OpCode
.MinSize
= MinSize
;
3492 OpCode
.MaxSize
= MaxSize
;
3493 OpCode
.Flags
= (UINT8
) (StringFlags
& EFI_IFR_STRING_MULTI_LINE
);
3495 if (DefaultsOpCodeHandle
== NULL
) {
3496 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
));
3499 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3500 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
), 0, 1);
3501 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3502 HiiCreateEndOpCode (OpCodeHandle
);
3503 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3507 Create EFI_IFR_ONE_OF_OP opcode.
3509 If OpCodeHandle is NULL, then ASSERT().
3510 If any reserved bits are set in QuestionFlags, then ASSERT().
3511 If any reserved bits are set in OneOfFlags, then ASSERT().
3513 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3514 @param[in] QuestionId Question ID
3515 @param[in] VarStoreId Storage ID
3516 @param[in] VarOffset Offset in Storage
3517 @param[in] Prompt String ID for Prompt
3518 @param[in] Help String ID for Help
3519 @param[in] QuestionFlags Flags in Question Header
3520 @param[in] OneOfFlags Flags for oneof opcode
3521 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3522 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3523 is an optional parameter that may be NULL.
3525 @retval NULL There is not enough space left in Buffer to add the opcode.
3526 @retval Other A pointer to the created opcode.
3531 HiiCreateOneOfOpCode (
3532 IN VOID
*OpCodeHandle
,
3533 IN EFI_QUESTION_ID QuestionId
,
3534 IN EFI_VARSTORE_ID VarStoreId
,
3535 IN UINT16 VarOffset
,
3536 IN EFI_STRING_ID Prompt
,
3537 IN EFI_STRING_ID Help
,
3538 IN UINT8 QuestionFlags
,
3539 IN UINT8 OneOfFlags
,
3540 IN VOID
*OptionsOpCodeHandle
,
3541 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3544 EFI_IFR_ONE_OF OpCode
;
3548 ASSERT (OptionsOpCodeHandle
!= NULL
);
3549 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3551 ZeroMem (&OpCode
, sizeof (OpCode
));
3552 OpCode
.Question
.Header
.Prompt
= Prompt
;
3553 OpCode
.Question
.Header
.Help
= Help
;
3554 OpCode
.Question
.QuestionId
= QuestionId
;
3555 OpCode
.Question
.VarStoreId
= VarStoreId
;
3556 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3557 OpCode
.Question
.Flags
= QuestionFlags
;
3558 OpCode
.Flags
= OneOfFlags
;
3560 Length
= OFFSET_OF (EFI_IFR_ONE_OF
, data
);
3561 Length
+= (1 << (OneOfFlags
& EFI_IFR_NUMERIC_SIZE
)) * 3;
3563 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3564 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OP
, Length
, 0, 1);
3565 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3566 if (DefaultsOpCodeHandle
!= NULL
) {
3567 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3569 HiiCreateEndOpCode (OpCodeHandle
);
3570 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3574 Create EFI_IFR_ORDERED_LIST_OP opcode.
3576 If OpCodeHandle is NULL, then ASSERT().
3577 If any reserved bits are set in QuestionFlags, then ASSERT().
3578 If any reserved bits are set in OrderedListFlags, then ASSERT().
3580 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3581 @param[in] QuestionId Question ID
3582 @param[in] VarStoreId Storage ID
3583 @param[in] VarOffset Offset in Storage
3584 @param[in] Prompt String ID for Prompt
3585 @param[in] Help String ID for Help
3586 @param[in] QuestionFlags Flags in Question Header
3587 @param[in] OrderedListFlags Flags for ordered list opcode
3588 @param[in] DataType Type for option value
3589 @param[in] MaxContainers Maximum count for options in this ordered list
3590 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3591 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3592 is an optional parameter that may be NULL.
3594 @retval NULL There is not enough space left in Buffer to add the opcode.
3595 @retval Other A pointer to the created opcode.
3600 HiiCreateOrderedListOpCode (
3601 IN VOID
*OpCodeHandle
,
3602 IN EFI_QUESTION_ID QuestionId
,
3603 IN EFI_VARSTORE_ID VarStoreId
,
3604 IN UINT16 VarOffset
,
3605 IN EFI_STRING_ID Prompt
,
3606 IN EFI_STRING_ID Help
,
3607 IN UINT8 QuestionFlags
,
3608 IN UINT8 OrderedListFlags
,
3610 IN UINT8 MaxContainers
,
3611 IN VOID
*OptionsOpCodeHandle
,
3612 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3615 EFI_IFR_ORDERED_LIST OpCode
;
3618 ASSERT (OptionsOpCodeHandle
!= NULL
);
3619 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3621 ZeroMem (&OpCode
, sizeof (OpCode
));
3622 OpCode
.Question
.Header
.Prompt
= Prompt
;
3623 OpCode
.Question
.Header
.Help
= Help
;
3624 OpCode
.Question
.QuestionId
= QuestionId
;
3625 OpCode
.Question
.VarStoreId
= VarStoreId
;
3626 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3627 OpCode
.Question
.Flags
= QuestionFlags
;
3628 OpCode
.MaxContainers
= MaxContainers
;
3629 OpCode
.Flags
= OrderedListFlags
;
3631 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3632 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ORDERED_LIST_OP
, sizeof (OpCode
), 0, 1);
3633 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3634 if (DefaultsOpCodeHandle
!= NULL
) {
3635 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3637 HiiCreateEndOpCode (OpCodeHandle
);
3638 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3642 Create EFI_IFR_TEXT_OP opcode.
3644 If OpCodeHandle is NULL, then ASSERT().
3646 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3647 @param[in] Prompt String ID for Prompt.
3648 @param[in] Help String ID for Help.
3649 @param[in] TextTwo String ID for TextTwo.
3651 @retval NULL There is not enough space left in Buffer to add the opcode.
3652 @retval Other A pointer to the created opcode.
3657 HiiCreateTextOpCode (
3658 IN VOID
*OpCodeHandle
,
3659 IN EFI_STRING_ID Prompt
,
3660 IN EFI_STRING_ID Help
,
3661 IN EFI_STRING_ID TextTwo
3664 EFI_IFR_TEXT OpCode
;
3666 ZeroMem (&OpCode
, sizeof (OpCode
));
3667 OpCode
.Statement
.Prompt
= Prompt
;
3668 OpCode
.Statement
.Help
= Help
;
3669 OpCode
.TextTwo
= TextTwo
;
3671 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TEXT_OP
, sizeof (OpCode
));
3675 Create EFI_IFR_DATE_OP opcode.
3677 If OpCodeHandle is NULL, then ASSERT().
3678 If any reserved bits are set in QuestionFlags, then ASSERT().
3679 If any reserved bits are set in DateFlags, then ASSERT().
3681 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3682 @param[in] QuestionId Question ID
3683 @param[in] VarStoreId Storage ID, optional. If DateFlags is not
3684 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3685 @param[in] VarOffset Offset in Storage, optional. If DateFlags is not
3686 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3687 @param[in] Prompt String ID for Prompt
3688 @param[in] Help String ID for Help
3689 @param[in] QuestionFlags Flags in Question Header
3690 @param[in] DateFlags Flags for date opcode
3691 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3692 is an optional parameter that may be NULL.
3694 @retval NULL There is not enough space left in Buffer to add the opcode.
3695 @retval Other A pointer to the created opcode.
3700 HiiCreateDateOpCode (
3701 IN VOID
*OpCodeHandle
,
3702 IN EFI_QUESTION_ID QuestionId
,
3703 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
3704 IN UINT16 VarOffset
, OPTIONAL
3705 IN EFI_STRING_ID Prompt
,
3706 IN EFI_STRING_ID Help
,
3707 IN UINT8 QuestionFlags
,
3709 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3712 EFI_IFR_DATE OpCode
;
3715 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3716 ASSERT ((DateFlags
& (~(EFI_QF_DATE_YEAR_SUPPRESS
| EFI_QF_DATE_MONTH_SUPPRESS
| EFI_QF_DATE_DAY_SUPPRESS
| EFI_QF_DATE_STORAGE
))) == 0);
3718 ZeroMem (&OpCode
, sizeof (OpCode
));
3719 OpCode
.Question
.Header
.Prompt
= Prompt
;
3720 OpCode
.Question
.Header
.Help
= Help
;
3721 OpCode
.Question
.QuestionId
= QuestionId
;
3722 OpCode
.Question
.VarStoreId
= VarStoreId
;
3723 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3724 OpCode
.Question
.Flags
= QuestionFlags
;
3725 OpCode
.Flags
= DateFlags
;
3727 if (DefaultsOpCodeHandle
== NULL
) {
3728 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
));
3731 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3732 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
), 0, 1);
3733 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3734 HiiCreateEndOpCode (OpCodeHandle
);
3735 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3739 Create EFI_IFR_TIME_OP opcode.
3741 If OpCodeHandle is NULL, then ASSERT().
3742 If any reserved bits are set in QuestionFlags, then ASSERT().
3743 If any reserved bits are set in TimeFlags, then ASSERT().
3745 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3746 @param[in] QuestionId Question ID
3747 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not
3748 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3749 @param[in] VarOffset Offset in Storage, optional. If TimeFlags is not
3750 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3751 @param[in] Prompt String ID for Prompt
3752 @param[in] Help String ID for Help
3753 @param[in] QuestionFlags Flags in Question Header
3754 @param[in] TimeFlags Flags for time opcode
3755 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3756 is an optional parameter that may be NULL.
3758 @retval NULL There is not enough space left in Buffer to add the opcode.
3759 @retval Other A pointer to the created opcode.
3764 HiiCreateTimeOpCode (
3765 IN VOID
*OpCodeHandle
,
3766 IN EFI_QUESTION_ID QuestionId
,
3767 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
3768 IN UINT16 VarOffset
, OPTIONAL
3769 IN EFI_STRING_ID Prompt
,
3770 IN EFI_STRING_ID Help
,
3771 IN UINT8 QuestionFlags
,
3773 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3776 EFI_IFR_TIME OpCode
;
3779 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3780 ASSERT ((TimeFlags
& (~(QF_TIME_HOUR_SUPPRESS
| QF_TIME_MINUTE_SUPPRESS
| QF_TIME_SECOND_SUPPRESS
| QF_TIME_STORAGE
))) == 0);
3782 ZeroMem (&OpCode
, sizeof (OpCode
));
3783 OpCode
.Question
.Header
.Prompt
= Prompt
;
3784 OpCode
.Question
.Header
.Help
= Help
;
3785 OpCode
.Question
.QuestionId
= QuestionId
;
3786 OpCode
.Question
.VarStoreId
= VarStoreId
;
3787 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3788 OpCode
.Question
.Flags
= QuestionFlags
;
3789 OpCode
.Flags
= TimeFlags
;
3791 if (DefaultsOpCodeHandle
== NULL
) {
3792 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
));
3795 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3796 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
), 0, 1);
3797 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3798 HiiCreateEndOpCode (OpCodeHandle
);
3799 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3803 This is the internal worker function to update the data in
3804 a form specified by FormSetGuid, FormId and Label.
3806 @param[in] FormSetGuid The optional Formset GUID.
3807 @param[in] FormId The Form ID.
3808 @param[in] Package The package header.
3809 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR
3810 opcodes to be inserted or replaced in the form.
3811 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode
3812 that marks the end of a replace operation in the form.
3813 @param[out] TempPackage The resultant package.
3815 @retval EFI_SUCCESS The function completes successfully.
3816 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.
3821 InternalHiiUpdateFormPackageData (
3822 IN EFI_GUID
*FormSetGuid
, OPTIONAL
3823 IN EFI_FORM_ID FormId
,
3824 IN EFI_HII_PACKAGE_HEADER
*Package
,
3825 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
,
3826 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
, OPTIONAL
3827 OUT EFI_HII_PACKAGE_HEADER
*TempPackage
3832 EFI_HII_PACKAGE_HEADER PackageHeader
;
3834 EFI_IFR_OP_HEADER
*IfrOpHdr
;
3835 EFI_IFR_OP_HEADER
*UpdateIfrOpHdr
;
3839 UINTN UpdatePackageLength
;
3841 CopyMem (TempPackage
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3842 UpdatePackageLength
= sizeof (EFI_HII_PACKAGE_HEADER
);
3843 BufferPos
= (UINT8
*) (TempPackage
+ 1);
3845 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3846 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
3847 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
3848 GetFormSet
= (BOOLEAN
) ((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
3852 while (Offset
< PackageHeader
.Length
) {
3853 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3854 BufferPos
+= IfrOpHdr
->Length
;
3855 UpdatePackageLength
+= IfrOpHdr
->Length
;
3858 // Find the matched FormSet and Form
3860 if ((IfrOpHdr
->OpCode
== EFI_IFR_FORM_SET_OP
) && (FormSetGuid
!= NULL
)) {
3861 if (CompareGuid((GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
)) {
3866 } else if (IfrOpHdr
->OpCode
== EFI_IFR_FORM_OP
|| IfrOpHdr
->OpCode
== EFI_IFR_FORM_MAP_OP
) {
3867 if (CompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
3875 // The matched Form is found, and Update data in this form
3877 if (GetFormSet
&& GetForm
) {
3878 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
;
3879 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3880 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3882 // Remove the original data when End OpCode buffer exist.
3884 if (OpCodeBufferEnd
!= NULL
) {
3885 Offset
+= IfrOpHdr
->Length
;
3886 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3887 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferEnd
->Buffer
;
3888 while (Offset
< PackageHeader
.Length
) {
3890 // Search the matched end opcode
3892 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3893 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3897 // Go to the next Op-Code
3899 Offset
+= IfrOpHdr
->Length
;
3900 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3903 if (Offset
>= PackageHeader
.Length
) {
3905 // The end opcode is not found.
3907 return EFI_NOT_FOUND
;
3912 // Insert the updated data
3914 AddSize
= ((EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
)->Length
;
3915 CopyMem (BufferPos
, OpCodeBufferStart
->Buffer
+ AddSize
, OpCodeBufferStart
->Position
- AddSize
);
3916 BufferPos
+= OpCodeBufferStart
->Position
- AddSize
;
3917 UpdatePackageLength
+= OpCodeBufferStart
->Position
- AddSize
;
3919 if (OpCodeBufferEnd
!= NULL
) {
3921 // Add the end opcode
3923 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3924 BufferPos
+= IfrOpHdr
->Length
;
3925 UpdatePackageLength
+= IfrOpHdr
->Length
;
3929 // Copy the left package data.
3931 Offset
+= IfrOpHdr
->Length
;
3932 CopyMem (BufferPos
, (UINT8
*) Package
+ Offset
, PackageHeader
.Length
- Offset
);
3933 UpdatePackageLength
+= PackageHeader
.Length
- Offset
;
3944 // Go to the next Op-Code
3946 Offset
+= IfrOpHdr
->Length
;
3947 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3952 // The updated opcode buffer is not found.
3954 return EFI_NOT_FOUND
;
3957 // Update the package length.
3959 PackageHeader
.Length
= (UINT32
) UpdatePackageLength
;
3960 CopyMem (TempPackage
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3966 This function updates a form that has previously been registered with the HII
3967 Database. This function will perform at most one update operation.
3969 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
3970 comparisons of IFR opcodes are performed from the beginning of the form being
3971 updated until an IFR opcode is found that exactly matches the first IFR opcode
3972 specified by StartOpCodeHandle. The following rules are used to determine if
3973 an insert, replace, or delete operation is performed.
3975 1) If no matches are found, then NULL is returned.
3976 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
3977 from StartOpCodeHandle except the first opcode are inserted immediately after
3978 the matching IFR opcode in the form to be updated.
3979 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
3980 from the matching IFR opcode until an IFR opcode exactly matches the first
3981 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
3982 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
3983 is found, then all of the IFR opcodes between the start match and the end
3984 match are deleted from the form being updated and all of the IFR opcodes
3985 from StartOpCodeHandle except the first opcode are inserted immediately after
3986 the matching start IFR opcode. If StartOpCcodeHandle only contains one
3987 IFR instruction, then the result of this operation will delete all of the IFR
3988 opcodes between the start end matches.
3990 If HiiHandle is NULL, then ASSERT().
3991 If StartOpCodeHandle is NULL, then ASSERT().
3993 @param[in] HiiHandle The HII Handle of the form to update.
3994 @param[in] FormSetGuid The Formset GUID of the form to update. This
3995 is an optional parameter that may be NULL.
3996 If it is NULL, all FormSet will be updated.
3997 @param[in] FormId The ID of the form to update.
3998 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
3999 opcodes to be inserted or replaced in the form.
4000 The first IFR instruction in StartOpCodeHandle
4001 is used to find matching IFR opcode in the
4003 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
4004 that marks the end of a replace operation in
4005 the form. This is an optional parameter that
4006 may be NULL. If it is NULL, then an the IFR
4007 opcodes specified by StartOpCodeHandle are
4008 inserted into the form.
4010 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
4011 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
4012 1) The form specified by HiiHandle, FormSetGuid,
4013 and FormId could not be found in the HII Database.
4014 2) No IFR opcodes in the target form match the first
4015 IFR opcode in StartOpCodeHandle.
4016 3) EndOpCOde is not NULL, and no IFR opcodes in the
4017 target form following a matching start opcode match
4018 the first IFR opcode in EndOpCodeHandle.
4019 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
4025 IN EFI_HII_HANDLE HiiHandle
,
4026 IN EFI_GUID
*FormSetGuid
, OPTIONAL
4027 IN EFI_FORM_ID FormId
,
4028 IN VOID
*StartOpCodeHandle
,
4029 IN VOID
*EndOpCodeHandle OPTIONAL
4033 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4034 UINT32 PackageListLength
;
4036 EFI_HII_PACKAGE_LIST_HEADER
*UpdatePackageList
;
4038 UINT8
*UpdateBufferPos
;
4039 EFI_HII_PACKAGE_HEADER
*Package
;
4040 EFI_HII_PACKAGE_HEADER
*TempPacakge
;
4041 EFI_HII_PACKAGE_HEADER PackageHeader
;
4043 HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
;
4044 HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
;
4047 // Input update data can't be NULL.
4049 ASSERT (HiiHandle
!= NULL
);
4050 ASSERT (StartOpCodeHandle
!= NULL
);
4051 UpdatePackageList
= NULL
;
4053 HiiPackageList
= NULL
;
4056 // Retrieve buffer data from Opcode Handle
4058 OpCodeBufferStart
= (HII_LIB_OPCODE_BUFFER
*) StartOpCodeHandle
;
4059 OpCodeBufferEnd
= (HII_LIB_OPCODE_BUFFER
*) EndOpCodeHandle
;
4062 // Get the original package list
4065 HiiPackageList
= NULL
;
4066 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4068 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
4070 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4074 HiiPackageList
= AllocatePool (BufferSize
);
4075 if (HiiPackageList
== NULL
) {
4076 Status
= EFI_OUT_OF_RESOURCES
;
4080 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4081 if (EFI_ERROR (Status
)) {
4086 // Calculate and allocate space for retrieval of IFR data
4088 BufferSize
+= OpCodeBufferStart
->Position
;
4089 UpdatePackageList
= AllocateZeroPool (BufferSize
);
4090 if (UpdatePackageList
== NULL
) {
4091 Status
= EFI_OUT_OF_RESOURCES
;
4096 // Allocate temp buffer to store the temp updated package buffer
4098 TempPacakge
= AllocateZeroPool (BufferSize
);
4099 if (TempPacakge
== NULL
) {
4100 Status
= EFI_OUT_OF_RESOURCES
;
4104 UpdateBufferPos
= (UINT8
*) UpdatePackageList
;
4107 // Copy the package list header
4109 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
4110 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4113 // Go through each package to find the matched package and update one by one
4116 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4117 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
4118 while (Offset
< PackageListLength
) {
4119 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
4120 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4121 Offset
+= Package
->Length
;
4123 if (Package
->Type
== EFI_HII_PACKAGE_FORMS
) {
4125 // Check this package is the matched package.
4127 Status
= InternalHiiUpdateFormPackageData (FormSetGuid
, FormId
, Package
, OpCodeBufferStart
, OpCodeBufferEnd
, TempPacakge
);
4129 // The matched package is found. Its package buffer will be updated by the input new data.
4131 if (!EFI_ERROR(Status
)) {
4137 // Add updated package buffer
4139 Package
= TempPacakge
;
4144 // Add pacakge buffer
4146 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4147 CopyMem (UpdateBufferPos
, Package
, PackageHeader
.Length
);
4148 UpdateBufferPos
+= PackageHeader
.Length
;
4153 // Update package list length
4155 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdatePackageList
;
4156 WriteUnaligned32 (&UpdatePackageList
->PackageLength
, (UINT32
) BufferSize
);
4159 // Update Package to show form
4161 Status
= gHiiDatabase
->UpdatePackageList (gHiiDatabase
, HiiHandle
, UpdatePackageList
);
4164 // Not matched form is found and updated.
4166 Status
= EFI_NOT_FOUND
;
4170 if (HiiPackageList
!= NULL
) {
4171 FreePool (HiiPackageList
);
4174 if (UpdatePackageList
!= NULL
) {
4175 FreePool (UpdatePackageList
);
4178 if (TempPacakge
!= NULL
) {
4179 FreePool (TempPacakge
);