2 HII Library implementation that uses DXE protocols and services.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "InternalHiiLib.h"
11 #define GUID_CONFIG_STRING_TYPE 0x00
12 #define NAME_CONFIG_STRING_TYPE 0x01
13 #define PATH_CONFIG_STRING_TYPE 0x02
15 #define ACTION_SET_DEFAUTL_VALUE 0x01
16 #define ACTION_VALIDATE_SETTING 0x02
18 #define HII_LIB_DEFAULT_VARSTORE_SIZE 0x200
21 LIST_ENTRY Entry
; // Link to Block array
29 EFI_VARSTORE_ID VarStoreId
;
31 } IFR_VARSTORAGE_DATA
;
34 // <ConfigHdr> Template
36 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";
38 EFI_FORM_BROWSER2_PROTOCOL
*mUefiFormBrowser2
= NULL
;
41 // Template used to mark the end of a list of packages
43 GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER mEndOfPakageList
= {
44 sizeof (EFI_HII_PACKAGE_HEADER
),
49 Extract Hii package list GUID for given HII handle.
51 If HiiHandle could not be found in the HII database, then ASSERT.
52 If Guid is NULL, then ASSERT.
54 @param Handle Hii handle
55 @param Guid Package list GUID
57 @retval EFI_SUCCESS Successfully extract GUID from Hii database.
62 InternalHiiExtractGuidFromHiiHandle (
63 IN EFI_HII_HANDLE Handle
,
69 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
71 ASSERT (Guid
!= NULL
);
72 ASSERT (Handle
!= NULL
);
75 // Get HII PackageList
78 HiiPackageList
= NULL
;
80 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
81 ASSERT (Status
!= EFI_NOT_FOUND
);
83 if (Status
== EFI_BUFFER_TOO_SMALL
) {
84 HiiPackageList
= AllocatePool (BufferSize
);
85 ASSERT (HiiPackageList
!= NULL
);
87 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
90 if (EFI_ERROR (Status
)) {
91 FreePool (HiiPackageList
);
98 CopyGuid (Guid
, &HiiPackageList
->PackageListGuid
);
100 FreePool (HiiPackageList
);
106 Registers a list of packages in the HII Database and returns the HII Handle
107 associated with that registration. If an HII Handle has already been registered
108 with the same PackageListGuid and DeviceHandle, then NULL is returned. If there
109 are not enough resources to perform the registration, then NULL is returned.
110 If an empty list of packages is passed in, then NULL is returned. If the size of
111 the list of package is 0, then NULL is returned.
113 The variable arguments are pointers which point to package header that defined
114 by UEFI VFR compiler and StringGather tool.
116 #pragma pack (push, 1)
119 EFI_HII_PACKAGE_HEADER PackageHeader;
120 } EDKII_AUTOGEN_PACKAGES_HEADER;
123 @param[in] PackageListGuid The GUID of the package list.
124 @param[in] DeviceHandle If not NULL, the Device Handle on which
125 an instance of DEVICE_PATH_PROTOCOL is installed.
126 This Device Handle uniquely defines the device that
127 the added packages are associated with.
128 @param[in] ... The variable argument list that contains pointers
129 to packages terminated by a NULL.
131 @retval NULL A HII Handle has already been registered in the HII Database with
132 the same PackageListGuid and DeviceHandle.
133 @retval NULL The HII Handle could not be created.
134 @retval NULL An empty list of packages was passed in.
135 @retval NULL All packages are empty.
136 @retval Other The HII Handle associated with the newly registered package list.
142 IN CONST EFI_GUID
*PackageListGuid
,
143 IN EFI_HANDLE DeviceHandle OPTIONAL
,
150 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
151 EFI_HII_HANDLE HiiHandle
;
155 ASSERT (PackageListGuid
!= NULL
);
158 // Calculate the length of all the packages in the variable argument list
160 for (Length
= 0, VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
161 Length
+= (ReadUnaligned32 (Package
) - sizeof (UINT32
));
167 // If there are no packages in the variable argument list or all the packages
168 // are empty, then return a NULL HII Handle
175 // Add the length of the Package List Header and the terminating Package Header
177 Length
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
) + sizeof (EFI_HII_PACKAGE_HEADER
);
180 // Allocate the storage for the entire Package List
182 PackageListHeader
= AllocateZeroPool (Length
);
185 // If the Package List can not be allocated, then return a NULL HII Handle
187 if (PackageListHeader
== NULL
) {
192 // Fill in the GUID and Length of the Package List Header
194 CopyGuid (&PackageListHeader
->PackageListGuid
, PackageListGuid
);
195 PackageListHeader
->PackageLength
= Length
;
198 // Initialize a pointer to the beginning if the Package List data
200 Data
= (UINT8
*)(PackageListHeader
+ 1);
203 // Copy the data from each package in the variable argument list
205 for (VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
206 Length
= ReadUnaligned32 (Package
) - sizeof (UINT32
);
207 CopyMem (Data
, Package
+ 1, Length
);
214 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list
216 CopyMem (Data
, &mEndOfPakageList
, sizeof (mEndOfPakageList
));
219 // Register the package list with the HII Database
221 Status
= gHiiDatabase
->NewPackageList (
227 if (EFI_ERROR (Status
)) {
232 // Free the allocated package list
234 FreePool (PackageListHeader
);
237 // Return the new HII Handle
243 Removes a package list from the HII database.
245 If HiiHandle is NULL, then ASSERT.
246 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.
248 @param[in] HiiHandle The handle that was previously registered in the HII database
254 IN EFI_HII_HANDLE HiiHandle
259 ASSERT (HiiHandle
!= NULL
);
260 Status
= gHiiDatabase
->RemovePackageList (gHiiDatabase
, HiiHandle
);
261 ASSERT_EFI_ERROR (Status
);
265 Retrieves the array of all the HII Handles or the HII handles of a specific
266 package list GUID in the HII Database.
267 This array is terminated with a NULL HII Handle.
268 This function allocates the returned array using AllocatePool().
269 The caller is responsible for freeing the array with FreePool().
271 @param[in] PackageListGuid An optional parameter that is used to request
272 HII Handles associated with a specific
273 Package List GUID. If this parameter is NULL,
274 then all the HII Handles in the HII Database
275 are returned. If this parameter is not NULL,
276 then zero or more HII Handles associated with
277 PackageListGuid are returned.
279 @retval NULL No HII handles were found in the HII database
280 @retval NULL The array of HII Handles could not be retrieved
281 @retval Other A pointer to the NULL terminated array of HII Handles
287 IN CONST EFI_GUID
*PackageListGuid OPTIONAL
291 UINTN HandleBufferLength
;
292 EFI_HII_HANDLE TempHiiHandleBuffer
;
293 EFI_HII_HANDLE
*HiiHandleBuffer
;
299 // Retrieve the size required for the buffer of all HII handles.
301 HandleBufferLength
= 0;
302 Status
= gHiiDatabase
->ListPackageLists (
304 EFI_HII_PACKAGE_TYPE_ALL
,
311 // If ListPackageLists() returns EFI_SUCCESS for a zero size,
312 // then there are no HII handles in the HII database. If ListPackageLists()
313 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII
314 // handles in the HII database.
316 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
318 // Return NULL if the size can not be retrieved, or if there are no HII
319 // handles in the HII Database
325 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator
327 HiiHandleBuffer
= AllocateZeroPool (HandleBufferLength
+ sizeof (EFI_HII_HANDLE
));
328 if (HiiHandleBuffer
== NULL
) {
330 // Return NULL if allocation fails.
336 // Retrieve the array of HII Handles in the HII Database
338 Status
= gHiiDatabase
->ListPackageLists (
340 EFI_HII_PACKAGE_TYPE_ALL
,
345 if (EFI_ERROR (Status
)) {
347 // Free the buffer and return NULL if the HII handles can not be retrieved.
349 FreePool (HiiHandleBuffer
);
353 if (PackageListGuid
== NULL
) {
355 // Return the NULL terminated array of HII handles in the HII Database
357 return HiiHandleBuffer
;
359 for (Index1
= 0, Index2
= 0; HiiHandleBuffer
[Index1
] != NULL
; Index1
++) {
360 Status
= InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer
[Index1
], &Guid
);
361 ASSERT_EFI_ERROR (Status
);
362 if (CompareGuid (&Guid
, PackageListGuid
)) {
363 HiiHandleBuffer
[Index2
++] = HiiHandleBuffer
[Index1
];
368 HiiHandleBuffer
[Index2
] = NULL
;
369 return HiiHandleBuffer
;
371 FreePool (HiiHandleBuffer
);
378 This function allows a caller to extract the form set opcode form the Hii Handle.
379 The returned buffer is allocated using AllocatePool().The caller is responsible
380 for freeing the allocated buffer using FreePool().
382 @param Handle The HII handle.
383 @param Buffer On return, points to a pointer which point to the buffer that contain the formset opcode.
384 @param BufferSize On return, points to the length of the buffer.
386 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
387 @retval EFI_NOT_FOUND Can't find the package data for the input Handle.
388 @retval EFI_INVALID_PARAMETER The input parameters are not correct.
389 @retval EFI_SUCCESS Get the formset opcode from the hii handle successfully.
394 HiiGetFormSetFromHiiHandle (
395 IN EFI_HII_HANDLE Handle
,
396 OUT EFI_IFR_FORM_SET
**Buffer
,
397 OUT UINTN
*BufferSize
401 UINTN PackageListSize
;
403 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
406 UINT8
*FormSetBuffer
;
410 UINT32 PackageListLength
;
411 EFI_HII_PACKAGE_HEADER PackageHeader
;
414 FormSetBuffer
= NULL
;
418 // Get HII PackageList
421 HiiPackageList
= NULL
;
422 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &PackageListSize
, HiiPackageList
);
423 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
427 HiiPackageList
= AllocatePool (PackageListSize
);
428 if (HiiPackageList
== NULL
) {
429 return EFI_OUT_OF_RESOURCES
;
432 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &PackageListSize
, HiiPackageList
);
433 ASSERT_EFI_ERROR (Status
);
436 // Get Form package from this HII package List
438 Status
= EFI_NOT_FOUND
;
439 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
440 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
442 while (Offset
< PackageListLength
) {
443 Package
= ((UINT8
*)HiiPackageList
) + Offset
;
444 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
445 Offset
+= PackageHeader
.Length
;
447 if (PackageHeader
.Type
!= EFI_HII_PACKAGE_FORMS
) {
452 // Search FormSet Opcode in this Form Package
454 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
455 while (Offset2
< PackageHeader
.Length
) {
456 OpCodeData
= Package
+ Offset2
;
457 Offset2
+= ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
;
459 if (((EFI_IFR_OP_HEADER
*)OpCodeData
)->OpCode
!= EFI_IFR_FORM_SET_OP
) {
463 if (FormSetBuffer
!= NULL
) {
464 TempBuffer
= ReallocatePool (
466 TempSize
+ ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
,
469 if (TempBuffer
== NULL
) {
470 Status
= EFI_OUT_OF_RESOURCES
;
474 CopyMem (TempBuffer
+ TempSize
, OpCodeData
, ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
);
475 FormSetBuffer
= NULL
;
477 TempBuffer
= AllocatePool (TempSize
+ ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
);
478 if (TempBuffer
== NULL
) {
479 Status
= EFI_OUT_OF_RESOURCES
;
483 CopyMem (TempBuffer
, OpCodeData
, ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
);
486 TempSize
+= ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
;
487 FormSetBuffer
= TempBuffer
;
489 Status
= EFI_SUCCESS
;
491 // One form package has one formset, exit current form package to search other form package in the packagelist.
498 FreePool (HiiPackageList
);
500 *BufferSize
= TempSize
;
501 *Buffer
= (EFI_IFR_FORM_SET
*)FormSetBuffer
;
507 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
508 hex digits that appear between a '=' and a '&' in a config string.
510 If ConfigString is NULL, then ASSERT().
512 @param[in] ConfigString Pointer to a Null-terminated Unicode string.
514 @return Pointer to the Null-terminated Unicode result string.
519 InternalHiiLowerConfigString (
520 IN EFI_STRING ConfigString
526 ASSERT (ConfigString
!= NULL
);
529 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
531 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
532 if (*String
== L
'=') {
534 } else if (*String
== L
'&') {
536 } else if (Lower
&& (*String
>= L
'A') && (*String
<= L
'F')) {
537 *String
= (CHAR16
)(*String
- L
'A' + L
'a');
545 Uses the BlockToConfig() service of the Config Routing Protocol to
546 convert <ConfigRequest> and a buffer to a <ConfigResp>
548 If ConfigRequest is NULL, then ASSERT().
549 If Block is NULL, then ASSERT().
551 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.
552 @param[in] Block Pointer to a block of data.
553 @param[in] BlockSize The zie, in bytes, of Block.
555 @retval NULL The <ConfigResp> string could not be generated.
556 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.
561 InternalHiiBlockToConfig (
562 IN CONST EFI_STRING ConfigRequest
,
563 IN CONST UINT8
*Block
,
568 EFI_STRING ConfigResp
;
571 ASSERT (ConfigRequest
!= NULL
);
572 ASSERT (Block
!= NULL
);
575 // Convert <ConfigRequest> to <ConfigResp>
577 Status
= gHiiConfigRouting
->BlockToConfig (
585 if (EFI_ERROR (Status
)) {
593 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve
594 or set uncommitted data. If sata i being retrieved, then the buffer is
595 allocated using AllocatePool(). The caller is then responsible for freeing
596 the buffer using FreePool().
598 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
599 parameter that may be NULL.
600 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
601 is an optional parameter that may be NULL.
602 @param[in] SetResultsData If not NULL, then this parameter specified the buffer
603 of uncommited data to set. If this parameter is NULL,
604 then the caller is requesting to get the uncommited data
605 from the Form Browser.
607 @retval NULL The uncommitted data could not be retrieved.
608 @retval Other A pointer to a buffer containing the uncommitted data.
613 InternalHiiBrowserCallback (
614 IN CONST EFI_GUID
*VariableGuid OPTIONAL
,
615 IN CONST CHAR16
*VariableName OPTIONAL
,
616 IN CONST EFI_STRING SetResultsData OPTIONAL
620 UINTN ResultsDataSize
;
621 EFI_STRING ResultsData
;
622 CHAR16 TempResultsData
;
627 if (mUefiFormBrowser2
== NULL
) {
628 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**)&mUefiFormBrowser2
);
629 if (EFI_ERROR (Status
) || (mUefiFormBrowser2
== NULL
)) {
636 if (SetResultsData
!= NULL
) {
638 // Request to to set data in the uncommitted browser state information
640 ResultsData
= SetResultsData
;
643 // Retrieve the length of the buffer required ResultsData from the Browser Callback
645 Status
= mUefiFormBrowser2
->BrowserCallback (
654 if (!EFI_ERROR (Status
)) {
656 // No Resluts Data, only allocate one char for '\0'
658 ResultsData
= AllocateZeroPool (sizeof (CHAR16
));
662 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
667 // Allocate the ResultsData buffer
669 ResultsData
= AllocateZeroPool (ResultsDataSize
);
670 if (ResultsData
== NULL
) {
676 // Retrieve or set the ResultsData from the Browser Callback
678 Status
= mUefiFormBrowser2
->BrowserCallback (
682 (BOOLEAN
)(SetResultsData
== NULL
),
686 if (EFI_ERROR (Status
)) {
694 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing
695 information that includes a GUID, an optional Unicode string name, and a device
696 path. The string returned is allocated with AllocatePool(). The caller is
697 responsible for freeing the allocated string with FreePool().
699 The format of a <ConfigHdr> is as follows:
701 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
703 @param[in] Guid Pointer to an EFI_GUID that is the routing information
704 GUID. Each of the 16 bytes in Guid is converted to
705 a 2 Unicode character hexadecimal string. This is
706 an optional parameter that may be NULL.
707 @param[in] Name Pointer to a Null-terminated Unicode string that is
708 the routing information NAME. This is an optional
709 parameter that may be NULL. Each 16-bit Unicode
710 character in Name is converted to a 4 character Unicode
712 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
713 that is the routing information PATH. Each byte of
714 the Device Path associated with DriverHandle is converted
715 to a 2 Unicode character hexadecimal string.
717 @retval NULL DriverHandle does not support the Device Path Protocol.
718 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
723 HiiConstructConfigHdr (
724 IN CONST EFI_GUID
*Guid OPTIONAL
,
725 IN CONST CHAR16
*Name OPTIONAL
,
726 IN EFI_HANDLE DriverHandle
730 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
731 UINTN DevicePathSize
;
733 CHAR16
*ReturnString
;
739 // Compute the length of Name in Unicode characters.
740 // If Name is NULL, then the length is 0.
744 NameLength
= StrLen (Name
);
750 // Retrieve DevicePath Protocol associated with DriverHandle
752 if (DriverHandle
!= NULL
) {
753 DevicePath
= DevicePathFromHandle (DriverHandle
);
754 if (DevicePath
== NULL
) {
759 // Compute the size of the device path in bytes
761 DevicePathSize
= GetDevicePathSize (DevicePath
);
765 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
766 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
768 MaxLen
= 5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1;
769 String
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
770 if (String
== NULL
) {
775 // Start with L"GUID="
777 StrCpyS (String
, MaxLen
, L
"GUID=");
778 ReturnString
= String
;
779 String
+= StrLen (String
);
783 // Append Guid converted to <HexCh>32
785 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
786 UnicodeValueToStringS (
788 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
789 PREFIX_ZERO
| RADIX_HEX
,
793 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
800 StrCatS (ReturnString
, MaxLen
, L
"&NAME=");
801 String
+= StrLen (String
);
805 // Append Name converted to <Char>NameLength
807 for ( ; *Name
!= L
'\0'; Name
++) {
808 UnicodeValueToStringS (
810 sizeof (CHAR16
) * MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
),
811 PREFIX_ZERO
| RADIX_HEX
,
815 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
822 StrCatS (ReturnString
, MaxLen
, L
"&PATH=");
823 String
+= StrLen (String
);
826 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
828 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
829 UnicodeValueToStringS (
831 sizeof (CHAR16
) * MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
),
832 PREFIX_ZERO
| RADIX_HEX
,
836 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
840 // Null terminate the Unicode string
845 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
847 return InternalHiiLowerConfigString (ReturnString
);
851 Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path
852 to binary buffer from <ConfigHdr>.
854 This is a internal function.
856 @param String UEFI configuration string.
857 @param Flag Flag specifies what type buffer will be retrieved.
858 @param Buffer Binary of Guid, Name or Device path.
860 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
861 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
862 @retval EFI_SUCCESS The buffer data is retrieved and translated to
867 InternalHiiGetBufferFromString (
868 IN EFI_STRING String
,
874 EFI_STRING ConfigHdr
;
881 if ((String
== NULL
) || (Buffer
== NULL
)) {
882 return EFI_INVALID_PARAMETER
;
889 // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element
890 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.
892 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++) {
896 case GUID_CONFIG_STRING_TYPE
:
897 case PATH_CONFIG_STRING_TYPE
:
899 // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order
900 // as the device path and Guid resides in RAM memory.
901 // Translate the data into binary.
903 DataBuffer
= (UINT8
*)AllocateZeroPool ((Length
+ 1) / 2);
904 if (DataBuffer
== NULL
) {
905 return EFI_OUT_OF_RESOURCES
;
909 // Convert binary byte one by one
911 ZeroMem (TemStr
, sizeof (TemStr
));
912 for (Index
= 0; Index
< Length
; Index
++) {
913 TemStr
[0] = ConfigHdr
[Index
];
914 DigitUint8
= (UINT8
)StrHexToUint64 (TemStr
);
915 if ((Index
& 1) == 0) {
916 DataBuffer
[Index
/2] = DigitUint8
;
918 DataBuffer
[Index
/2] = (UINT8
)((DataBuffer
[Index
/2] << 4) + DigitUint8
);
922 *Buffer
= DataBuffer
;
925 case NAME_CONFIG_STRING_TYPE
:
927 // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"
931 // Add the tailling char L'\0'
933 DataBuffer
= (UINT8
*)AllocateZeroPool ((Length
/4 + 1) * sizeof (CHAR16
));
934 if (DataBuffer
== NULL
) {
935 return EFI_OUT_OF_RESOURCES
;
939 // Convert character one by one
941 StringPtr
= (CHAR16
*)DataBuffer
;
942 ZeroMem (TemStr
, sizeof (TemStr
));
943 for (Index
= 0; Index
< Length
; Index
+= 4) {
944 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), ConfigHdr
+ Index
, 4);
945 StringPtr
[Index
/4] = (CHAR16
)StrHexToUint64 (TemStr
);
949 // Add tailing L'\0' character
951 StringPtr
[Index
/4] = L
'\0';
953 *Buffer
= DataBuffer
;
957 return EFI_INVALID_PARAMETER
;
964 This function checks VarOffset and VarWidth is in the block range.
966 @param BlockArray The block array is to be checked.
967 @param VarOffset Offset of var to the structure
968 @param VarWidth Width of var.
970 @retval TRUE This Var is in the block range.
971 @retval FALSE This Var is not in the block range.
975 IN IFR_BLOCK_DATA
*BlockArray
,
981 IFR_BLOCK_DATA
*BlockData
;
984 // No Request Block array, all vars are got.
986 if (BlockArray
== NULL
) {
991 // Check the input var is in the request block range.
993 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
994 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
995 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1004 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
1006 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
1008 @param ValueString String in <BlockConfig> format and points to the
1009 first character of <Number>.
1010 @param ValueData The output value. Caller takes the responsibility
1012 @param ValueLength Length of the <Number>, in characters.
1014 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
1016 @retval EFI_SUCCESS Value of <Number> is outputted in Number
1022 InternalHiiGetValueOfNumber (
1023 IN EFI_STRING ValueString
,
1024 OUT UINT8
**ValueData
,
1025 OUT UINTN
*ValueLength
1028 EFI_STRING StringPtr
;
1035 ASSERT (ValueString
!= NULL
&& ValueData
!= NULL
&& ValueLength
!= NULL
);
1036 ASSERT (*ValueString
!= L
'\0');
1039 // Get the length of value string
1041 StringPtr
= ValueString
;
1042 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1046 Length
= StringPtr
- ValueString
;
1049 // Allocate buffer to store the value
1051 Buf
= (UINT8
*)AllocateZeroPool ((Length
+ 1) / 2);
1053 return EFI_OUT_OF_RESOURCES
;
1057 // Convert character one by one to the value buffer
1059 ZeroMem (TemStr
, sizeof (TemStr
));
1060 for (Index
= 0; Index
< Length
; Index
++) {
1061 TemStr
[0] = ValueString
[Length
- Index
- 1];
1062 DigitUint8
= (UINT8
)StrHexToUint64 (TemStr
);
1063 if ((Index
& 1) == 0) {
1064 Buf
[Index
/2] = DigitUint8
;
1066 Buf
[Index
/2] = (UINT8
)((DigitUint8
<< 4) + Buf
[Index
/2]);
1071 // Set the converted value and string length.
1074 *ValueLength
= Length
;
1079 Get value from config request resp string.
1081 @param ConfigElement ConfigResp string contains the current setting.
1082 @param VarName The variable name which need to get value.
1083 @param VarValue The return value.
1085 @retval EFI_SUCCESS Get the value for the VarName
1086 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1089 GetValueFromRequest (
1090 IN CHAR16
*ConfigElement
,
1092 OUT UINT64
*VarValue
1101 // Find VarName related string.
1103 StringPtr
= StrStr (ConfigElement
, VarName
);
1104 ASSERT (StringPtr
!= NULL
);
1107 // Skip the "VarName=" string
1109 StringPtr
+= StrLen (VarName
) + 1;
1114 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1115 if (EFI_ERROR (Status
)) {
1120 CopyMem (VarValue
, TmpBuffer
, (((Length
+ 1) / 2) < sizeof (UINT64
)) ? ((Length
+ 1) / 2) : sizeof (UINT64
));
1122 FreePool (TmpBuffer
);
1128 This internal function parses IFR data to validate current setting.
1130 Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;
1131 else the VarBuffer and CurrentBlockArray is valid.
1133 @param HiiPackageList Point to Hii package list.
1134 @param PackageListLength The length of the pacakge.
1135 @param VarGuid Guid of the buffer storage.
1136 @param VarName Name of the buffer storage.
1137 @param VarBuffer The data buffer for the storage.
1138 @param CurrentBlockArray The block array from the config Requst string.
1139 @param RequestElement The config string for this storage.
1140 @param HiiHandle The HiiHandle for this formset.
1141 @param NameValueType Whether current storage is name/value varstore or not.
1143 @retval EFI_SUCCESS The current setting is valid.
1144 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1145 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1148 ValidateQuestionFromVfr (
1149 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
1150 IN UINTN PackageListLength
,
1151 IN EFI_GUID
*VarGuid
,
1153 IN UINT8
*VarBuffer
,
1154 IN IFR_BLOCK_DATA
*CurrentBlockArray
,
1155 IN CHAR16
*RequestElement
,
1156 IN EFI_HII_HANDLE HiiHandle
,
1157 IN BOOLEAN NameValueType
1160 IFR_BLOCK_DATA VarBlockData
;
1164 EFI_IFR_TYPE_VALUE TmpValue
;
1166 EFI_HII_PACKAGE_HEADER PackageHeader
;
1167 UINT32 PackageOffset
;
1170 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1171 EFI_IFR_VARSTORE
*IfrVarStore
;
1172 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueStore
;
1173 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1174 IFR_VARSTORAGE_DATA VarStoreData
;
1175 EFI_IFR_ONE_OF
*IfrOneOf
;
1176 EFI_IFR_NUMERIC
*IfrNumeric
;
1177 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1178 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1179 EFI_IFR_STRING
*IfrString
;
1180 CHAR8
*VarStoreName
;
1182 CHAR16
*QuestionName
;
1189 BOOLEAN QuestionReferBitField
;
1193 // Initialize the local variables.
1196 VarStoreName
= NULL
;
1197 Status
= EFI_SUCCESS
;
1200 IfrNameValueStore
= NULL
;
1201 IfrEfiVarStore
= NULL
;
1202 ZeroMem (&VarStoreData
, sizeof (IFR_VARSTORAGE_DATA
));
1203 ZeroMem (&VarBlockData
, sizeof (VarBlockData
));
1206 QuestionReferBitField
= FALSE
;
1209 // Check IFR value is in block data, then Validate Value
1211 PackageOffset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1212 while (PackageOffset
< PackageListLength
) {
1213 CopyMem (&PackageHeader
, (UINT8
*)HiiPackageList
+ PackageOffset
, sizeof (PackageHeader
));
1216 // Parse IFR opcode from the form package.
1218 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1219 IfrOffset
= sizeof (PackageHeader
);
1220 PackageData
= (UINT8
*)HiiPackageList
+ PackageOffset
;
1221 while (IfrOffset
< PackageHeader
.Length
) {
1222 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)(PackageData
+ IfrOffset
);
1224 // Validate current setting to the value built in IFR opcode
1226 switch (IfrOpHdr
->OpCode
) {
1227 case EFI_IFR_VARSTORE_OP
:
1229 // VarStoreId has been found. No further found.
1231 if (VarStoreData
.VarStoreId
!= 0) {
1236 // Find the matched VarStoreId to the input VarGuid and VarName
1238 IfrVarStore
= (EFI_IFR_VARSTORE
*)IfrOpHdr
;
1239 if (CompareGuid ((EFI_GUID
*)(VOID
*)&IfrVarStore
->Guid
, VarGuid
)) {
1240 VarStoreName
= (CHAR8
*)IfrVarStore
->Name
;
1241 for (Index
= 0; VarStoreName
[Index
] != 0; Index
++) {
1242 if ((CHAR16
)VarStoreName
[Index
] != VarName
[Index
]) {
1248 // The matched VarStore is found.
1250 if ((VarStoreName
[Index
] != 0) || (VarName
[Index
] != 0)) {
1257 if (IfrVarStore
!= NULL
) {
1258 VarStoreData
.VarStoreId
= IfrVarStore
->VarStoreId
;
1259 VarStoreData
.Size
= IfrVarStore
->Size
;
1263 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1265 // VarStoreId has been found. No further found.
1267 if (VarStoreData
.VarStoreId
!= 0) {
1272 // Find the matched VarStoreId to the input VarGuid
1274 IfrNameValueStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*)IfrOpHdr
;
1275 if (!CompareGuid ((EFI_GUID
*)(VOID
*)&IfrNameValueStore
->Guid
, VarGuid
)) {
1276 IfrNameValueStore
= NULL
;
1279 if (IfrNameValueStore
!= NULL
) {
1280 VarStoreData
.VarStoreId
= IfrNameValueStore
->VarStoreId
;
1284 case EFI_IFR_VARSTORE_EFI_OP
:
1286 // VarStore is found. Don't need to search any more.
1288 if (VarStoreData
.VarStoreId
!= 0) {
1292 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*)IfrOpHdr
;
1295 // If the length is small than the structure, this is from old efi
1296 // varstore definition. Old efi varstore get config directly from
1297 // GetVariable function.
1299 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1303 if (CompareGuid ((EFI_GUID
*)(VOID
*)&IfrEfiVarStore
->Guid
, VarGuid
)) {
1304 VarStoreName
= (CHAR8
*)IfrEfiVarStore
->Name
;
1305 for (Index
= 0; VarStoreName
[Index
] != 0; Index
++) {
1306 if ((CHAR16
)VarStoreName
[Index
] != VarName
[Index
]) {
1312 // The matched VarStore is found.
1314 if ((VarStoreName
[Index
] != 0) || (VarName
[Index
] != 0)) {
1315 IfrEfiVarStore
= NULL
;
1318 IfrEfiVarStore
= NULL
;
1321 if (IfrEfiVarStore
!= NULL
) {
1323 // Find the matched VarStore
1325 VarStoreData
.VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1326 VarStoreData
.Size
= IfrEfiVarStore
->Size
;
1330 case EFI_IFR_FORM_OP
:
1331 case EFI_IFR_FORM_MAP_OP
:
1333 // Check the matched VarStoreId is found.
1335 if (VarStoreData
.VarStoreId
== 0) {
1340 case EFI_IFR_ONE_OF_OP
:
1342 // Check whether current value is the one of option.
1346 // OneOf question is not in IFR Form. This IFR form is not valid.
1348 if (VarStoreData
.VarStoreId
== 0) {
1349 return EFI_INVALID_PARAMETER
;
1353 // Check whether this question is for the requested varstore.
1355 IfrOneOf
= (EFI_IFR_ONE_OF
*)IfrOpHdr
;
1356 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1360 if (NameValueType
) {
1361 QuestionName
= HiiGetString (HiiHandle
, IfrOneOf
->Question
.VarStoreInfo
.VarName
, NULL
);
1362 ASSERT (QuestionName
!= NULL
);
1364 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1366 // This question is not in the current configuration string. Skip it.
1371 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1372 if (EFI_ERROR (Status
)) {
1377 // Get Offset by Question header and Width by DataType Flags
1379 if (QuestionReferBitField
) {
1381 // Get the byte offset/width for bit field.
1383 BitOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1384 BitWidth
= IfrOneOf
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
1385 Offset
= BitOffset
/ 8;
1386 TotalBits
= BitOffset
% 8 + BitWidth
;
1387 Width
= (TotalBits
% 8 == 0 ? TotalBits
/ 8 : TotalBits
/ 8 + 1);
1389 Offset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1390 Width
= (UINT16
)(1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1394 // Check whether this question is in current block array.
1396 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1398 // This question is not in the current configuration string. Skip it.
1404 // Check this var question is in the var storage
1406 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1408 // This question exceeds the var store size.
1410 return EFI_INVALID_PARAMETER
;
1414 // Get the current value for oneof opcode
1417 if (QuestionReferBitField
) {
1419 // Get the value in bit fields.
1421 StartBit
= BitOffset
% 8;
1422 EndBit
= StartBit
+ BitWidth
- 1;
1423 CopyMem ((UINT8
*)&BufferValue
, VarBuffer
+ Offset
, Width
);
1424 VarValue
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1426 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1431 // Set Block Data, to be checked in the following Oneof option opcode.
1433 VarBlockData
.OpCode
= IfrOpHdr
->OpCode
;
1434 VarBlockData
.Scope
= IfrOpHdr
->Scope
;
1436 case EFI_IFR_NUMERIC_OP
:
1438 // Check the current value is in the numeric range.
1442 // Numeric question is not in IFR Form. This IFR form is not valid.
1444 if (VarStoreData
.VarStoreId
== 0) {
1445 return EFI_INVALID_PARAMETER
;
1449 // Check whether this question is for the requested varstore.
1451 IfrNumeric
= (EFI_IFR_NUMERIC
*)IfrOpHdr
;
1452 if (IfrNumeric
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1456 if (NameValueType
) {
1457 QuestionName
= HiiGetString (HiiHandle
, IfrNumeric
->Question
.VarStoreInfo
.VarName
, NULL
);
1458 ASSERT (QuestionName
!= NULL
);
1460 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1462 // This question is not in the current configuration string. Skip it.
1467 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1468 if (EFI_ERROR (Status
)) {
1473 // Get Offset by Question header and Width by DataType Flags
1475 if (QuestionReferBitField
) {
1477 // Get the byte offset/width for bit field.
1479 BitOffset
= IfrNumeric
->Question
.VarStoreInfo
.VarOffset
;
1480 BitWidth
= IfrNumeric
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
1481 Offset
= BitOffset
/ 8;
1482 TotalBits
= BitOffset
% 8 + BitWidth
;
1483 Width
= (TotalBits
% 8 == 0 ? TotalBits
/ 8 : TotalBits
/ 8 + 1);
1485 Offset
= IfrNumeric
->Question
.VarStoreInfo
.VarOffset
;
1486 Width
= (UINT16
)(1 << (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1490 // Check whether this question is in current block array.
1492 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1494 // This question is not in the current configuration string. Skip it.
1500 // Check this var question is in the var storage
1502 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1504 // This question exceeds the var store size.
1506 return EFI_INVALID_PARAMETER
;
1510 // Check the current value is in the numeric range.
1513 if (QuestionReferBitField
) {
1515 // Get the value in the bit fields.
1517 StartBit
= BitOffset
% 8;
1518 EndBit
= StartBit
+ BitWidth
- 1;
1519 CopyMem ((UINT8
*)&BufferValue
, VarBuffer
+ Offset
, Width
);
1520 VarValue
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1522 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1526 if ( QuestionReferBitField
) {
1528 // Value in bit fields was stored as UINt32 type.
1530 if ((IfrNumeric
->Flags
& EDKII_IFR_DISPLAY_BIT
) == 0) {
1531 if (((INT32
)VarValue
< (INT32
)IfrNumeric
->data
.u32
.MinValue
) || ((INT32
)VarValue
> (INT32
)IfrNumeric
->data
.u32
.MaxValue
)) {
1533 // Not in the valid range.
1535 return EFI_INVALID_PARAMETER
;
1538 if ((VarValue
< IfrNumeric
->data
.u32
.MinValue
) || (VarValue
> IfrNumeric
->data
.u32
.MaxValue
)) {
1540 // Not in the valid range.
1542 return EFI_INVALID_PARAMETER
;
1546 if ((IfrNumeric
->Flags
& EFI_IFR_DISPLAY
) == 0) {
1547 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1548 case EFI_IFR_NUMERIC_SIZE_1
:
1549 if (((INT8
)VarValue
< (INT8
)IfrNumeric
->data
.u8
.MinValue
) || ((INT8
)VarValue
> (INT8
)IfrNumeric
->data
.u8
.MaxValue
)) {
1551 // Not in the valid range.
1553 return EFI_INVALID_PARAMETER
;
1557 case EFI_IFR_NUMERIC_SIZE_2
:
1558 if (((INT16
)VarValue
< (INT16
)IfrNumeric
->data
.u16
.MinValue
) || ((INT16
)VarValue
> (INT16
)IfrNumeric
->data
.u16
.MaxValue
)) {
1560 // Not in the valid range.
1562 return EFI_INVALID_PARAMETER
;
1566 case EFI_IFR_NUMERIC_SIZE_4
:
1567 if (((INT32
)VarValue
< (INT32
)IfrNumeric
->data
.u32
.MinValue
) || ((INT32
)VarValue
> (INT32
)IfrNumeric
->data
.u32
.MaxValue
)) {
1569 // Not in the valid range.
1571 return EFI_INVALID_PARAMETER
;
1575 case EFI_IFR_NUMERIC_SIZE_8
:
1576 if (((INT64
)VarValue
< (INT64
)IfrNumeric
->data
.u64
.MinValue
) || ((INT64
)VarValue
> (INT64
)IfrNumeric
->data
.u64
.MaxValue
)) {
1578 // Not in the valid range.
1580 return EFI_INVALID_PARAMETER
;
1586 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1587 case EFI_IFR_NUMERIC_SIZE_1
:
1588 if (((UINT8
)VarValue
< IfrNumeric
->data
.u8
.MinValue
) || ((UINT8
)VarValue
> IfrNumeric
->data
.u8
.MaxValue
)) {
1590 // Not in the valid range.
1592 return EFI_INVALID_PARAMETER
;
1596 case EFI_IFR_NUMERIC_SIZE_2
:
1597 if (((UINT16
)VarValue
< IfrNumeric
->data
.u16
.MinValue
) || ((UINT16
)VarValue
> IfrNumeric
->data
.u16
.MaxValue
)) {
1599 // Not in the valid range.
1601 return EFI_INVALID_PARAMETER
;
1605 case EFI_IFR_NUMERIC_SIZE_4
:
1606 if (((UINT32
)VarValue
< IfrNumeric
->data
.u32
.MinValue
) || ((UINT32
)VarValue
> IfrNumeric
->data
.u32
.MaxValue
)) {
1608 // Not in the valid range.
1610 return EFI_INVALID_PARAMETER
;
1614 case EFI_IFR_NUMERIC_SIZE_8
:
1615 if (((UINT64
)VarValue
< IfrNumeric
->data
.u64
.MinValue
) || ((UINT64
)VarValue
> IfrNumeric
->data
.u64
.MaxValue
)) {
1617 // Not in the valid range.
1619 return EFI_INVALID_PARAMETER
;
1628 case EFI_IFR_CHECKBOX_OP
:
1630 // Check value is BOOLEAN type, only 0 and 1 is valid.
1634 // CheckBox question is not in IFR Form. This IFR form is not valid.
1636 if (VarStoreData
.VarStoreId
== 0) {
1637 return EFI_INVALID_PARAMETER
;
1641 // Check whether this question is for the requested varstore.
1643 IfrCheckBox
= (EFI_IFR_CHECKBOX
*)IfrOpHdr
;
1644 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1648 if (NameValueType
) {
1649 QuestionName
= HiiGetString (HiiHandle
, IfrCheckBox
->Question
.VarStoreInfo
.VarName
, NULL
);
1650 ASSERT (QuestionName
!= NULL
);
1652 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1654 // This question is not in the current configuration string. Skip it.
1659 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1660 if (EFI_ERROR (Status
)) {
1665 // Get Offset by Question header
1667 if (QuestionReferBitField
) {
1669 // Get the byte offset/width for bit field.
1671 BitOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1673 Offset
= BitOffset
/ 8;
1674 TotalBits
= BitOffset
% 8 + BitWidth
;
1675 Width
= (TotalBits
% 8 == 0 ? TotalBits
/ 8 : TotalBits
/ 8 + 1);
1677 Offset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1678 Width
= (UINT16
)sizeof (BOOLEAN
);
1682 // Check whether this question is in current block array.
1684 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1686 // This question is not in the current configuration string. Skip it.
1692 // Check this var question is in the var storage
1694 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1696 // This question exceeds the var store size.
1698 return EFI_INVALID_PARAMETER
;
1702 // Check the current value is in the numeric range.
1705 if (QuestionReferBitField
) {
1707 // Get the value in bit fields.
1709 StartBit
= BitOffset
% 8;
1710 EndBit
= StartBit
+ BitWidth
- 1;
1711 CopyMem ((UINT8
*)&BufferValue
, VarBuffer
+ Offset
, Width
);
1712 VarValue
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1714 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1719 // Boolean type, only 1 and 0 is valid.
1722 return EFI_INVALID_PARAMETER
;
1726 case EFI_IFR_STRING_OP
:
1728 // Check current string length is less than maxsize
1732 // CheckBox question is not in IFR Form. This IFR form is not valid.
1734 if (VarStoreData
.VarStoreId
== 0) {
1735 return EFI_INVALID_PARAMETER
;
1739 // Check whether this question is for the requested varstore.
1741 IfrString
= (EFI_IFR_STRING
*)IfrOpHdr
;
1742 if (IfrString
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1747 // Get the Max size of the string.
1749 Width
= (UINT16
)(IfrString
->MaxSize
* sizeof (UINT16
));
1750 if (NameValueType
) {
1751 QuestionName
= HiiGetString (HiiHandle
, IfrString
->Question
.VarStoreInfo
.VarName
, NULL
);
1752 ASSERT (QuestionName
!= NULL
);
1754 StringPtr
= StrStr (RequestElement
, QuestionName
);
1755 if (StringPtr
== NULL
) {
1757 // This question is not in the current configuration string. Skip it.
1763 // Skip the VarName.
1765 StringPtr
+= StrLen (QuestionName
);
1773 // Check current string length is less than maxsize
1774 // e.g Config String: "0041004200430044", Unicode String: "ABCD". Unicode String length = Config String length / 4.
1775 // Config string format in UEFI spec.
1776 // <NvConfig> ::= <Label>'='<String>
1777 // <String> ::= [<Char>]+
1778 // <Char> ::= <HexCh>4
1780 if (StrLen (StringPtr
) / 4 > IfrString
->MaxSize
) {
1781 return EFI_INVALID_PARAMETER
;
1785 // Get Offset/Width by Question header and OneOf Flags
1787 Offset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1789 // Check whether this question is in current block array.
1791 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1793 // This question is not in the current configuration string. Skip it.
1799 // Check this var question is in the var storage
1801 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1803 // This question exceeds the var store size.
1805 return EFI_INVALID_PARAMETER
;
1809 // Check current string length is less than maxsize
1811 if (StrLen ((CHAR16
*)(VarBuffer
+ Offset
)) > IfrString
->MaxSize
) {
1812 return EFI_INVALID_PARAMETER
;
1817 case EFI_IFR_ONE_OF_OPTION_OP
:
1819 // Opcode Scope is zero. This one of option is not to be checked.
1821 if (VarBlockData
.Scope
== 0) {
1826 // Only check for OneOf and OrderList opcode
1828 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*)IfrOpHdr
;
1829 if (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
) {
1831 // Check current value is the value of one of option.
1833 ASSERT (IfrOneOfOption
->Type
<= EFI_IFR_TYPE_NUM_SIZE_64
);
1834 ZeroMem (&TmpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
1835 CopyMem (&TmpValue
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
1836 if (VarValue
== TmpValue
.u64
) {
1838 // The value is one of option value.
1839 // Set OpCode to Zero, don't need check again.
1841 VarBlockData
.OpCode
= 0;
1846 case EFI_IFR_END_OP
:
1847 QuestionReferBitField
= FALSE
;
1849 // Decrease opcode scope for the validated opcode
1851 if (VarBlockData
.Scope
> 0) {
1852 VarBlockData
.Scope
--;
1856 // OneOf value doesn't belong to one of option value.
1858 if ((VarBlockData
.Scope
== 0) && (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
)) {
1859 return EFI_INVALID_PARAMETER
;
1863 case EFI_IFR_GUID_OP
:
1864 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
1865 QuestionReferBitField
= TRUE
;
1871 // Increase Scope for the validated opcode
1873 if (VarBlockData
.Scope
> 0) {
1874 VarBlockData
.Scope
= (UINT8
)(VarBlockData
.Scope
+ IfrOpHdr
->Scope
);
1881 // Go to the next opcode
1883 IfrOffset
+= IfrOpHdr
->Length
;
1887 // Only one form is in a package list.
1893 // Go to next package.
1895 PackageOffset
+= PackageHeader
.Length
;
1902 This internal function parses IFR data to validate current setting.
1904 @param ConfigElement ConfigResp element string contains the current setting.
1905 @param CurrentBlockArray Current block array.
1906 @param VarBuffer Data buffer for this varstore.
1908 @retval EFI_SUCCESS The current setting is valid.
1909 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1910 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1914 IN CHAR16
*ConfigElement
,
1915 OUT IFR_BLOCK_DATA
**CurrentBlockArray
,
1916 OUT UINT8
**VarBuffer
1919 IFR_BLOCK_DATA
*BlockData
;
1920 IFR_BLOCK_DATA
*NewBlockData
;
1921 EFI_STRING StringPtr
;
1927 UINTN MaxBufferSize
;
1929 IFR_BLOCK_DATA
*BlockArray
;
1933 // Initialize the local variables.
1935 Status
= EFI_SUCCESS
;
1937 NewBlockData
= NULL
;
1940 MaxBufferSize
= HII_LIB_DEFAULT_VARSTORE_SIZE
;
1941 DataBuffer
= AllocateZeroPool (MaxBufferSize
);
1942 if (DataBuffer
== NULL
) {
1943 return EFI_OUT_OF_RESOURCES
;
1949 BlockArray
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1950 if (BlockArray
== NULL
) {
1951 Status
= EFI_OUT_OF_RESOURCES
;
1955 InitializeListHead (&BlockArray
->Entry
);
1957 StringPtr
= StrStr (ConfigElement
, L
"&OFFSET=");
1958 ASSERT (StringPtr
!= NULL
);
1961 // Parse each <RequestElement> if exists
1962 // Only <BlockName> format is supported by this help function.
1963 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1965 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1967 // Skip the &OFFSET= string
1969 StringPtr
+= StrLen (L
"&OFFSET=");
1974 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1975 if (EFI_ERROR (Status
)) {
1983 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1985 FreePool (TmpBuffer
);
1988 StringPtr
+= Length
;
1989 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1990 Status
= EFI_INVALID_PARAMETER
;
1994 StringPtr
+= StrLen (L
"&WIDTH=");
1999 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2000 if (EFI_ERROR (Status
)) {
2008 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2010 FreePool (TmpBuffer
);
2013 StringPtr
+= Length
;
2014 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
2015 Status
= EFI_INVALID_PARAMETER
;
2019 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
2020 Status
= EFI_INVALID_PARAMETER
;
2024 StringPtr
+= StrLen (L
"&VALUE=");
2029 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2030 if (EFI_ERROR (Status
)) {
2034 StringPtr
+= Length
;
2035 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
2036 Status
= EFI_INVALID_PARAMETER
;
2041 // Check whether VarBuffer is enough
2043 if ((UINT32
)Offset
+ Width
> MaxBufferSize
) {
2044 DataBuffer
= ReallocatePool (
2046 Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
,
2049 if (DataBuffer
== NULL
) {
2050 Status
= EFI_OUT_OF_RESOURCES
;
2054 MaxBufferSize
= Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
;
2058 // Update the Block with configuration info
2060 CopyMem (DataBuffer
+ Offset
, TmpBuffer
, Width
);
2061 FreePool (TmpBuffer
);
2065 // Set new Block Data
2067 NewBlockData
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2068 if (NewBlockData
== NULL
) {
2069 Status
= EFI_OUT_OF_RESOURCES
;
2073 NewBlockData
->Offset
= Offset
;
2074 NewBlockData
->Width
= Width
;
2077 // Insert the new block data into the block data array.
2079 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
2080 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2081 if (NewBlockData
->Offset
== BlockData
->Offset
) {
2082 if (NewBlockData
->Width
> BlockData
->Width
) {
2083 BlockData
->Width
= NewBlockData
->Width
;
2086 FreePool (NewBlockData
);
2088 } else if (NewBlockData
->Offset
< BlockData
->Offset
) {
2090 // Insert new block data as the previous one of this link.
2092 InsertTailList (Link
, &NewBlockData
->Entry
);
2098 // Insert new block data into the array tail.
2100 if (Link
== &BlockArray
->Entry
) {
2101 InsertTailList (Link
, &NewBlockData
->Entry
);
2105 // If '\0', parsing is finished.
2107 if (*StringPtr
== 0) {
2112 // Go to next ConfigBlock
2117 // Merge the aligned block data into the single block data.
2119 Link
= BlockArray
->Entry
.ForwardLink
;
2120 while ((Link
!= &BlockArray
->Entry
) && (Link
->ForwardLink
!= &BlockArray
->Entry
)) {
2121 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2122 NewBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2123 if ((NewBlockData
->Offset
>= BlockData
->Offset
) && (NewBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2124 if ((NewBlockData
->Offset
+ NewBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2125 BlockData
->Width
= (UINT16
)(NewBlockData
->Offset
+ NewBlockData
->Width
- BlockData
->Offset
);
2128 RemoveEntryList (Link
->ForwardLink
);
2129 FreePool (NewBlockData
);
2133 Link
= Link
->ForwardLink
;
2136 *VarBuffer
= DataBuffer
;
2137 *CurrentBlockArray
= BlockArray
;
2141 if (DataBuffer
!= NULL
) {
2142 FreePool (DataBuffer
);
2145 if (BlockArray
!= NULL
) {
2147 // Free Link Array CurrentBlockArray
2149 while (!IsListEmpty (&BlockArray
->Entry
)) {
2150 BlockData
= BASE_CR (BlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2151 RemoveEntryList (&BlockData
->Entry
);
2152 FreePool (BlockData
);
2155 FreePool (BlockArray
);
2162 This internal function parses IFR data to validate current setting.
2164 @param ConfigResp ConfigResp string contains the current setting.
2165 @param HiiPackageList Point to Hii package list.
2166 @param PackageListLength The length of the pacakge.
2167 @param VarGuid Guid of the buffer storage.
2168 @param VarName Name of the buffer storage.
2169 @param HiiHandle The HiiHandle for this package.
2171 @retval EFI_SUCCESS The current setting is valid.
2172 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
2173 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
2177 InternalHiiValidateCurrentSetting (
2178 IN EFI_STRING ConfigResp
,
2179 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
2180 IN UINTN PackageListLength
,
2181 IN EFI_GUID
*VarGuid
,
2183 IN EFI_HII_HANDLE HiiHandle
2188 IFR_BLOCK_DATA
*CurrentBlockArray
;
2189 IFR_BLOCK_DATA
*BlockData
;
2191 BOOLEAN NameValueType
;
2193 CurrentBlockArray
= NULL
;
2196 Status
= EFI_SUCCESS
;
2199 // If StringPtr != NULL, get the request elements.
2201 if (StrStr (ConfigResp
, L
"&OFFSET=") != NULL
) {
2202 Status
= GetBlockDataInfo (ConfigResp
, &CurrentBlockArray
, &VarBuffer
);
2203 if (EFI_ERROR (Status
)) {
2207 NameValueType
= FALSE
;
2210 // Skip header part.
2212 StringPtr
= StrStr (ConfigResp
, L
"PATH=");
2213 ASSERT (StringPtr
!= NULL
);
2215 if (StrStr (StringPtr
, L
"&") != NULL
) {
2216 NameValueType
= TRUE
;
2219 // Not found Request element, return success.
2225 Status
= ValidateQuestionFromVfr (
2237 if (VarBuffer
!= NULL
) {
2238 FreePool (VarBuffer
);
2241 if (CurrentBlockArray
!= NULL
) {
2243 // Free Link Array CurrentBlockArray
2245 while (!IsListEmpty (&CurrentBlockArray
->Entry
)) {
2246 BlockData
= BASE_CR (CurrentBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2247 RemoveEntryList (&BlockData
->Entry
);
2248 FreePool (BlockData
);
2251 FreePool (CurrentBlockArray
);
2258 Check whether the ConfigRequest string has the request elements.
2259 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
2260 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
2262 @param ConfigRequest The input config request string.
2264 @retval TRUE The input include config request elements.
2265 @retval FALSE The input string not includes.
2269 GetElementsFromRequest (
2270 IN EFI_STRING ConfigRequest
2273 EFI_STRING TmpRequest
;
2275 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
2276 ASSERT (TmpRequest
!= NULL
);
2278 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
2286 This function parses the input ConfigRequest string and its matched IFR code
2287 string for setting default value and validating current setting.
2289 1. For setting default action, Reset the default value specified by DefaultId
2290 to the driver configuration got by Request string.
2291 2. For validating current setting, Validate the current configuration
2292 by parsing HII form IFR opcode.
2294 NULL request string support depends on the ExportConfig interface of
2295 HiiConfigRouting protocol in UEFI specification.
2297 @param Request A null-terminated Unicode string in
2298 <MultiConfigRequest> format. It can be NULL.
2299 If it is NULL, all current configuration for the
2300 entirety of the current HII database will be validated.
2301 If it is NULL, all configuration for the
2302 entirety of the current HII database will be reset.
2303 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.
2304 @param ActionType Action supports setting defaults and validate current setting.
2306 @retval TRUE Action runs successfully.
2307 @retval FALSE Action is not valid or Action can't be executed successfully..
2311 InternalHiiIfrValueAction (
2312 IN CONST EFI_STRING Request OPTIONAL
,
2313 IN UINT16 DefaultId
,
2317 EFI_STRING ConfigAltResp
;
2318 EFI_STRING ConfigAltHdr
;
2319 EFI_STRING ConfigResp
;
2320 EFI_STRING Progress
;
2321 EFI_STRING StringPtr
;
2322 EFI_STRING StringHdr
;
2324 EFI_HANDLE DriverHandle
;
2325 EFI_HANDLE TempDriverHandle
;
2326 EFI_HII_HANDLE
*HiiHandleBuffer
;
2327 EFI_HII_HANDLE HiiHandle
;
2332 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
2333 UINTN PackageListLength
;
2335 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2336 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2338 ConfigAltResp
= NULL
;
2343 ConfigAltHdr
= NULL
;
2344 HiiHandleBuffer
= NULL
;
2346 TempDriverHandle
= NULL
;
2348 HiiPackageList
= NULL
;
2351 // Only support set default and validate setting action.
2353 if ((ActionType
!= ACTION_SET_DEFAUTL_VALUE
) && (ActionType
!= ACTION_VALIDATE_SETTING
)) {
2358 // Get the full requested value and deault value string.
2360 if (Request
!= NULL
) {
2361 Status
= gHiiConfigRouting
->ExtractConfig (
2368 Status
= gHiiConfigRouting
->ExportConfig (
2374 if (EFI_ERROR (Status
)) {
2378 StringPtr
= ConfigAltResp
;
2379 ASSERT (StringPtr
!= NULL
);
2381 while (*StringPtr
!= L
'\0') {
2383 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
2385 StringHdr
= StringPtr
;
2390 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2391 Status
= EFI_INVALID_PARAMETER
;
2395 StringPtr
+= StrLen (L
"GUID=");
2396 Status
= InternalHiiGetBufferFromString (StringPtr
, GUID_CONFIG_STRING_TYPE
, (UINT8
**)&VarGuid
);
2397 if (EFI_ERROR (Status
)) {
2402 // Get Name value VarName
2404 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2408 if (*StringPtr
== L
'\0') {
2409 Status
= EFI_INVALID_PARAMETER
;
2413 StringPtr
+= StrLen (L
"&NAME=");
2414 Status
= InternalHiiGetBufferFromString (StringPtr
, NAME_CONFIG_STRING_TYPE
, (UINT8
**)&VarName
);
2415 if (EFI_ERROR (Status
)) {
2420 // Get Path value DevicePath
2422 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2426 if (*StringPtr
== L
'\0') {
2427 Status
= EFI_INVALID_PARAMETER
;
2431 StringPtr
+= StrLen (L
"&PATH=");
2432 Status
= InternalHiiGetBufferFromString (StringPtr
, PATH_CONFIG_STRING_TYPE
, (UINT8
**)&DevicePath
);
2433 if (EFI_ERROR (Status
)) {
2438 // Get the Driver handle by the got device path.
2440 TempDevicePath
= DevicePath
;
2441 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDevicePath
, &DriverHandle
);
2442 if (EFI_ERROR (Status
)) {
2447 // Find the matched Hii Handle for the found Driver handle
2449 HiiHandleBuffer
= HiiGetHiiHandles (NULL
);
2450 if (HiiHandleBuffer
== NULL
) {
2451 Status
= EFI_NOT_FOUND
;
2455 for (Index
= 0; HiiHandleBuffer
[Index
] != NULL
; Index
++) {
2456 gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, HiiHandleBuffer
[Index
], &TempDriverHandle
);
2457 if (TempDriverHandle
== DriverHandle
) {
2462 HiiHandle
= HiiHandleBuffer
[Index
];
2463 FreePool (HiiHandleBuffer
);
2465 if (HiiHandle
== NULL
) {
2467 // This request string has no its Hii package.
2468 // Its default value and validating can't execute by parsing IFR data.
2469 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
2471 Status
= EFI_SUCCESS
;
2472 goto NextConfigAltResp
;
2476 // 2. Get HiiPackage by HiiHandle
2478 PackageListLength
= 0;
2479 HiiPackageList
= NULL
;
2480 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2483 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
2485 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2486 Status
= EFI_INVALID_PARAMETER
;
2490 HiiPackageList
= AllocatePool (PackageListLength
);
2491 if (HiiPackageList
== NULL
) {
2492 Status
= EFI_OUT_OF_RESOURCES
;
2497 // Get PackageList on HiiHandle
2499 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2500 if (EFI_ERROR (Status
)) {
2505 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2506 // Get the default configuration string according to the default ID.
2508 Status
= gHiiConfigRouting
->GetAltConfig (
2514 (ActionType
== ACTION_SET_DEFAUTL_VALUE
) ? &DefaultId
: NULL
, // it can be NULL to get the current setting.
2519 // The required setting can't be found. So, it is not required to be validated and set.
2521 if (EFI_ERROR (Status
)) {
2522 Status
= EFI_SUCCESS
;
2523 goto NextConfigAltResp
;
2527 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
2529 if (!GetElementsFromRequest (ConfigResp
)) {
2530 goto NextConfigAltResp
;
2534 // 4. Set the default configuration information or Validate current setting by parse IFR code.
2535 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2537 if (ActionType
== ACTION_SET_DEFAUTL_VALUE
) {
2539 // Set the default configuration information.
2541 Status
= gHiiConfigRouting
->RouteConfig (gHiiConfigRouting
, ConfigResp
, &Progress
);
2544 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2546 Status
= InternalHiiValidateCurrentSetting (ConfigResp
, HiiPackageList
, PackageListLength
, VarGuid
, VarName
, HiiHandle
);
2549 if (EFI_ERROR (Status
)) {
2555 // Free the allocated pacakge buffer and the got ConfigResp string.
2557 if (HiiPackageList
!= NULL
) {
2558 FreePool (HiiPackageList
);
2559 HiiPackageList
= NULL
;
2562 if (ConfigResp
!= NULL
) {
2563 FreePool (ConfigResp
);
2568 // Free the allocated buffer.
2576 FreePool (DevicePath
);
2580 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
2584 // Get and Skip ConfigHdr
2586 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2590 if (*StringPtr
== L
'\0') {
2595 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"
2596 // | 1 | StrLen (ConfigHdr) | 8 | 1 |
2598 MaxLen
= 1 + StringPtr
- StringHdr
+ 8 + 1;
2599 ConfigAltHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2600 if (ConfigAltHdr
== NULL
) {
2601 Status
= EFI_OUT_OF_RESOURCES
;
2605 StrCpyS (ConfigAltHdr
, MaxLen
, L
"&");
2606 StrnCatS (ConfigAltHdr
, MaxLen
, StringHdr
, StringPtr
- StringHdr
);
2607 StrCatS (ConfigAltHdr
, MaxLen
, L
"&ALTCFG=");
2610 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
2612 while ((StringHdr
= StrStr (StringPtr
, ConfigAltHdr
)) != NULL
) {
2613 StringPtr
= StringHdr
+ StrLen (ConfigAltHdr
);
2614 if (*StringPtr
== L
'\0') {
2620 // Free the allocated ConfigAltHdr string
2622 FreePool (ConfigAltHdr
);
2623 if (*StringPtr
== L
'\0') {
2628 // Find &GUID as the next ConfigHdr
2630 StringPtr
= StrStr (StringPtr
, L
"&GUID");
2631 if (StringPtr
== NULL
) {
2642 if (VarGuid
!= NULL
) {
2646 if (VarName
!= NULL
) {
2650 if (DevicePath
!= NULL
) {
2651 FreePool (DevicePath
);
2654 if (ConfigResp
!= NULL
) {
2655 FreePool (ConfigResp
);
2658 if (ConfigAltResp
!= NULL
) {
2659 FreePool (ConfigAltResp
);
2662 if (HiiPackageList
!= NULL
) {
2663 FreePool (HiiPackageList
);
2666 if (EFI_ERROR (Status
)) {
2674 Validate the current configuration by parsing HII form IFR opcode.
2676 NULL request string support depends on the ExportConfig interface of
2677 HiiConfigRouting protocol in UEFI specification.
2679 @param Request A null-terminated Unicode string in
2680 <MultiConfigRequest> format. It can be NULL.
2681 If it is NULL, all current configuration for the
2682 entirety of the current HII database will be validated.
2684 @retval TRUE Current configuration is valid.
2685 @retval FALSE Current configuration is invalid.
2689 HiiValidateSettings (
2690 IN CONST EFI_STRING Request OPTIONAL
2693 return InternalHiiIfrValueAction (Request
, 0, ACTION_VALIDATE_SETTING
);
2697 Reset the default value specified by DefaultId to the driver
2698 configuration got by Request string.
2700 NULL request string support depends on the ExportConfig interface of
2701 HiiConfigRouting protocol in UEFI specification.
2703 @param Request A null-terminated Unicode string in
2704 <MultiConfigRequest> format. It can be NULL.
2705 If it is NULL, all configuration for the
2706 entirety of the current HII database will be reset.
2707 @param DefaultId Specifies the type of defaults to retrieve.
2709 @retval TRUE The default value is set successfully.
2710 @retval FALSE The default value can't be found and set.
2715 IN CONST EFI_STRING Request OPTIONAL
,
2719 return InternalHiiIfrValueAction (Request
, DefaultId
, ACTION_SET_DEFAUTL_VALUE
);
2723 Determines if two values in config strings match.
2725 Compares the substring between StartSearchString and StopSearchString in
2726 FirstString to the substring between StartSearchString and StopSearchString
2727 in SecondString. If the two substrings match, then TRUE is returned. If the
2728 two substrings do not match, then FALSE is returned.
2730 If FirstString is NULL, then ASSERT().
2731 If SecondString is NULL, then ASSERT().
2732 If StartSearchString is NULL, then ASSERT().
2733 If StopSearchString is NULL, then ASSERT().
2735 @param FirstString Pointer to the first Null-terminated Unicode string.
2736 @param SecondString Pointer to the second Null-terminated Unicode string.
2737 @param StartSearchString Pointer to the Null-terminated Unicode string that
2738 marks the start of the value string to compare.
2739 @param StopSearchString Pointer to the Null-terminated Unicode string that
2740 marks the end of the value string to compare.
2742 @retval FALSE StartSearchString is not present in FirstString.
2743 @retval FALSE StartSearchString is not present in SecondString.
2744 @retval FALSE StopSearchString is not present in FirstString.
2745 @retval FALSE StopSearchString is not present in SecondString.
2746 @retval FALSE The length of the substring in FirstString is not the
2747 same length as the substring in SecondString.
2748 @retval FALSE The value string in FirstString does not matche the
2749 value string in SecondString.
2750 @retval TRUE The value string in FirstString matches the value
2751 string in SecondString.
2756 InternalHiiCompareSubString (
2757 IN CHAR16
*FirstString
,
2758 IN CHAR16
*SecondString
,
2759 IN CHAR16
*StartSearchString
,
2760 IN CHAR16
*StopSearchString
2763 CHAR16
*EndFirstString
;
2764 CHAR16
*EndSecondString
;
2766 ASSERT (FirstString
!= NULL
);
2767 ASSERT (SecondString
!= NULL
);
2768 ASSERT (StartSearchString
!= NULL
);
2769 ASSERT (StopSearchString
!= NULL
);
2771 FirstString
= StrStr (FirstString
, StartSearchString
);
2772 if (FirstString
== NULL
) {
2776 SecondString
= StrStr (SecondString
, StartSearchString
);
2777 if (SecondString
== NULL
) {
2781 EndFirstString
= StrStr (FirstString
, StopSearchString
);
2782 if (EndFirstString
== NULL
) {
2786 EndSecondString
= StrStr (SecondString
, StopSearchString
);
2787 if (EndSecondString
== NULL
) {
2791 if ((EndFirstString
- FirstString
) != (EndSecondString
- SecondString
)) {
2795 return (BOOLEAN
)(StrnCmp (FirstString
, SecondString
, EndFirstString
- FirstString
) == 0);
2799 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
2801 If ConfigHdr is NULL, then ASSERT().
2803 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
2804 @param[in] Guid GUID of the storage.
2805 @param[in] Name NAME of the storage.
2807 @retval TRUE Routing information matches <ConfigHdr>.
2808 @retval FALSE Routing information does not match <ConfigHdr>.
2813 HiiIsConfigHdrMatch (
2814 IN CONST EFI_STRING ConfigHdr
,
2815 IN CONST EFI_GUID
*Guid OPTIONAL
,
2816 IN CONST CHAR16
*Name OPTIONAL
2819 EFI_STRING CompareConfigHdr
;
2822 ASSERT (ConfigHdr
!= NULL
);
2825 // Use Guid and Name to generate a <ConfigHdr> string
2827 CompareConfigHdr
= HiiConstructConfigHdr (Guid
, Name
, NULL
);
2828 if (CompareConfigHdr
== NULL
) {
2835 // Compare GUID value strings
2837 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"GUID=", L
"&NAME=");
2840 if (Result
&& (Name
!= NULL
)) {
2842 // Compare NAME value strings
2844 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"&NAME=", L
"&PATH=");
2848 // Free the <ConfigHdr> string
2850 FreePool (CompareConfigHdr
);
2856 Retrieves uncommitted data from the Form Browser and converts it to a binary
2859 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2860 parameter that may be NULL.
2861 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2862 is an optional parameter that may be NULL.
2863 @param[in] BufferSize Length in bytes of buffer to hold retrieved data.
2864 @param[out] Buffer Buffer of data to be updated.
2866 @retval FALSE The uncommitted data could not be retrieved.
2867 @retval TRUE The uncommitted data was retrieved.
2873 IN CONST EFI_GUID
*VariableGuid OPTIONAL
,
2874 IN CONST CHAR16
*VariableName OPTIONAL
,
2875 IN UINTN BufferSize
,
2879 EFI_STRING ResultsData
;
2881 EFI_STRING ConfigResp
;
2886 // Retrieve the results data from the Browser Callback
2888 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, NULL
);
2889 if (ResultsData
== NULL
) {
2894 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
2896 Size
= (StrLen (mConfigHdrTemplate
) + 1) * sizeof (CHAR16
);
2897 Size
= Size
+ (StrLen (ResultsData
) + 1) * sizeof (CHAR16
);
2898 ConfigResp
= AllocateZeroPool (Size
);
2899 UnicodeSPrint (ConfigResp
, Size
, L
"%s&%s", mConfigHdrTemplate
, ResultsData
);
2902 // Free the allocated buffer
2904 FreePool (ResultsData
);
2905 if (ConfigResp
== NULL
) {
2910 // Convert <ConfigResp> to a buffer
2912 Status
= gHiiConfigRouting
->ConfigToBlock (
2920 // Free the allocated buffer
2922 FreePool (ConfigResp
);
2924 if (EFI_ERROR (Status
)) {
2932 Updates uncommitted data in the Form Browser.
2934 If Buffer is NULL, then ASSERT().
2936 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2937 parameter that may be NULL.
2938 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2939 is an optional parameter that may be NULL.
2940 @param[in] BufferSize Length, in bytes, of Buffer.
2941 @param[in] Buffer Buffer of data to commit.
2942 @param[in] RequestElement An optional field to specify which part of the
2943 buffer data will be send back to Browser. If NULL,
2944 the whole buffer of data will be committed to
2946 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
2948 @retval FALSE The uncommitted data could not be updated.
2949 @retval TRUE The uncommitted data was updated.
2955 IN CONST EFI_GUID
*VariableGuid OPTIONAL
,
2956 IN CONST CHAR16
*VariableName OPTIONAL
,
2957 IN UINTN BufferSize
,
2958 IN CONST UINT8
*Buffer
,
2959 IN CONST CHAR16
*RequestElement OPTIONAL
2963 EFI_STRING ConfigRequest
;
2964 EFI_STRING ConfigResp
;
2965 EFI_STRING ResultsData
;
2967 ASSERT (Buffer
!= NULL
);
2970 // Construct <ConfigRequest>
2972 if (RequestElement
== NULL
) {
2974 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2975 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2977 Size
= (StrLen (mConfigHdrTemplate
) + 32 + 1) * sizeof (CHAR16
);
2978 ConfigRequest
= AllocateZeroPool (Size
);
2979 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate
, (UINT64
)BufferSize
);
2982 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2983 // followed by <RequestElement> followed by a Null-terminator
2985 Size
= StrLen (mConfigHdrTemplate
) * sizeof (CHAR16
);
2986 Size
= Size
+ (StrLen (RequestElement
) + 1) * sizeof (CHAR16
);
2987 ConfigRequest
= AllocateZeroPool (Size
);
2988 UnicodeSPrint (ConfigRequest
, Size
, L
"%s%s", mConfigHdrTemplate
, RequestElement
);
2991 if (ConfigRequest
== NULL
) {
2996 // Convert <ConfigRequest> to <ConfigResp>
2998 ConfigResp
= InternalHiiBlockToConfig (ConfigRequest
, Buffer
, BufferSize
);
2999 FreePool (ConfigRequest
);
3000 if (ConfigResp
== NULL
) {
3005 // Set data in the uncommitted browser state information
3007 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, ConfigResp
+ StrLen (mConfigHdrTemplate
) + 1);
3008 FreePool (ConfigResp
);
3010 return (BOOLEAN
)(ResultsData
!= NULL
);
3013 /////////////////////////////////////////
3014 /////////////////////////////////////////
3016 /////////////////////////////////////////
3017 /////////////////////////////////////////
3019 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
3025 } HII_LIB_OPCODE_BUFFER
;
3028 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
3030 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth
[] = {
3031 1, // EFI_IFR_TYPE_NUM_SIZE_8
3032 2, // EFI_IFR_TYPE_NUM_SIZE_16
3033 4, // EFI_IFR_TYPE_NUM_SIZE_32
3034 8, // EFI_IFR_TYPE_NUM_SIZE_64
3035 1, // EFI_IFR_TYPE_BOOLEAN
3036 3, // EFI_IFR_TYPE_TIME
3037 4, // EFI_IFR_TYPE_DATE
3038 2 // EFI_IFR_TYPE_STRING
3042 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
3043 HiiFreeOpCodeHandle().
3045 @retval NULL There are not enough resources to allocate a new OpCode Handle.
3046 @retval Other A new OpCode handle.
3051 HiiAllocateOpCodeHandle (
3055 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
3057 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER
));
3058 if (OpCodeBuffer
== NULL
) {
3062 OpCodeBuffer
->Buffer
= (UINT8
*)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE
);
3063 if (OpCodeBuffer
->Buffer
== NULL
) {
3064 FreePool (OpCodeBuffer
);
3068 OpCodeBuffer
->BufferSize
= HII_LIB_OPCODE_ALLOCATION_SIZE
;
3069 OpCodeBuffer
->Position
= 0;
3070 return (VOID
*)OpCodeBuffer
;
3074 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
3075 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
3076 Handle are also freed.
3078 If OpCodeHandle is NULL, then ASSERT().
3080 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3085 HiiFreeOpCodeHandle (
3089 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
3091 ASSERT (OpCodeHandle
!= NULL
);
3093 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
3094 if (OpCodeBuffer
->Buffer
!= NULL
) {
3095 FreePool (OpCodeBuffer
->Buffer
);
3098 FreePool (OpCodeBuffer
);
3102 Internal function gets the current position of opcode buffer.
3104 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3106 @return Current position of opcode buffer.
3110 InternalHiiOpCodeHandlePosition (
3111 IN VOID
*OpCodeHandle
3114 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Position
;
3118 Internal function gets the start pointer of opcode buffer.
3120 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3122 @return Pointer to the opcode buffer base.
3126 InternalHiiOpCodeHandleBuffer (
3127 IN VOID
*OpCodeHandle
3130 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Buffer
;
3134 Internal function reserves the enough buffer for current opcode.
3135 When the buffer is not enough, Opcode buffer will be extended.
3137 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3138 @param[in] Size Size of current opcode.
3140 @return Pointer to the current opcode.
3144 InternalHiiGrowOpCodeHandle (
3145 IN VOID
*OpCodeHandle
,
3149 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
3152 ASSERT (OpCodeHandle
!= NULL
);
3154 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
3155 if (OpCodeBuffer
->Position
+ Size
> OpCodeBuffer
->BufferSize
) {
3156 Buffer
= ReallocatePool (
3157 OpCodeBuffer
->BufferSize
,
3158 OpCodeBuffer
->BufferSize
+ (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
),
3159 OpCodeBuffer
->Buffer
3161 ASSERT (Buffer
!= NULL
);
3162 OpCodeBuffer
->Buffer
= Buffer
;
3163 OpCodeBuffer
->BufferSize
+= (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
);
3166 Buffer
= OpCodeBuffer
->Buffer
+ OpCodeBuffer
->Position
;
3167 OpCodeBuffer
->Position
+= Size
;
3172 Internal function creates opcode based on the template opcode.
3174 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3175 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
3176 @param[in] OpCode OpCode IFR value.
3177 @param[in] OpCodeSize Size of opcode.
3178 @param[in] ExtensionSize Size of extended opcode.
3179 @param[in] Scope Scope bit of opcode.
3181 @return Pointer to the current opcode with opcode data.
3185 InternalHiiCreateOpCodeExtended (
3186 IN VOID
*OpCodeHandle
,
3187 IN VOID
*OpCodeTemplate
,
3189 IN UINTN OpCodeSize
,
3190 IN UINTN ExtensionSize
,
3194 EFI_IFR_OP_HEADER
*Header
;
3197 ASSERT (OpCodeTemplate
!= NULL
);
3198 ASSERT ((OpCodeSize
+ ExtensionSize
) <= 0x7F);
3200 Header
= (EFI_IFR_OP_HEADER
*)OpCodeTemplate
;
3201 Header
->OpCode
= OpCode
;
3202 Header
->Scope
= Scope
;
3203 Header
->Length
= (UINT8
)(OpCodeSize
+ ExtensionSize
);
3204 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, Header
->Length
);
3205 return (UINT8
*)CopyMem (Buffer
, Header
, OpCodeSize
);
3209 Internal function creates opcode based on the template opcode for the normal opcode.
3211 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3212 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
3213 @param[in] OpCode OpCode IFR value.
3214 @param[in] OpCodeSize Size of opcode.
3216 @return Pointer to the current opcode with opcode data.
3220 InternalHiiCreateOpCode (
3221 IN VOID
*OpCodeHandle
,
3222 IN VOID
*OpCodeTemplate
,
3227 return InternalHiiCreateOpCodeExtended (OpCodeHandle
, OpCodeTemplate
, OpCode
, OpCodeSize
, 0, 0);
3231 Append raw opcodes to an OpCodeHandle.
3233 If OpCodeHandle is NULL, then ASSERT().
3234 If RawBuffer is NULL, then ASSERT();
3236 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3237 @param[in] RawBuffer Buffer of opcodes to append.
3238 @param[in] RawBufferSize The size, in bytes, of Buffer.
3240 @retval NULL There is not enough space left in Buffer to add the opcode.
3241 @retval Other A pointer to the appended opcodes.
3246 HiiCreateRawOpCodes (
3247 IN VOID
*OpCodeHandle
,
3248 IN UINT8
*RawBuffer
,
3249 IN UINTN RawBufferSize
3254 ASSERT (RawBuffer
!= NULL
);
3256 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, RawBufferSize
);
3257 return (UINT8
*)CopyMem (Buffer
, RawBuffer
, RawBufferSize
);
3261 Append opcodes from one OpCode Handle to another OpCode handle.
3263 If OpCodeHandle is NULL, then ASSERT().
3264 If RawOpCodeHandle is NULL, then ASSERT();
3266 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3267 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
3269 @retval NULL There is not enough space left in Buffer to add the opcode.
3270 @retval Other A pointer to the appended opcodes.
3275 InternalHiiAppendOpCodes (
3276 IN VOID
*OpCodeHandle
,
3277 IN VOID
*RawOpCodeHandle
3280 HII_LIB_OPCODE_BUFFER
*RawOpCodeBuffer
;
3282 ASSERT (RawOpCodeHandle
!= NULL
);
3284 RawOpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)RawOpCodeHandle
;
3285 return HiiCreateRawOpCodes (OpCodeHandle
, RawOpCodeBuffer
->Buffer
, RawOpCodeBuffer
->Position
);
3289 Create EFI_IFR_END_OP opcode.
3291 If OpCodeHandle is NULL, then ASSERT().
3293 @param[in] OpCodeHandle Handle to the buffer of opcodes.
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 HiiCreateEndOpCode (
3302 IN VOID
*OpCodeHandle
3307 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_END_OP
, sizeof (OpCode
));
3311 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
3313 If OpCodeHandle is NULL, then ASSERT().
3314 If Type is invalid, then ASSERT().
3315 If Flags is invalid, then ASSERT().
3317 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3318 @param[in] StringId StringId for the option
3319 @param[in] Flags Flags for the option
3320 @param[in] Type Type for the option
3321 @param[in] Value Value for the option
3323 @retval NULL There is not enough space left in Buffer to add the opcode.
3324 @retval Other A pointer to the created opcode.
3329 HiiCreateOneOfOptionOpCode (
3330 IN VOID
*OpCodeHandle
,
3337 EFI_IFR_ONE_OF_OPTION OpCode
;
3339 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
3341 ZeroMem (&OpCode
, sizeof (OpCode
));
3342 OpCode
.Option
= StringId
;
3343 OpCode
.Flags
= (UINT8
)(Flags
& (EFI_IFR_OPTION_DEFAULT
| EFI_IFR_OPTION_DEFAULT_MFG
));
3345 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
3347 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OPTION_OP
, OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
3351 Create EFI_IFR_DEFAULT_OP opcode.
3353 If OpCodeHandle is NULL, then ASSERT().
3354 If Type is invalid, then ASSERT().
3356 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3357 @param[in] DefaultId DefaultId for the default
3358 @param[in] Type Type for the default
3359 @param[in] Value Value for the default
3361 @retval NULL There is not enough space left in Buffer to add the opcode.
3362 @retval Other A pointer to the created opcode.
3367 HiiCreateDefaultOpCode (
3368 IN VOID
*OpCodeHandle
,
3369 IN UINT16 DefaultId
,
3374 EFI_IFR_DEFAULT OpCode
;
3376 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
3378 ZeroMem (&OpCode
, sizeof (OpCode
));
3380 OpCode
.DefaultId
= DefaultId
;
3381 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
3383 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DEFAULT_OP
, OFFSET_OF (EFI_IFR_DEFAULT
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
3387 Create EFI_IFR_GUID opcode.
3389 If OpCodeHandle is NULL, then ASSERT().
3390 If Guid is NULL, then ASSERT().
3391 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
3393 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3394 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
3395 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
3396 optional parameter that may be NULL. If this
3397 parameter is NULL, then the GUID extension
3398 region of the created opcode is filled with zeros.
3399 If this parameter is not NULL, then the GUID
3400 extension region of GuidData will be copied to
3401 the GUID extension region of the created opcode.
3402 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
3403 must be >= sizeof(EFI_IFR_GUID).
3405 @retval NULL There is not enough space left in Buffer to add the opcode.
3406 @retval Other A pointer to the created opcode.
3411 HiiCreateGuidOpCode (
3412 IN VOID
*OpCodeHandle
,
3413 IN CONST EFI_GUID
*Guid
,
3414 IN CONST VOID
*GuidOpCode OPTIONAL
,
3418 EFI_IFR_GUID OpCode
;
3419 EFI_IFR_GUID
*OpCodePointer
;
3421 ASSERT (Guid
!= NULL
);
3422 ASSERT (OpCodeSize
>= sizeof (OpCode
));
3424 ZeroMem (&OpCode
, sizeof (OpCode
));
3425 CopyGuid ((EFI_GUID
*)(VOID
*)&OpCode
.Guid
, Guid
);
3427 OpCodePointer
= (EFI_IFR_GUID
*)InternalHiiCreateOpCodeExtended (
3432 OpCodeSize
- sizeof (OpCode
),
3435 if ((OpCodePointer
!= NULL
) && (GuidOpCode
!= NULL
)) {
3436 CopyMem (OpCodePointer
+ 1, (EFI_IFR_GUID
*)GuidOpCode
+ 1, OpCodeSize
- sizeof (OpCode
));
3439 return (UINT8
*)OpCodePointer
;
3443 Create EFI_IFR_ACTION_OP opcode.
3445 If OpCodeHandle is NULL, then ASSERT().
3446 If any reserved bits are set in QuestionFlags, then ASSERT().
3448 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3449 @param[in] QuestionId Question ID
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] QuestionConfig String ID for configuration
3455 @retval NULL There is not enough space left in Buffer to add the opcode.
3456 @retval Other A pointer to the created opcode.
3461 HiiCreateActionOpCode (
3462 IN VOID
*OpCodeHandle
,
3463 IN EFI_QUESTION_ID QuestionId
,
3464 IN EFI_STRING_ID Prompt
,
3465 IN EFI_STRING_ID Help
,
3466 IN UINT8 QuestionFlags
,
3467 IN EFI_STRING_ID QuestionConfig
3470 EFI_IFR_ACTION OpCode
;
3472 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3474 ZeroMem (&OpCode
, sizeof (OpCode
));
3475 OpCode
.Question
.QuestionId
= QuestionId
;
3476 OpCode
.Question
.Header
.Prompt
= Prompt
;
3477 OpCode
.Question
.Header
.Help
= Help
;
3478 OpCode
.Question
.Flags
= QuestionFlags
;
3479 OpCode
.QuestionConfig
= QuestionConfig
;
3481 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ACTION_OP
, sizeof (OpCode
));
3485 Create EFI_IFR_SUBTITLE_OP opcode.
3487 If OpCodeHandle is NULL, then ASSERT().
3488 If any reserved bits are set in Flags, then ASSERT().
3489 If Scope > 1, then ASSERT().
3491 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3492 @param[in] Prompt String ID for Prompt
3493 @param[in] Help String ID for Help
3494 @param[in] Flags Subtitle opcode flags
3495 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
3496 0 if this opcode is within the current scope.
3498 @retval NULL There is not enough space left in Buffer to add the opcode.
3499 @retval Other A pointer to the created opcode.
3504 HiiCreateSubTitleOpCode (
3505 IN VOID
*OpCodeHandle
,
3506 IN EFI_STRING_ID Prompt
,
3507 IN EFI_STRING_ID Help
,
3512 EFI_IFR_SUBTITLE OpCode
;
3514 ASSERT (Scope
<= 1);
3515 ASSERT ((Flags
& (~(EFI_IFR_FLAGS_HORIZONTAL
))) == 0);
3517 ZeroMem (&OpCode
, sizeof (OpCode
));
3518 OpCode
.Statement
.Prompt
= Prompt
;
3519 OpCode
.Statement
.Help
= Help
;
3520 OpCode
.Flags
= Flags
;
3522 return InternalHiiCreateOpCodeExtended (
3525 EFI_IFR_SUBTITLE_OP
,
3533 Create EFI_IFR_REF_OP opcode.
3535 If OpCodeHandle is NULL, then ASSERT().
3536 If any reserved bits are set in QuestionFlags, then ASSERT().
3538 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3539 @param[in] FormId Destination Form ID
3540 @param[in] Prompt String ID for Prompt
3541 @param[in] Help String ID for Help
3542 @param[in] QuestionFlags Flags in Question Header
3543 @param[in] QuestionId Question ID
3545 @retval NULL There is not enough space left in Buffer to add the opcode.
3546 @retval Other A pointer to the created opcode.
3551 HiiCreateGotoOpCode (
3552 IN VOID
*OpCodeHandle
,
3553 IN EFI_FORM_ID FormId
,
3554 IN EFI_STRING_ID Prompt
,
3555 IN EFI_STRING_ID Help
,
3556 IN UINT8 QuestionFlags
,
3557 IN EFI_QUESTION_ID QuestionId
3562 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3564 ZeroMem (&OpCode
, sizeof (OpCode
));
3565 OpCode
.Question
.Header
.Prompt
= Prompt
;
3566 OpCode
.Question
.Header
.Help
= Help
;
3567 OpCode
.Question
.QuestionId
= QuestionId
;
3568 OpCode
.Question
.Flags
= QuestionFlags
;
3569 OpCode
.FormId
= FormId
;
3571 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, sizeof (OpCode
));
3575 Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.
3577 When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.
3578 When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.
3579 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.
3580 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.
3582 If OpCodeHandle is NULL, then ASSERT().
3583 If any reserved bits are set in QuestionFlags, then ASSERT().
3585 @param[in] OpCodeHandle The handle to the buffer of opcodes.
3586 @param[in] RefFormId The Destination Form ID.
3587 @param[in] Prompt The string ID for Prompt.
3588 @param[in] Help The string ID for Help.
3589 @param[in] QuestionFlags The flags in Question Header
3590 @param[in] QuestionId Question ID.
3591 @param[in] RefQuestionId The question on the form to which this link is referring.
3592 If its value is zero, then the link refers to the top of the form.
3593 @param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is
3594 zero, then the link is to the current form set.
3595 @param[in] RefDevicePath The string identifier that specifies the string containing the text representation of
3596 the device path to which the form set containing the form specified by FormId.
3597 If its value is zero, then the link refers to the current page.
3599 @retval NULL There is not enough space left in Buffer to add the opcode.
3600 @retval Other A pointer to the created opcode.
3605 HiiCreateGotoExOpCode (
3606 IN VOID
*OpCodeHandle
,
3607 IN EFI_FORM_ID RefFormId
,
3608 IN EFI_STRING_ID Prompt
,
3609 IN EFI_STRING_ID Help
,
3610 IN UINT8 QuestionFlags
,
3611 IN EFI_QUESTION_ID QuestionId
,
3612 IN EFI_QUESTION_ID RefQuestionId
,
3613 IN EFI_GUID
*RefFormSetId OPTIONAL
,
3614 IN EFI_STRING_ID RefDevicePath
3617 EFI_IFR_REF4 OpCode
;
3620 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3622 ZeroMem (&OpCode
, sizeof (OpCode
));
3623 OpCode
.Question
.Header
.Prompt
= Prompt
;
3624 OpCode
.Question
.Header
.Help
= Help
;
3625 OpCode
.Question
.QuestionId
= QuestionId
;
3626 OpCode
.Question
.Flags
= QuestionFlags
;
3627 OpCode
.FormId
= RefFormId
;
3628 OpCode
.QuestionId
= RefQuestionId
;
3629 OpCode
.DevicePath
= RefDevicePath
;
3630 if (RefFormSetId
!= NULL
) {
3631 CopyMem (&OpCode
.FormSetId
, RefFormSetId
, sizeof (OpCode
.FormSetId
));
3635 // Cacluate OpCodeSize based on the input Ref value.
3636 // Try to use the small OpCode to save size.
3638 OpCodeSize
= sizeof (EFI_IFR_REF
);
3639 if (RefDevicePath
!= 0) {
3640 OpCodeSize
= sizeof (EFI_IFR_REF4
);
3641 } else if (RefFormSetId
!= NULL
) {
3642 OpCodeSize
= sizeof (EFI_IFR_REF3
);
3643 } else if (RefQuestionId
!= 0) {
3644 OpCodeSize
= sizeof (EFI_IFR_REF2
);
3647 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, OpCodeSize
);
3651 Create EFI_IFR_CHECKBOX_OP opcode.
3653 If OpCodeHandle is NULL, then ASSERT().
3654 If any reserved bits are set in QuestionFlags, then ASSERT().
3655 If any reserved bits are set in CheckBoxFlags, then ASSERT().
3657 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3658 @param[in] QuestionId Question ID
3659 @param[in] VarStoreId Storage ID
3660 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3661 for this name/value pair.
3662 @param[in] Prompt String ID for Prompt
3663 @param[in] Help String ID for Help
3664 @param[in] QuestionFlags Flags in Question Header
3665 @param[in] CheckBoxFlags Flags for checkbox opcode
3666 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3667 is an optional parameter that may be NULL.
3669 @retval NULL There is not enough space left in Buffer to add the opcode.
3670 @retval Other A pointer to the created opcode.
3675 HiiCreateCheckBoxOpCode (
3676 IN VOID
*OpCodeHandle
,
3677 IN EFI_QUESTION_ID QuestionId
,
3678 IN EFI_VARSTORE_ID VarStoreId
,
3679 IN UINT16 VarOffset
,
3680 IN EFI_STRING_ID Prompt
,
3681 IN EFI_STRING_ID Help
,
3682 IN UINT8 QuestionFlags
,
3683 IN UINT8 CheckBoxFlags
,
3684 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3687 EFI_IFR_CHECKBOX OpCode
;
3690 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_REST_STYLE
))) == 0);
3692 ZeroMem (&OpCode
, sizeof (OpCode
));
3693 OpCode
.Question
.QuestionId
= QuestionId
;
3694 OpCode
.Question
.VarStoreId
= VarStoreId
;
3695 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3696 OpCode
.Question
.Header
.Prompt
= Prompt
;
3697 OpCode
.Question
.Header
.Help
= Help
;
3698 OpCode
.Question
.Flags
= QuestionFlags
;
3699 OpCode
.Flags
= CheckBoxFlags
;
3701 if (DefaultsOpCodeHandle
== NULL
) {
3702 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
));
3705 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3706 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
), 0, 1);
3707 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3708 HiiCreateEndOpCode (OpCodeHandle
);
3709 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3713 Create EFI_IFR_NUMERIC_OP opcode.
3715 If OpCodeHandle is NULL, then ASSERT().
3716 If any reserved bits are set in QuestionFlags, then ASSERT().
3717 If any reserved bits are set in NumericFlags, then ASSERT().
3719 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3720 @param[in] QuestionId Question ID
3721 @param[in] VarStoreId Storage ID
3722 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3723 for this name/value pair.
3724 @param[in] Prompt String ID for Prompt
3725 @param[in] Help String ID for Help
3726 @param[in] QuestionFlags Flags in Question Header
3727 @param[in] NumericFlags Flags for numeric opcode
3728 @param[in] Minimum Numeric minimum value
3729 @param[in] Maximum Numeric maximum value
3730 @param[in] Step Numeric step for edit
3731 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3732 is an optional parameter that may be NULL.
3734 @retval NULL There is not enough space left in Buffer to add the opcode.
3735 @retval Other A pointer to the created opcode.
3740 HiiCreateNumericOpCode (
3741 IN VOID
*OpCodeHandle
,
3742 IN EFI_QUESTION_ID QuestionId
,
3743 IN EFI_VARSTORE_ID VarStoreId
,
3744 IN UINT16 VarOffset
,
3745 IN EFI_STRING_ID Prompt
,
3746 IN EFI_STRING_ID Help
,
3747 IN UINT8 QuestionFlags
,
3748 IN UINT8 NumericFlags
,
3752 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3755 EFI_IFR_NUMERIC OpCode
;
3759 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_REST_STYLE
))) == 0);
3762 ZeroMem (&OpCode
, sizeof (OpCode
));
3763 OpCode
.Question
.QuestionId
= QuestionId
;
3764 OpCode
.Question
.VarStoreId
= VarStoreId
;
3765 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3766 OpCode
.Question
.Header
.Prompt
= Prompt
;
3767 OpCode
.Question
.Header
.Help
= Help
;
3768 OpCode
.Question
.Flags
= QuestionFlags
;
3769 OpCode
.Flags
= NumericFlags
;
3771 switch (NumericFlags
& EFI_IFR_NUMERIC_SIZE
) {
3772 case EFI_IFR_NUMERIC_SIZE_1
:
3773 OpCode
.data
.u8
.MinValue
= (UINT8
)Minimum
;
3774 OpCode
.data
.u8
.MaxValue
= (UINT8
)Maximum
;
3775 OpCode
.data
.u8
.Step
= (UINT8
)Step
;
3779 case EFI_IFR_NUMERIC_SIZE_2
:
3780 OpCode
.data
.u16
.MinValue
= (UINT16
)Minimum
;
3781 OpCode
.data
.u16
.MaxValue
= (UINT16
)Maximum
;
3782 OpCode
.data
.u16
.Step
= (UINT16
)Step
;
3786 case EFI_IFR_NUMERIC_SIZE_4
:
3787 OpCode
.data
.u32
.MinValue
= (UINT32
)Minimum
;
3788 OpCode
.data
.u32
.MaxValue
= (UINT32
)Maximum
;
3789 OpCode
.data
.u32
.Step
= (UINT32
)Step
;
3793 case EFI_IFR_NUMERIC_SIZE_8
:
3794 OpCode
.data
.u64
.MinValue
= Minimum
;
3795 OpCode
.data
.u64
.MaxValue
= Maximum
;
3796 OpCode
.data
.u64
.Step
= Step
;
3801 Length
+= OFFSET_OF (EFI_IFR_NUMERIC
, data
);
3803 if (DefaultsOpCodeHandle
== NULL
) {
3804 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
);
3807 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3808 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
, 0, 1);
3809 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3810 HiiCreateEndOpCode (OpCodeHandle
);
3811 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3815 Create EFI_IFR_STRING_OP opcode.
3817 If OpCodeHandle is NULL, then ASSERT().
3818 If any reserved bits are set in QuestionFlags, then ASSERT().
3819 If any reserved bits are set in StringFlags, then ASSERT().
3821 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3822 @param[in] QuestionId Question ID
3823 @param[in] VarStoreId Storage ID
3824 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3825 for this name/value pair.
3826 @param[in] Prompt String ID for Prompt
3827 @param[in] Help String ID for Help
3828 @param[in] QuestionFlags Flags in Question Header
3829 @param[in] StringFlags Flags for string opcode
3830 @param[in] MinSize String minimum length
3831 @param[in] MaxSize String maximum length
3832 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3833 is an optional parameter that may be NULL.
3835 @retval NULL There is not enough space left in Buffer to add the opcode.
3836 @retval Other A pointer to the created opcode.
3841 HiiCreateStringOpCode (
3842 IN VOID
*OpCodeHandle
,
3843 IN EFI_QUESTION_ID QuestionId
,
3844 IN EFI_VARSTORE_ID VarStoreId
,
3845 IN UINT16 VarOffset
,
3846 IN EFI_STRING_ID Prompt
,
3847 IN EFI_STRING_ID Help
,
3848 IN UINT8 QuestionFlags
,
3849 IN UINT8 StringFlags
,
3852 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3855 EFI_IFR_STRING OpCode
;
3858 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_REST_STYLE
))) == 0);
3860 ZeroMem (&OpCode
, sizeof (OpCode
));
3861 OpCode
.Question
.Header
.Prompt
= Prompt
;
3862 OpCode
.Question
.Header
.Help
= Help
;
3863 OpCode
.Question
.QuestionId
= QuestionId
;
3864 OpCode
.Question
.VarStoreId
= VarStoreId
;
3865 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3866 OpCode
.Question
.Flags
= QuestionFlags
;
3867 OpCode
.MinSize
= MinSize
;
3868 OpCode
.MaxSize
= MaxSize
;
3869 OpCode
.Flags
= (UINT8
)(StringFlags
& EFI_IFR_STRING_MULTI_LINE
);
3871 if (DefaultsOpCodeHandle
== NULL
) {
3872 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
));
3875 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3876 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
), 0, 1);
3877 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3878 HiiCreateEndOpCode (OpCodeHandle
);
3879 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3883 Create EFI_IFR_ONE_OF_OP opcode.
3885 If OpCodeHandle is NULL, then ASSERT().
3886 If any reserved bits are set in QuestionFlags, then ASSERT().
3887 If any reserved bits are set in OneOfFlags, then ASSERT().
3889 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3890 @param[in] QuestionId Question ID
3891 @param[in] VarStoreId Storage ID
3892 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3893 for this name/value pair.
3894 @param[in] Prompt String ID for Prompt
3895 @param[in] Help String ID for Help
3896 @param[in] QuestionFlags Flags in Question Header
3897 @param[in] OneOfFlags Flags for oneof opcode
3898 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3899 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3900 is an optional parameter that may be NULL.
3902 @retval NULL There is not enough space left in Buffer to add the opcode.
3903 @retval Other A pointer to the created opcode.
3908 HiiCreateOneOfOpCode (
3909 IN VOID
*OpCodeHandle
,
3910 IN EFI_QUESTION_ID QuestionId
,
3911 IN EFI_VARSTORE_ID VarStoreId
,
3912 IN UINT16 VarOffset
,
3913 IN EFI_STRING_ID Prompt
,
3914 IN EFI_STRING_ID Help
,
3915 IN UINT8 QuestionFlags
,
3916 IN UINT8 OneOfFlags
,
3917 IN VOID
*OptionsOpCodeHandle
,
3918 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3921 EFI_IFR_ONE_OF OpCode
;
3925 ASSERT (OptionsOpCodeHandle
!= NULL
);
3926 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_REST_STYLE
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3928 ZeroMem (&OpCode
, sizeof (OpCode
));
3929 OpCode
.Question
.Header
.Prompt
= Prompt
;
3930 OpCode
.Question
.Header
.Help
= Help
;
3931 OpCode
.Question
.QuestionId
= QuestionId
;
3932 OpCode
.Question
.VarStoreId
= VarStoreId
;
3933 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3934 OpCode
.Question
.Flags
= QuestionFlags
;
3935 OpCode
.Flags
= OneOfFlags
;
3937 Length
= OFFSET_OF (EFI_IFR_ONE_OF
, data
);
3938 Length
+= (1 << (OneOfFlags
& EFI_IFR_NUMERIC_SIZE
)) * 3;
3940 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3941 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OP
, Length
, 0, 1);
3942 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3943 if (DefaultsOpCodeHandle
!= NULL
) {
3944 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3947 HiiCreateEndOpCode (OpCodeHandle
);
3948 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3952 Create EFI_IFR_ORDERED_LIST_OP opcode.
3954 If OpCodeHandle is NULL, then ASSERT().
3955 If any reserved bits are set in QuestionFlags, then ASSERT().
3956 If any reserved bits are set in OrderedListFlags, then ASSERT().
3958 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3959 @param[in] QuestionId Question ID
3960 @param[in] VarStoreId Storage ID
3961 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3962 for this name/value pair.
3963 @param[in] Prompt String ID for Prompt
3964 @param[in] Help String ID for Help
3965 @param[in] QuestionFlags Flags in Question Header
3966 @param[in] OrderedListFlags Flags for ordered list opcode
3967 @param[in] DataType Type for option value
3968 @param[in] MaxContainers Maximum count for options in this ordered list
3969 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3970 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3971 is an optional parameter that may be NULL.
3973 @retval NULL There is not enough space left in Buffer to add the opcode.
3974 @retval Other A pointer to the created opcode.
3979 HiiCreateOrderedListOpCode (
3980 IN VOID
*OpCodeHandle
,
3981 IN EFI_QUESTION_ID QuestionId
,
3982 IN EFI_VARSTORE_ID VarStoreId
,
3983 IN UINT16 VarOffset
,
3984 IN EFI_STRING_ID Prompt
,
3985 IN EFI_STRING_ID Help
,
3986 IN UINT8 QuestionFlags
,
3987 IN UINT8 OrderedListFlags
,
3989 IN UINT8 MaxContainers
,
3990 IN VOID
*OptionsOpCodeHandle
,
3991 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3994 EFI_IFR_ORDERED_LIST OpCode
;
3997 ASSERT (OptionsOpCodeHandle
!= NULL
);
3998 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_REST_STYLE
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
4000 ZeroMem (&OpCode
, sizeof (OpCode
));
4001 OpCode
.Question
.Header
.Prompt
= Prompt
;
4002 OpCode
.Question
.Header
.Help
= Help
;
4003 OpCode
.Question
.QuestionId
= QuestionId
;
4004 OpCode
.Question
.VarStoreId
= VarStoreId
;
4005 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
4006 OpCode
.Question
.Flags
= QuestionFlags
;
4007 OpCode
.MaxContainers
= MaxContainers
;
4008 OpCode
.Flags
= OrderedListFlags
;
4010 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
4011 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ORDERED_LIST_OP
, sizeof (OpCode
), 0, 1);
4012 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
4013 if (DefaultsOpCodeHandle
!= NULL
) {
4014 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
4017 HiiCreateEndOpCode (OpCodeHandle
);
4018 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
4022 Create EFI_IFR_TEXT_OP opcode.
4024 If OpCodeHandle is NULL, then ASSERT().
4026 @param[in] OpCodeHandle Handle to the buffer of opcodes.
4027 @param[in] Prompt String ID for Prompt.
4028 @param[in] Help String ID for Help.
4029 @param[in] TextTwo String ID for TextTwo.
4031 @retval NULL There is not enough space left in Buffer to add the opcode.
4032 @retval Other A pointer to the created opcode.
4037 HiiCreateTextOpCode (
4038 IN VOID
*OpCodeHandle
,
4039 IN EFI_STRING_ID Prompt
,
4040 IN EFI_STRING_ID Help
,
4041 IN EFI_STRING_ID TextTwo
4044 EFI_IFR_TEXT OpCode
;
4046 ZeroMem (&OpCode
, sizeof (OpCode
));
4047 OpCode
.Statement
.Prompt
= Prompt
;
4048 OpCode
.Statement
.Help
= Help
;
4049 OpCode
.TextTwo
= TextTwo
;
4051 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TEXT_OP
, sizeof (OpCode
));
4055 Create EFI_IFR_DATE_OP opcode.
4057 If OpCodeHandle is NULL, then ASSERT().
4058 If any reserved bits are set in QuestionFlags, then ASSERT().
4059 If any reserved bits are set in DateFlags, then ASSERT().
4061 @param[in] OpCodeHandle Handle to the buffer of opcodes.
4062 @param[in] QuestionId Question ID
4063 @param[in] VarStoreId Storage ID, optional. If DateFlags is not
4064 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
4065 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
4066 for this name/value pair, optional. If DateFlags is not
4067 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
4068 @param[in] Prompt String ID for Prompt
4069 @param[in] Help String ID for Help
4070 @param[in] QuestionFlags Flags in Question Header
4071 @param[in] DateFlags Flags for date opcode
4072 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
4073 is an optional parameter that may be NULL.
4075 @retval NULL There is not enough space left in Buffer to add the opcode.
4076 @retval Other A pointer to the created opcode.
4081 HiiCreateDateOpCode (
4082 IN VOID
*OpCodeHandle
,
4083 IN EFI_QUESTION_ID QuestionId
,
4084 IN EFI_VARSTORE_ID VarStoreId OPTIONAL
,
4085 IN UINT16 VarOffset OPTIONAL
,
4086 IN EFI_STRING_ID Prompt
,
4087 IN EFI_STRING_ID Help
,
4088 IN UINT8 QuestionFlags
,
4090 IN VOID
*DefaultsOpCodeHandle OPTIONAL
4093 EFI_IFR_DATE OpCode
;
4096 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_REST_STYLE
))) == 0);
4097 ASSERT ((DateFlags
& (~(EFI_QF_DATE_YEAR_SUPPRESS
| EFI_QF_DATE_MONTH_SUPPRESS
| EFI_QF_DATE_DAY_SUPPRESS
| EFI_QF_DATE_STORAGE
))) == 0);
4099 ZeroMem (&OpCode
, sizeof (OpCode
));
4100 OpCode
.Question
.Header
.Prompt
= Prompt
;
4101 OpCode
.Question
.Header
.Help
= Help
;
4102 OpCode
.Question
.QuestionId
= QuestionId
;
4103 OpCode
.Question
.VarStoreId
= VarStoreId
;
4104 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
4105 OpCode
.Question
.Flags
= QuestionFlags
;
4106 OpCode
.Flags
= DateFlags
;
4108 if (DefaultsOpCodeHandle
== NULL
) {
4109 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
));
4112 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
4113 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
), 0, 1);
4114 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
4115 HiiCreateEndOpCode (OpCodeHandle
);
4116 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
4120 Create EFI_IFR_TIME_OP opcode.
4122 If OpCodeHandle is NULL, then ASSERT().
4123 If any reserved bits are set in QuestionFlags, then ASSERT().
4124 If any reserved bits are set in TimeFlags, then ASSERT().
4126 @param[in] OpCodeHandle Handle to the buffer of opcodes.
4127 @param[in] QuestionId Question ID
4128 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not
4129 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
4130 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
4131 for this name/value pair, optional. If TimeFlags is not
4132 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
4133 @param[in] Prompt String ID for Prompt
4134 @param[in] Help String ID for Help
4135 @param[in] QuestionFlags Flags in Question Header
4136 @param[in] TimeFlags Flags for time opcode
4137 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
4138 is an optional parameter that may be NULL.
4140 @retval NULL There is not enough space left in Buffer to add the opcode.
4141 @retval Other A pointer to the created opcode.
4146 HiiCreateTimeOpCode (
4147 IN VOID
*OpCodeHandle
,
4148 IN EFI_QUESTION_ID QuestionId
,
4149 IN EFI_VARSTORE_ID VarStoreId OPTIONAL
,
4150 IN UINT16 VarOffset OPTIONAL
,
4151 IN EFI_STRING_ID Prompt
,
4152 IN EFI_STRING_ID Help
,
4153 IN UINT8 QuestionFlags
,
4155 IN VOID
*DefaultsOpCodeHandle OPTIONAL
4158 EFI_IFR_TIME OpCode
;
4161 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_REST_STYLE
))) == 0);
4162 ASSERT ((TimeFlags
& (~(QF_TIME_HOUR_SUPPRESS
| QF_TIME_MINUTE_SUPPRESS
| QF_TIME_SECOND_SUPPRESS
| QF_TIME_STORAGE
))) == 0);
4164 ZeroMem (&OpCode
, sizeof (OpCode
));
4165 OpCode
.Question
.Header
.Prompt
= Prompt
;
4166 OpCode
.Question
.Header
.Help
= Help
;
4167 OpCode
.Question
.QuestionId
= QuestionId
;
4168 OpCode
.Question
.VarStoreId
= VarStoreId
;
4169 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
4170 OpCode
.Question
.Flags
= QuestionFlags
;
4171 OpCode
.Flags
= TimeFlags
;
4173 if (DefaultsOpCodeHandle
== NULL
) {
4174 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
));
4177 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
4178 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
), 0, 1);
4179 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
4180 HiiCreateEndOpCode (OpCodeHandle
);
4181 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
4185 This is the internal worker function to update the data in
4186 a form specified by FormSetGuid, FormId and Label.
4188 @param[in] FormSetGuid The optional Formset GUID.
4189 @param[in] FormId The Form ID.
4190 @param[in] Package The package header.
4191 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR
4192 opcodes to be inserted or replaced in the form.
4193 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode
4194 that marks the end of a replace operation in the form.
4195 @param[out] TempPackage The resultant package.
4197 @retval EFI_SUCCESS The function completes successfully.
4198 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.
4203 InternalHiiUpdateFormPackageData (
4204 IN EFI_GUID
*FormSetGuid OPTIONAL
,
4205 IN EFI_FORM_ID FormId
,
4206 IN EFI_HII_PACKAGE_HEADER
*Package
,
4207 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
,
4208 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd OPTIONAL
,
4209 OUT EFI_HII_PACKAGE_HEADER
*TempPackage
4214 EFI_HII_PACKAGE_HEADER PackageHeader
;
4216 EFI_IFR_OP_HEADER
*IfrOpHdr
;
4217 EFI_IFR_OP_HEADER
*UpdateIfrOpHdr
;
4221 UINTN UpdatePackageLength
;
4223 CopyMem (TempPackage
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4224 UpdatePackageLength
= sizeof (EFI_HII_PACKAGE_HEADER
);
4225 BufferPos
= (UINT8
*)(TempPackage
+ 1);
4227 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4228 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*)Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
4229 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
4230 GetFormSet
= (BOOLEAN
)((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
4234 while (Offset
< PackageHeader
.Length
) {
4235 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
4236 BufferPos
+= IfrOpHdr
->Length
;
4237 UpdatePackageLength
+= IfrOpHdr
->Length
;
4240 // Find the matched FormSet and Form
4242 if ((IfrOpHdr
->OpCode
== EFI_IFR_FORM_SET_OP
) && (FormSetGuid
!= NULL
)) {
4243 if (CompareGuid ((GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*)IfrOpHdr
)->Guid
, FormSetGuid
)) {
4248 } else if ((IfrOpHdr
->OpCode
== EFI_IFR_FORM_OP
) || (IfrOpHdr
->OpCode
== EFI_IFR_FORM_MAP_OP
)) {
4249 if (CompareMem (&((EFI_IFR_FORM
*)IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
4257 // The matched Form is found, and Update data in this form
4259 if (GetFormSet
&& GetForm
) {
4260 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*)OpCodeBufferStart
->Buffer
;
4261 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
4262 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0))
4265 // Remove the original data when End OpCode buffer exist.
4267 if (OpCodeBufferEnd
!= NULL
) {
4268 Offset
+= IfrOpHdr
->Length
;
4269 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*)(IfrOpHdr
) + IfrOpHdr
->Length
);
4270 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*)OpCodeBufferEnd
->Buffer
;
4271 while (Offset
< PackageHeader
.Length
) {
4273 // Search the matched end opcode
4275 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
4276 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0))
4282 // Go to the next Op-Code
4284 Offset
+= IfrOpHdr
->Length
;
4285 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*)(IfrOpHdr
) + IfrOpHdr
->Length
);
4288 if (Offset
>= PackageHeader
.Length
) {
4290 // The end opcode is not found.
4292 return EFI_NOT_FOUND
;
4297 // Insert the updated data
4299 AddSize
= ((EFI_IFR_OP_HEADER
*)OpCodeBufferStart
->Buffer
)->Length
;
4300 CopyMem (BufferPos
, OpCodeBufferStart
->Buffer
+ AddSize
, OpCodeBufferStart
->Position
- AddSize
);
4301 BufferPos
+= OpCodeBufferStart
->Position
- AddSize
;
4302 UpdatePackageLength
+= OpCodeBufferStart
->Position
- AddSize
;
4304 if (OpCodeBufferEnd
!= NULL
) {
4306 // Add the end opcode
4308 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
4309 BufferPos
+= IfrOpHdr
->Length
;
4310 UpdatePackageLength
+= IfrOpHdr
->Length
;
4314 // Copy the left package data.
4316 Offset
+= IfrOpHdr
->Length
;
4317 CopyMem (BufferPos
, (UINT8
*)Package
+ Offset
, PackageHeader
.Length
- Offset
);
4318 UpdatePackageLength
+= PackageHeader
.Length
- Offset
;
4329 // Go to the next Op-Code
4331 Offset
+= IfrOpHdr
->Length
;
4332 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((CHAR8
*)(IfrOpHdr
) + IfrOpHdr
->Length
);
4337 // The updated opcode buffer is not found.
4339 return EFI_NOT_FOUND
;
4343 // Update the package length.
4345 PackageHeader
.Length
= (UINT32
)UpdatePackageLength
;
4346 CopyMem (TempPackage
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4352 This function updates a form that has previously been registered with the HII
4353 Database. This function will perform at most one update operation.
4355 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
4356 comparisons of IFR opcodes are performed from the beginning of the form being
4357 updated until an IFR opcode is found that exactly matches the first IFR opcode
4358 specified by StartOpCodeHandle. The following rules are used to determine if
4359 an insert, replace, or delete operation is performed.
4361 1) If no matches are found, then NULL is returned.
4362 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
4363 from StartOpCodeHandle except the first opcode are inserted immediately after
4364 the matching IFR opcode in the form to be updated.
4365 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
4366 from the matching IFR opcode until an IFR opcode exactly matches the first
4367 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
4368 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
4369 is found, then all of the IFR opcodes between the start match and the end
4370 match are deleted from the form being updated and all of the IFR opcodes
4371 from StartOpCodeHandle except the first opcode are inserted immediately after
4372 the matching start IFR opcode. If StartOpCcodeHandle only contains one
4373 IFR instruction, then the result of this operation will delete all of the IFR
4374 opcodes between the start end matches.
4376 If HiiHandle is NULL, then ASSERT().
4377 If StartOpCodeHandle is NULL, then ASSERT().
4379 @param[in] HiiHandle The HII Handle of the form to update.
4380 @param[in] FormSetGuid The Formset GUID of the form to update. This
4381 is an optional parameter that may be NULL.
4382 If it is NULL, all FormSet will be updated.
4383 @param[in] FormId The ID of the form to update.
4384 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
4385 opcodes to be inserted or replaced in the form.
4386 The first IFR instruction in StartOpCodeHandle
4387 is used to find matching IFR opcode in the
4389 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
4390 that marks the end of a replace operation in
4391 the form. This is an optional parameter that
4392 may be NULL. If it is NULL, then an the IFR
4393 opcodes specified by StartOpCodeHandle are
4394 inserted into the form.
4396 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
4397 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
4398 1) The form specified by HiiHandle, FormSetGuid,
4399 and FormId could not be found in the HII Database.
4400 2) No IFR opcodes in the target form match the first
4401 IFR opcode in StartOpCodeHandle.
4402 3) EndOpCOde is not NULL, and no IFR opcodes in the
4403 target form following a matching start opcode match
4404 the first IFR opcode in EndOpCodeHandle.
4405 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
4411 IN EFI_HII_HANDLE HiiHandle
,
4412 IN EFI_GUID
*FormSetGuid OPTIONAL
,
4413 IN EFI_FORM_ID FormId
,
4414 IN VOID
*StartOpCodeHandle
,
4415 IN VOID
*EndOpCodeHandle OPTIONAL
4419 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4420 UINT32 PackageListLength
;
4422 EFI_HII_PACKAGE_LIST_HEADER
*UpdatePackageList
;
4424 UINT8
*UpdateBufferPos
;
4425 EFI_HII_PACKAGE_HEADER
*Package
;
4426 EFI_HII_PACKAGE_HEADER
*TempPackage
;
4427 EFI_HII_PACKAGE_HEADER PackageHeader
;
4429 HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
;
4430 HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
;
4433 // Input update data can't be NULL.
4435 ASSERT (HiiHandle
!= NULL
);
4436 ASSERT (StartOpCodeHandle
!= NULL
);
4437 UpdatePackageList
= NULL
;
4439 HiiPackageList
= NULL
;
4442 // Retrieve buffer data from Opcode Handle
4444 OpCodeBufferStart
= (HII_LIB_OPCODE_BUFFER
*)StartOpCodeHandle
;
4445 OpCodeBufferEnd
= (HII_LIB_OPCODE_BUFFER
*)EndOpCodeHandle
;
4448 // Get the original package list
4451 HiiPackageList
= NULL
;
4452 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4454 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
4456 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4460 HiiPackageList
= AllocatePool (BufferSize
);
4461 if (HiiPackageList
== NULL
) {
4462 Status
= EFI_OUT_OF_RESOURCES
;
4466 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4467 if (EFI_ERROR (Status
)) {
4472 // Calculate and allocate space for retrieval of IFR data
4474 BufferSize
+= OpCodeBufferStart
->Position
;
4475 UpdatePackageList
= AllocateZeroPool (BufferSize
);
4476 if (UpdatePackageList
== NULL
) {
4477 Status
= EFI_OUT_OF_RESOURCES
;
4482 // Allocate temp buffer to store the temp updated package buffer
4484 TempPackage
= AllocateZeroPool (BufferSize
);
4485 if (TempPackage
== NULL
) {
4486 Status
= EFI_OUT_OF_RESOURCES
;
4490 UpdateBufferPos
= (UINT8
*)UpdatePackageList
;
4493 // Copy the package list header
4495 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
4496 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4499 // Go through each package to find the matched package and update one by one
4502 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4503 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
4504 while (Offset
< PackageListLength
) {
4505 Package
= (EFI_HII_PACKAGE_HEADER
*)(((UINT8
*)HiiPackageList
) + Offset
);
4506 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4507 Offset
+= Package
->Length
;
4509 if (Package
->Type
== EFI_HII_PACKAGE_FORMS
) {
4511 // Check this package is the matched package.
4513 Status
= InternalHiiUpdateFormPackageData (FormSetGuid
, FormId
, Package
, OpCodeBufferStart
, OpCodeBufferEnd
, TempPackage
);
4515 // The matched package is found. Its package buffer will be updated by the input new data.
4517 if (!EFI_ERROR (Status
)) {
4523 // Add updated package buffer
4525 Package
= TempPackage
;
4530 // Add pacakge buffer
4532 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4533 CopyMem (UpdateBufferPos
, Package
, PackageHeader
.Length
);
4534 UpdateBufferPos
+= PackageHeader
.Length
;
4539 // Update package list length
4541 BufferSize
= UpdateBufferPos
- (UINT8
*)UpdatePackageList
;
4542 WriteUnaligned32 (&UpdatePackageList
->PackageLength
, (UINT32
)BufferSize
);
4545 // Update Package to show form
4547 Status
= gHiiDatabase
->UpdatePackageList (gHiiDatabase
, HiiHandle
, UpdatePackageList
);
4550 // Not matched form is found and updated.
4552 Status
= EFI_NOT_FOUND
;
4556 if (HiiPackageList
!= NULL
) {
4557 FreePool (HiiPackageList
);
4560 if (UpdatePackageList
!= NULL
) {
4561 FreePool (UpdatePackageList
);
4564 if (TempPackage
!= NULL
) {
4565 FreePool (TempPackage
);