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
);
89 if (EFI_ERROR (Status
)) {
90 FreePool (HiiPackageList
);
97 CopyGuid (Guid
, &HiiPackageList
->PackageListGuid
);
99 FreePool (HiiPackageList
);
105 Registers a list of packages in the HII Database and returns the HII Handle
106 associated with that registration. If an HII Handle has already been registered
107 with the same PackageListGuid and DeviceHandle, then NULL is returned. If there
108 are not enough resources to perform the registration, then NULL is returned.
109 If an empty list of packages is passed in, then NULL is returned. If the size of
110 the list of package is 0, then NULL is returned.
112 The variable arguments are pointers which point to package header that defined
113 by UEFI VFR compiler and StringGather tool.
115 #pragma pack (push, 1)
118 EFI_HII_PACKAGE_HEADER PackageHeader;
119 } EDKII_AUTOGEN_PACKAGES_HEADER;
122 @param[in] PackageListGuid The GUID of the package list.
123 @param[in] DeviceHandle If not NULL, the Device Handle on which
124 an instance of DEVICE_PATH_PROTOCOL is installed.
125 This Device Handle uniquely defines the device that
126 the added packages are associated with.
127 @param[in] ... The variable argument list that contains pointers
128 to packages terminated by a NULL.
130 @retval NULL A HII Handle has already been registered in the HII Database with
131 the same PackageListGuid and DeviceHandle.
132 @retval NULL The HII Handle could not be created.
133 @retval NULL An empty list of packages was passed in.
134 @retval NULL All packages are empty.
135 @retval Other The HII Handle associated with the newly registered package list.
141 IN CONST EFI_GUID
*PackageListGuid
,
142 IN EFI_HANDLE DeviceHandle OPTIONAL
,
149 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
150 EFI_HII_HANDLE HiiHandle
;
154 ASSERT (PackageListGuid
!= NULL
);
157 // Calculate the length of all the packages in the variable argument list
159 for (Length
= 0, VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
160 Length
+= (ReadUnaligned32 (Package
) - sizeof (UINT32
));
165 // If there are no packages in the variable argument list or all the packages
166 // are empty, then return a NULL HII Handle
173 // Add the length of the Package List Header and the terminating Package Header
175 Length
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
) + sizeof (EFI_HII_PACKAGE_HEADER
);
178 // Allocate the storage for the entire Package List
180 PackageListHeader
= AllocateZeroPool (Length
);
183 // If the Package List can not be allocated, then return a NULL HII Handle
185 if (PackageListHeader
== NULL
) {
190 // Fill in the GUID and Length of the Package List Header
192 CopyGuid (&PackageListHeader
->PackageListGuid
, PackageListGuid
);
193 PackageListHeader
->PackageLength
= Length
;
196 // Initialize a pointer to the beginning if the Package List data
198 Data
= (UINT8
*)(PackageListHeader
+ 1);
201 // Copy the data from each package in the variable argument list
203 for (VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
204 Length
= ReadUnaligned32 (Package
) - sizeof (UINT32
);
205 CopyMem (Data
, Package
+ 1, Length
);
211 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list
213 CopyMem (Data
, &mEndOfPakageList
, sizeof (mEndOfPakageList
));
216 // Register the package list with the HII Database
218 Status
= gHiiDatabase
->NewPackageList (
224 if (EFI_ERROR (Status
)) {
229 // Free the allocated package list
231 FreePool (PackageListHeader
);
234 // Return the new HII Handle
240 Removes a package list from the HII database.
242 If HiiHandle is NULL, then ASSERT.
243 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.
245 @param[in] HiiHandle The handle that was previously registered in the HII database
251 IN EFI_HII_HANDLE HiiHandle
256 ASSERT (HiiHandle
!= NULL
);
257 Status
= gHiiDatabase
->RemovePackageList (gHiiDatabase
, HiiHandle
);
258 ASSERT_EFI_ERROR (Status
);
263 Retrieves the array of all the HII Handles or the HII handles of a specific
264 package list GUID in the HII Database.
265 This array is terminated with a NULL HII Handle.
266 This function allocates the returned array using AllocatePool().
267 The caller is responsible for freeing the array with FreePool().
269 @param[in] PackageListGuid An optional parameter that is used to request
270 HII Handles associated with a specific
271 Package List GUID. If this parameter is NULL,
272 then all the HII Handles in the HII Database
273 are returned. If this parameter is not NULL,
274 then zero or more HII Handles associated with
275 PackageListGuid are returned.
277 @retval NULL No HII handles were found in the HII database
278 @retval NULL The array of HII Handles could not be retrieved
279 @retval Other A pointer to the NULL terminated array of HII Handles
285 IN CONST EFI_GUID
*PackageListGuid OPTIONAL
289 UINTN HandleBufferLength
;
290 EFI_HII_HANDLE TempHiiHandleBuffer
;
291 EFI_HII_HANDLE
*HiiHandleBuffer
;
297 // Retrieve the size required for the buffer of all HII handles.
299 HandleBufferLength
= 0;
300 Status
= gHiiDatabase
->ListPackageLists (
302 EFI_HII_PACKAGE_TYPE_ALL
,
309 // If ListPackageLists() returns EFI_SUCCESS for a zero size,
310 // then there are no HII handles in the HII database. If ListPackageLists()
311 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII
312 // handles in the HII database.
314 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
316 // Return NULL if the size can not be retrieved, or if there are no HII
317 // handles in the HII Database
323 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator
325 HiiHandleBuffer
= AllocateZeroPool (HandleBufferLength
+ sizeof (EFI_HII_HANDLE
));
326 if (HiiHandleBuffer
== NULL
) {
328 // Return NULL if allocation fails.
334 // Retrieve the array of HII Handles in the HII Database
336 Status
= gHiiDatabase
->ListPackageLists (
338 EFI_HII_PACKAGE_TYPE_ALL
,
343 if (EFI_ERROR (Status
)) {
345 // Free the buffer and return NULL if the HII handles can not be retrieved.
347 FreePool (HiiHandleBuffer
);
351 if (PackageListGuid
== NULL
) {
353 // Return the NULL terminated array of HII handles in the HII Database
355 return HiiHandleBuffer
;
357 for (Index1
= 0, Index2
= 0; HiiHandleBuffer
[Index1
] != NULL
; Index1
++) {
358 Status
= InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer
[Index1
], &Guid
);
359 ASSERT_EFI_ERROR (Status
);
360 if (CompareGuid (&Guid
, PackageListGuid
)) {
361 HiiHandleBuffer
[Index2
++] = HiiHandleBuffer
[Index1
];
365 HiiHandleBuffer
[Index2
] = NULL
;
366 return HiiHandleBuffer
;
368 FreePool (HiiHandleBuffer
);
375 This function allows a caller to extract the form set opcode form the Hii Handle.
376 The returned buffer is allocated using AllocatePool().The caller is responsible
377 for freeing the allocated buffer using FreePool().
379 @param Handle The HII handle.
380 @param Buffer On return, points to a pointer which point to the buffer that contain the formset opcode.
381 @param BufferSize On return, points to the length of the buffer.
383 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
384 @retval EFI_NOT_FOUND Can't find the package data for the input Handle.
385 @retval EFI_INVALID_PARAMETER The input parameters are not correct.
386 @retval EFI_SUCCESS Get the formset opcode from the hii handle successfully.
391 HiiGetFormSetFromHiiHandle(
392 IN EFI_HII_HANDLE Handle
,
393 OUT EFI_IFR_FORM_SET
**Buffer
,
394 OUT UINTN
*BufferSize
398 UINTN PackageListSize
;
400 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
403 UINT8
*FormSetBuffer
;
407 UINT32 PackageListLength
;
408 EFI_HII_PACKAGE_HEADER PackageHeader
;
411 FormSetBuffer
= NULL
;
415 // Get HII PackageList
418 HiiPackageList
= NULL
;
419 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &PackageListSize
, HiiPackageList
);
420 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
424 HiiPackageList
= AllocatePool (PackageListSize
);
425 if (HiiPackageList
== NULL
) {
426 return EFI_OUT_OF_RESOURCES
;
429 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &PackageListSize
, HiiPackageList
);
430 ASSERT_EFI_ERROR (Status
);
433 // Get Form package from this HII package List
435 Status
= EFI_NOT_FOUND
;
436 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
437 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
439 while (Offset
< PackageListLength
) {
440 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
441 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
442 Offset
+= PackageHeader
.Length
;
444 if (PackageHeader
.Type
!= EFI_HII_PACKAGE_FORMS
) {
449 // Search FormSet Opcode in this Form Package
451 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
452 while (Offset2
< PackageHeader
.Length
) {
453 OpCodeData
= Package
+ Offset2
;
454 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
456 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
!= EFI_IFR_FORM_SET_OP
) {
460 if (FormSetBuffer
!= NULL
){
461 TempBuffer
= ReallocatePool (
463 TempSize
+ ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
,
466 if (TempBuffer
== NULL
) {
467 Status
= EFI_OUT_OF_RESOURCES
;
470 CopyMem (TempBuffer
+ TempSize
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
471 FormSetBuffer
= NULL
;
473 TempBuffer
= AllocatePool (TempSize
+ ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
474 if (TempBuffer
== NULL
) {
475 Status
= EFI_OUT_OF_RESOURCES
;
478 CopyMem (TempBuffer
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
480 TempSize
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
481 FormSetBuffer
= TempBuffer
;
483 Status
= EFI_SUCCESS
;
485 //One form package has one formset, exit current form package to search other form package in the packagelist.
491 FreePool (HiiPackageList
);
493 *BufferSize
= TempSize
;
494 *Buffer
= (EFI_IFR_FORM_SET
*)FormSetBuffer
;
500 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
501 hex digits that appear between a '=' and a '&' in a config string.
503 If ConfigString is NULL, then ASSERT().
505 @param[in] ConfigString Pointer to a Null-terminated Unicode string.
507 @return Pointer to the Null-terminated Unicode result string.
512 InternalHiiLowerConfigString (
513 IN EFI_STRING ConfigString
519 ASSERT (ConfigString
!= NULL
);
522 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
524 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
525 if (*String
== L
'=') {
527 } else if (*String
== L
'&') {
529 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
530 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
538 Uses the BlockToConfig() service of the Config Routing Protocol to
539 convert <ConfigRequest> and a buffer to a <ConfigResp>
541 If ConfigRequest is NULL, then ASSERT().
542 If Block is NULL, then ASSERT().
544 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.
545 @param[in] Block Pointer to a block of data.
546 @param[in] BlockSize The zie, in bytes, of Block.
548 @retval NULL The <ConfigResp> string could not be generated.
549 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.
554 InternalHiiBlockToConfig (
555 IN CONST EFI_STRING ConfigRequest
,
556 IN CONST UINT8
*Block
,
561 EFI_STRING ConfigResp
;
564 ASSERT (ConfigRequest
!= NULL
);
565 ASSERT (Block
!= NULL
);
568 // Convert <ConfigRequest> to <ConfigResp>
570 Status
= gHiiConfigRouting
->BlockToConfig (
578 if (EFI_ERROR (Status
)) {
585 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve
586 or set uncommitted data. If sata i being retrieved, then the buffer is
587 allocated using AllocatePool(). The caller is then responsible for freeing
588 the buffer using FreePool().
590 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
591 parameter that may be NULL.
592 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
593 is an optional parameter that may be NULL.
594 @param[in] SetResultsData If not NULL, then this parameter specified the buffer
595 of uncommited data to set. If this parameter is NULL,
596 then the caller is requesting to get the uncommited data
597 from the Form Browser.
599 @retval NULL The uncommitted data could not be retrieved.
600 @retval Other A pointer to a buffer containing the uncommitted data.
605 InternalHiiBrowserCallback (
606 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
607 IN CONST CHAR16
*VariableName
, OPTIONAL
608 IN CONST EFI_STRING SetResultsData OPTIONAL
612 UINTN ResultsDataSize
;
613 EFI_STRING ResultsData
;
614 CHAR16 TempResultsData
;
619 if (mUefiFormBrowser2
== NULL
) {
620 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mUefiFormBrowser2
);
621 if (EFI_ERROR (Status
) || mUefiFormBrowser2
== NULL
) {
628 if (SetResultsData
!= NULL
) {
630 // Request to to set data in the uncommitted browser state information
632 ResultsData
= SetResultsData
;
635 // Retrieve the length of the buffer required ResultsData from the Browser Callback
637 Status
= mUefiFormBrowser2
->BrowserCallback (
646 if (!EFI_ERROR (Status
)) {
648 // No Resluts Data, only allocate one char for '\0'
650 ResultsData
= AllocateZeroPool (sizeof (CHAR16
));
654 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
659 // Allocate the ResultsData buffer
661 ResultsData
= AllocateZeroPool (ResultsDataSize
);
662 if (ResultsData
== NULL
) {
668 // Retrieve or set the ResultsData from the Browser Callback
670 Status
= mUefiFormBrowser2
->BrowserCallback (
674 (BOOLEAN
)(SetResultsData
== NULL
),
678 if (EFI_ERROR (Status
)) {
686 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing
687 information that includes a GUID, an optional Unicode string name, and a device
688 path. The string returned is allocated with AllocatePool(). The caller is
689 responsible for freeing the allocated string with FreePool().
691 The format of a <ConfigHdr> is as follows:
693 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
695 @param[in] Guid Pointer to an EFI_GUID that is the routing information
696 GUID. Each of the 16 bytes in Guid is converted to
697 a 2 Unicode character hexadecimal string. This is
698 an optional parameter that may be NULL.
699 @param[in] Name Pointer to a Null-terminated Unicode string that is
700 the routing information NAME. This is an optional
701 parameter that may be NULL. Each 16-bit Unicode
702 character in Name is converted to a 4 character Unicode
704 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
705 that is the routing information PATH. Each byte of
706 the Device Path associated with DriverHandle is converted
707 to a 2 Unicode character hexadecimal string.
709 @retval NULL DriverHandle does not support the Device Path Protocol.
710 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
715 HiiConstructConfigHdr (
716 IN CONST EFI_GUID
*Guid
, OPTIONAL
717 IN CONST CHAR16
*Name
, OPTIONAL
718 IN EFI_HANDLE DriverHandle
722 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
723 UINTN DevicePathSize
;
725 CHAR16
*ReturnString
;
731 // Compute the length of Name in Unicode characters.
732 // If Name is NULL, then the length is 0.
736 NameLength
= StrLen (Name
);
742 // Retrieve DevicePath Protocol associated with DriverHandle
744 if (DriverHandle
!= NULL
) {
745 DevicePath
= DevicePathFromHandle (DriverHandle
);
746 if (DevicePath
== NULL
) {
750 // Compute the size of the device path in bytes
752 DevicePathSize
= GetDevicePathSize (DevicePath
);
756 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
757 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
759 MaxLen
= 5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1;
760 String
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
761 if (String
== NULL
) {
766 // Start with L"GUID="
768 StrCpyS (String
, MaxLen
, L
"GUID=");
769 ReturnString
= String
;
770 String
+= StrLen (String
);
774 // Append Guid converted to <HexCh>32
776 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
777 UnicodeValueToStringS (
779 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
780 PREFIX_ZERO
| RADIX_HEX
,
784 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
791 StrCatS (ReturnString
, MaxLen
, L
"&NAME=");
792 String
+= StrLen (String
);
796 // Append Name converted to <Char>NameLength
798 for (; *Name
!= L
'\0'; Name
++) {
799 UnicodeValueToStringS (
801 sizeof (CHAR16
) * MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
),
802 PREFIX_ZERO
| RADIX_HEX
,
806 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
813 StrCatS (ReturnString
, MaxLen
, L
"&PATH=");
814 String
+= StrLen (String
);
817 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
819 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
820 UnicodeValueToStringS (
822 sizeof (CHAR16
) * MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
),
823 PREFIX_ZERO
| RADIX_HEX
,
827 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
831 // Null terminate the Unicode string
836 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
838 return InternalHiiLowerConfigString (ReturnString
);
842 Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path
843 to binary buffer from <ConfigHdr>.
845 This is a internal function.
847 @param String UEFI configuration string.
848 @param Flag Flag specifies what type buffer will be retrieved.
849 @param Buffer Binary of Guid, Name or Device path.
851 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
852 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
853 @retval EFI_SUCCESS The buffer data is retrieved and translated to
858 InternalHiiGetBufferFromString (
859 IN EFI_STRING String
,
865 EFI_STRING ConfigHdr
;
872 if (String
== NULL
|| Buffer
== NULL
) {
873 return EFI_INVALID_PARAMETER
;
880 // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element
881 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.
883 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
886 case GUID_CONFIG_STRING_TYPE
:
887 case PATH_CONFIG_STRING_TYPE
:
889 // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order
890 // as the device path and Guid resides in RAM memory.
891 // Translate the data into binary.
893 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
894 if (DataBuffer
== NULL
) {
895 return EFI_OUT_OF_RESOURCES
;
898 // Convert binary byte one by one
900 ZeroMem (TemStr
, sizeof (TemStr
));
901 for (Index
= 0; Index
< Length
; Index
++) {
902 TemStr
[0] = ConfigHdr
[Index
];
903 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
904 if ((Index
& 1) == 0) {
905 DataBuffer
[Index
/2] = DigitUint8
;
907 DataBuffer
[Index
/2] = (UINT8
) ((DataBuffer
[Index
/2] << 4) + DigitUint8
);
911 *Buffer
= DataBuffer
;
914 case NAME_CONFIG_STRING_TYPE
:
916 // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"
920 // Add the tailling char L'\0'
922 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
/4 + 1) * sizeof (CHAR16
));
923 if (DataBuffer
== NULL
) {
924 return EFI_OUT_OF_RESOURCES
;
927 // Convert character one by one
929 StringPtr
= (CHAR16
*) DataBuffer
;
930 ZeroMem (TemStr
, sizeof (TemStr
));
931 for (Index
= 0; Index
< Length
; Index
+= 4) {
932 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), ConfigHdr
+ Index
, 4);
933 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
936 // Add tailing L'\0' character
938 StringPtr
[Index
/4] = L
'\0';
940 *Buffer
= DataBuffer
;
944 return EFI_INVALID_PARAMETER
;
951 This function checks VarOffset and VarWidth is in the block range.
953 @param BlockArray The block array is to be checked.
954 @param VarOffset Offset of var to the structure
955 @param VarWidth Width of var.
957 @retval TRUE This Var is in the block range.
958 @retval FALSE This Var is not in the block range.
962 IN IFR_BLOCK_DATA
*BlockArray
,
968 IFR_BLOCK_DATA
*BlockData
;
971 // No Request Block array, all vars are got.
973 if (BlockArray
== NULL
) {
978 // Check the input var is in the request block range.
980 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
981 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
982 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
991 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
993 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
995 @param ValueString String in <BlockConfig> format and points to the
996 first character of <Number>.
997 @param ValueData The output value. Caller takes the responsibility
999 @param ValueLength Length of the <Number>, in characters.
1001 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
1003 @retval EFI_SUCCESS Value of <Number> is outputted in Number
1009 InternalHiiGetValueOfNumber (
1010 IN EFI_STRING ValueString
,
1011 OUT UINT8
**ValueData
,
1012 OUT UINTN
*ValueLength
1015 EFI_STRING StringPtr
;
1022 ASSERT (ValueString
!= NULL
&& ValueData
!= NULL
&& ValueLength
!= NULL
);
1023 ASSERT (*ValueString
!= L
'\0');
1026 // Get the length of value string
1028 StringPtr
= ValueString
;
1029 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1032 Length
= StringPtr
- ValueString
;
1035 // Allocate buffer to store the value
1037 Buf
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
1039 return EFI_OUT_OF_RESOURCES
;
1043 // Convert character one by one to the value buffer
1045 ZeroMem (TemStr
, sizeof (TemStr
));
1046 for (Index
= 0; Index
< Length
; Index
++) {
1047 TemStr
[0] = ValueString
[Length
- Index
- 1];
1048 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1049 if ((Index
& 1) == 0) {
1050 Buf
[Index
/2] = DigitUint8
;
1052 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
1057 // Set the converted value and string length.
1060 *ValueLength
= Length
;
1065 Get value from config request resp string.
1067 @param ConfigElement ConfigResp string contains the current setting.
1068 @param VarName The variable name which need to get value.
1069 @param VarValue The return value.
1071 @retval EFI_SUCCESS Get the value for the VarName
1072 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1075 GetValueFromRequest (
1076 IN CHAR16
*ConfigElement
,
1078 OUT UINT64
*VarValue
1087 // Find VarName related string.
1089 StringPtr
= StrStr (ConfigElement
, VarName
);
1090 ASSERT (StringPtr
!= NULL
);
1093 // Skip the "VarName=" string
1095 StringPtr
+= StrLen (VarName
) + 1;
1100 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1101 if (EFI_ERROR (Status
)) {
1106 CopyMem (VarValue
, TmpBuffer
, (((Length
+ 1) / 2) < sizeof (UINT64
)) ? ((Length
+ 1) / 2) : sizeof (UINT64
));
1108 FreePool (TmpBuffer
);
1114 This internal function parses IFR data to validate current setting.
1116 Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;
1117 else the VarBuffer and CurrentBlockArray is valid.
1119 @param HiiPackageList Point to Hii package list.
1120 @param PackageListLength The length of the pacakge.
1121 @param VarGuid Guid of the buffer storage.
1122 @param VarName Name of the buffer storage.
1123 @param VarBuffer The data buffer for the storage.
1124 @param CurrentBlockArray The block array from the config Requst string.
1125 @param RequestElement The config string for this storage.
1126 @param HiiHandle The HiiHandle for this formset.
1127 @param NameValueType Whether current storage is name/value varstore or not.
1129 @retval EFI_SUCCESS The current setting is valid.
1130 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1131 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1134 ValidateQuestionFromVfr (
1135 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
1136 IN UINTN PackageListLength
,
1137 IN EFI_GUID
*VarGuid
,
1139 IN UINT8
*VarBuffer
,
1140 IN IFR_BLOCK_DATA
*CurrentBlockArray
,
1141 IN CHAR16
*RequestElement
,
1142 IN EFI_HII_HANDLE HiiHandle
,
1143 IN BOOLEAN NameValueType
1146 IFR_BLOCK_DATA VarBlockData
;
1150 EFI_IFR_TYPE_VALUE TmpValue
;
1152 EFI_HII_PACKAGE_HEADER PackageHeader
;
1153 UINT32 PackageOffset
;
1156 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1157 EFI_IFR_VARSTORE
*IfrVarStore
;
1158 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueStore
;
1159 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1160 IFR_VARSTORAGE_DATA VarStoreData
;
1161 EFI_IFR_ONE_OF
*IfrOneOf
;
1162 EFI_IFR_NUMERIC
*IfrNumeric
;
1163 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1164 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1165 EFI_IFR_STRING
*IfrString
;
1166 CHAR8
*VarStoreName
;
1168 CHAR16
*QuestionName
;
1175 BOOLEAN QuestionReferBitField
;
1179 // Initialize the local variables.
1182 VarStoreName
= NULL
;
1183 Status
= EFI_SUCCESS
;
1186 IfrNameValueStore
= NULL
;
1187 IfrEfiVarStore
= NULL
;
1188 ZeroMem (&VarStoreData
, sizeof (IFR_VARSTORAGE_DATA
));
1189 ZeroMem (&VarBlockData
, sizeof (VarBlockData
));
1192 QuestionReferBitField
= FALSE
;
1195 // Check IFR value is in block data, then Validate Value
1197 PackageOffset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1198 while (PackageOffset
< PackageListLength
) {
1199 CopyMem (&PackageHeader
, (UINT8
*) HiiPackageList
+ PackageOffset
, sizeof (PackageHeader
));
1202 // Parse IFR opcode from the form package.
1204 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1205 IfrOffset
= sizeof (PackageHeader
);
1206 PackageData
= (UINT8
*) HiiPackageList
+ PackageOffset
;
1207 while (IfrOffset
< PackageHeader
.Length
) {
1208 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (PackageData
+ IfrOffset
);
1210 // Validate current setting to the value built in IFR opcode
1212 switch (IfrOpHdr
->OpCode
) {
1213 case EFI_IFR_VARSTORE_OP
:
1215 // VarStoreId has been found. No further found.
1217 if (VarStoreData
.VarStoreId
!= 0) {
1221 // Find the matched VarStoreId to the input VarGuid and VarName
1223 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1224 if (CompareGuid ((EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
, VarGuid
)) {
1225 VarStoreName
= (CHAR8
*) IfrVarStore
->Name
;
1226 for (Index
= 0; VarStoreName
[Index
] != 0; Index
++) {
1227 if ((CHAR16
) VarStoreName
[Index
] != VarName
[Index
]) {
1232 // The matched VarStore is found.
1234 if ((VarStoreName
[Index
] != 0) || (VarName
[Index
] != 0)) {
1241 if (IfrVarStore
!= NULL
) {
1242 VarStoreData
.VarStoreId
= IfrVarStore
->VarStoreId
;
1243 VarStoreData
.Size
= IfrVarStore
->Size
;
1246 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1248 // VarStoreId has been found. No further found.
1250 if (VarStoreData
.VarStoreId
!= 0) {
1254 // Find the matched VarStoreId to the input VarGuid
1256 IfrNameValueStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1257 if (!CompareGuid ((EFI_GUID
*) (VOID
*) &IfrNameValueStore
->Guid
, VarGuid
)) {
1258 IfrNameValueStore
= NULL
;
1261 if (IfrNameValueStore
!= NULL
) {
1262 VarStoreData
.VarStoreId
= IfrNameValueStore
->VarStoreId
;
1265 case EFI_IFR_VARSTORE_EFI_OP
:
1267 // VarStore is found. Don't need to search any more.
1269 if (VarStoreData
.VarStoreId
!= 0) {
1273 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1276 // If the length is small than the structure, this is from old efi
1277 // varstore definition. Old efi varstore get config directly from
1278 // GetVariable function.
1280 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1284 if (CompareGuid ((EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
, VarGuid
)) {
1285 VarStoreName
= (CHAR8
*) IfrEfiVarStore
->Name
;
1286 for (Index
= 0; VarStoreName
[Index
] != 0; Index
++) {
1287 if ((CHAR16
) VarStoreName
[Index
] != VarName
[Index
]) {
1292 // The matched VarStore is found.
1294 if ((VarStoreName
[Index
] != 0) || (VarName
[Index
] != 0)) {
1295 IfrEfiVarStore
= NULL
;
1298 IfrEfiVarStore
= NULL
;
1301 if (IfrEfiVarStore
!= NULL
) {
1303 // Find the matched VarStore
1305 VarStoreData
.VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1306 VarStoreData
.Size
= IfrEfiVarStore
->Size
;
1309 case EFI_IFR_FORM_OP
:
1310 case EFI_IFR_FORM_MAP_OP
:
1312 // Check the matched VarStoreId is found.
1314 if (VarStoreData
.VarStoreId
== 0) {
1318 case EFI_IFR_ONE_OF_OP
:
1320 // Check whether current value is the one of option.
1324 // OneOf question is not in IFR Form. This IFR form is not valid.
1326 if (VarStoreData
.VarStoreId
== 0) {
1327 return EFI_INVALID_PARAMETER
;
1330 // Check whether this question is for the requested varstore.
1332 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1333 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1337 if (NameValueType
) {
1338 QuestionName
= HiiGetString (HiiHandle
, IfrOneOf
->Question
.VarStoreInfo
.VarName
, NULL
);
1339 ASSERT (QuestionName
!= NULL
);
1341 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1343 // This question is not in the current configuration string. Skip it.
1348 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1349 if (EFI_ERROR (Status
)) {
1354 // Get Offset by Question header and Width by DataType Flags
1356 if (QuestionReferBitField
) {
1358 // Get the byte offset/width for bit field.
1360 BitOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1361 BitWidth
= IfrOneOf
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
1362 Offset
= BitOffset
/ 8;
1363 TotalBits
= BitOffset
% 8 + BitWidth
;
1364 Width
= (TotalBits
% 8 == 0 ? TotalBits
/ 8: TotalBits
/ 8 + 1);
1366 Offset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1367 Width
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1370 // Check whether this question is in current block array.
1372 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1374 // This question is not in the current configuration string. Skip it.
1379 // Check this var question is in the var storage
1381 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1383 // This question exceeds the var store size.
1385 return EFI_INVALID_PARAMETER
;
1389 // Get the current value for oneof opcode
1392 if (QuestionReferBitField
) {
1394 // Get the value in bit fields.
1396 StartBit
= BitOffset
% 8;
1397 EndBit
= StartBit
+ BitWidth
- 1;
1398 CopyMem ((UINT8
*) &BufferValue
, VarBuffer
+ Offset
, Width
);
1399 VarValue
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1401 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1405 // Set Block Data, to be checked in the following Oneof option opcode.
1407 VarBlockData
.OpCode
= IfrOpHdr
->OpCode
;
1408 VarBlockData
.Scope
= IfrOpHdr
->Scope
;
1410 case EFI_IFR_NUMERIC_OP
:
1412 // Check the current value is in the numeric range.
1416 // Numeric question is not in IFR Form. This IFR form is not valid.
1418 if (VarStoreData
.VarStoreId
== 0) {
1419 return EFI_INVALID_PARAMETER
;
1422 // Check whether this question is for the requested varstore.
1424 IfrNumeric
= (EFI_IFR_NUMERIC
*) IfrOpHdr
;
1425 if (IfrNumeric
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1429 if (NameValueType
) {
1430 QuestionName
= HiiGetString (HiiHandle
, IfrNumeric
->Question
.VarStoreInfo
.VarName
, NULL
);
1431 ASSERT (QuestionName
!= NULL
);
1433 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1435 // This question is not in the current configuration string. Skip it.
1440 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1441 if (EFI_ERROR (Status
)) {
1446 // Get Offset by Question header and Width by DataType Flags
1448 if (QuestionReferBitField
) {
1450 // Get the byte offset/width for bit field.
1452 BitOffset
= IfrNumeric
->Question
.VarStoreInfo
.VarOffset
;
1453 BitWidth
= IfrNumeric
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
1454 Offset
= BitOffset
/ 8;
1455 TotalBits
= BitOffset
% 8 + BitWidth
;
1456 Width
= (TotalBits
% 8 == 0 ? TotalBits
/ 8: TotalBits
/ 8 + 1);
1458 Offset
= IfrNumeric
->Question
.VarStoreInfo
.VarOffset
;
1459 Width
= (UINT16
) (1 << (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1462 // Check whether this question is in current block array.
1464 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1466 // This question is not in the current configuration string. Skip it.
1471 // Check this var question is in the var storage
1473 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1475 // This question exceeds the var store size.
1477 return EFI_INVALID_PARAMETER
;
1481 // Check the current value is in the numeric range.
1484 if (QuestionReferBitField
) {
1486 // Get the value in the bit fields.
1488 StartBit
= BitOffset
% 8;
1489 EndBit
= StartBit
+ BitWidth
- 1;
1490 CopyMem ((UINT8
*) &BufferValue
, VarBuffer
+ Offset
, Width
);
1491 VarValue
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1493 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1496 if ( QuestionReferBitField
) {
1498 // Value in bit fields was stored as UINt32 type.
1500 if ((IfrNumeric
->Flags
& EDKII_IFR_DISPLAY_BIT
) == 0) {
1501 if ((INT32
) VarValue
< (INT32
) IfrNumeric
->data
.u32
.MinValue
|| (INT32
) VarValue
> (INT32
) IfrNumeric
->data
.u32
.MaxValue
) {
1503 // Not in the valid range.
1505 return EFI_INVALID_PARAMETER
;
1508 if (VarValue
< IfrNumeric
->data
.u32
.MinValue
|| VarValue
> IfrNumeric
->data
.u32
.MaxValue
) {
1510 // Not in the valid range.
1512 return EFI_INVALID_PARAMETER
;
1516 if ((IfrNumeric
->Flags
& EFI_IFR_DISPLAY
) == 0) {
1517 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1518 case EFI_IFR_NUMERIC_SIZE_1
:
1519 if ((INT8
) VarValue
< (INT8
) IfrNumeric
->data
.u8
.MinValue
|| (INT8
) VarValue
> (INT8
) IfrNumeric
->data
.u8
.MaxValue
) {
1521 // Not in the valid range.
1523 return EFI_INVALID_PARAMETER
;
1526 case EFI_IFR_NUMERIC_SIZE_2
:
1527 if ((INT16
) VarValue
< (INT16
) IfrNumeric
->data
.u16
.MinValue
|| (INT16
) VarValue
> (INT16
) IfrNumeric
->data
.u16
.MaxValue
) {
1529 // Not in the valid range.
1531 return EFI_INVALID_PARAMETER
;
1534 case EFI_IFR_NUMERIC_SIZE_4
:
1535 if ((INT32
) VarValue
< (INT32
) IfrNumeric
->data
.u32
.MinValue
|| (INT32
) VarValue
> (INT32
) IfrNumeric
->data
.u32
.MaxValue
) {
1537 // Not in the valid range.
1539 return EFI_INVALID_PARAMETER
;
1542 case EFI_IFR_NUMERIC_SIZE_8
:
1543 if ((INT64
) VarValue
< (INT64
) IfrNumeric
->data
.u64
.MinValue
|| (INT64
) VarValue
> (INT64
) IfrNumeric
->data
.u64
.MaxValue
) {
1545 // Not in the valid range.
1547 return EFI_INVALID_PARAMETER
;
1552 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1553 case EFI_IFR_NUMERIC_SIZE_1
:
1554 if ((UINT8
) VarValue
< IfrNumeric
->data
.u8
.MinValue
|| (UINT8
) VarValue
> IfrNumeric
->data
.u8
.MaxValue
) {
1556 // Not in the valid range.
1558 return EFI_INVALID_PARAMETER
;
1561 case EFI_IFR_NUMERIC_SIZE_2
:
1562 if ((UINT16
) VarValue
< IfrNumeric
->data
.u16
.MinValue
|| (UINT16
) VarValue
> IfrNumeric
->data
.u16
.MaxValue
) {
1564 // Not in the valid range.
1566 return EFI_INVALID_PARAMETER
;
1569 case EFI_IFR_NUMERIC_SIZE_4
:
1570 if ((UINT32
) VarValue
< IfrNumeric
->data
.u32
.MinValue
|| (UINT32
) VarValue
> IfrNumeric
->data
.u32
.MaxValue
) {
1572 // Not in the valid range.
1574 return EFI_INVALID_PARAMETER
;
1577 case EFI_IFR_NUMERIC_SIZE_8
:
1578 if ((UINT64
) VarValue
< IfrNumeric
->data
.u64
.MinValue
|| (UINT64
) VarValue
> IfrNumeric
->data
.u64
.MaxValue
) {
1580 // Not in the valid range.
1582 return EFI_INVALID_PARAMETER
;
1589 case EFI_IFR_CHECKBOX_OP
:
1591 // Check value is BOOLEAN type, only 0 and 1 is valid.
1595 // CheckBox question is not in IFR Form. This IFR form is not valid.
1597 if (VarStoreData
.VarStoreId
== 0) {
1598 return EFI_INVALID_PARAMETER
;
1602 // Check whether this question is for the requested varstore.
1604 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1605 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1609 if (NameValueType
) {
1610 QuestionName
= HiiGetString (HiiHandle
, IfrCheckBox
->Question
.VarStoreInfo
.VarName
, NULL
);
1611 ASSERT (QuestionName
!= NULL
);
1613 if (StrStr (RequestElement
, QuestionName
) == NULL
) {
1615 // This question is not in the current configuration string. Skip it.
1620 Status
= GetValueFromRequest (RequestElement
, QuestionName
, &VarValue
);
1621 if (EFI_ERROR (Status
)) {
1626 // Get Offset by Question header
1628 if (QuestionReferBitField
) {
1630 // Get the byte offset/width for bit field.
1632 BitOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1634 Offset
= BitOffset
/ 8;
1635 TotalBits
= BitOffset
% 8 + BitWidth
;
1636 Width
= (TotalBits
% 8 == 0 ? TotalBits
/ 8: TotalBits
/ 8 + 1);
1638 Offset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1639 Width
= (UINT16
) sizeof (BOOLEAN
);
1642 // Check whether this question is in current block array.
1644 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1646 // This question is not in the current configuration string. Skip it.
1651 // Check this var question is in the var storage
1653 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1655 // This question exceeds the var store size.
1657 return EFI_INVALID_PARAMETER
;
1660 // Check the current value is in the numeric range.
1663 if (QuestionReferBitField
) {
1665 // Get the value in bit fields.
1667 StartBit
= BitOffset
% 8;
1668 EndBit
= StartBit
+ BitWidth
- 1;
1669 CopyMem ((UINT8
*) &BufferValue
, VarBuffer
+ Offset
, Width
);
1670 VarValue
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1672 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1676 // Boolean type, only 1 and 0 is valid.
1679 return EFI_INVALID_PARAMETER
;
1682 case EFI_IFR_STRING_OP
:
1684 // Check current string length is less than maxsize
1688 // CheckBox question is not in IFR Form. This IFR form is not valid.
1690 if (VarStoreData
.VarStoreId
== 0) {
1691 return EFI_INVALID_PARAMETER
;
1695 // Check whether this question is for the requested varstore.
1697 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1698 if (IfrString
->Question
.VarStoreId
!= VarStoreData
.VarStoreId
) {
1702 // Get the Max size of the string.
1704 Width
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1705 if (NameValueType
) {
1706 QuestionName
= HiiGetString (HiiHandle
, IfrString
->Question
.VarStoreInfo
.VarName
, NULL
);
1707 ASSERT (QuestionName
!= NULL
);
1709 StringPtr
= StrStr (RequestElement
, QuestionName
);
1710 if (StringPtr
== NULL
) {
1712 // This question is not in the current configuration string. Skip it.
1717 // Skip the VarName.
1719 StringPtr
+= StrLen (QuestionName
);
1727 // Check current string length is less than maxsize
1728 // e.g Config String: "0041004200430044", Unicode String: "ABCD". Unicode String length = Config String length / 4.
1729 // Config string format in UEFI spec.
1730 // <NvConfig> ::= <Label>'='<String>
1731 // <String> ::= [<Char>]+
1732 // <Char> ::= <HexCh>4
1734 if (StrLen (StringPtr
) / 4 > IfrString
->MaxSize
) {
1735 return EFI_INVALID_PARAMETER
;
1739 // Get Offset/Width by Question header and OneOf Flags
1741 Offset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1743 // Check whether this question is in current block array.
1745 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1747 // This question is not in the current configuration string. Skip it.
1752 // Check this var question is in the var storage
1754 if ((Offset
+ Width
) > VarStoreData
.Size
) {
1756 // This question exceeds the var store size.
1758 return EFI_INVALID_PARAMETER
;
1762 // Check current string length is less than maxsize
1764 if (StrLen ((CHAR16
*) (VarBuffer
+ Offset
)) > IfrString
->MaxSize
) {
1765 return EFI_INVALID_PARAMETER
;
1769 case EFI_IFR_ONE_OF_OPTION_OP
:
1771 // Opcode Scope is zero. This one of option is not to be checked.
1773 if (VarBlockData
.Scope
== 0) {
1778 // Only check for OneOf and OrderList opcode
1780 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1781 if (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
) {
1783 // Check current value is the value of one of option.
1785 ASSERT (IfrOneOfOption
->Type
<= EFI_IFR_TYPE_NUM_SIZE_64
);
1786 ZeroMem (&TmpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
1787 CopyMem (&TmpValue
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
1788 if (VarValue
== TmpValue
.u64
) {
1790 // The value is one of option value.
1791 // Set OpCode to Zero, don't need check again.
1793 VarBlockData
.OpCode
= 0;
1797 case EFI_IFR_END_OP
:
1798 QuestionReferBitField
= FALSE
;
1800 // Decrease opcode scope for the validated opcode
1802 if (VarBlockData
.Scope
> 0) {
1803 VarBlockData
.Scope
--;
1807 // OneOf value doesn't belong to one of option value.
1809 if ((VarBlockData
.Scope
== 0) && (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
)) {
1810 return EFI_INVALID_PARAMETER
;
1813 case EFI_IFR_GUID_OP
:
1814 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
1815 QuestionReferBitField
= TRUE
;
1820 // Increase Scope for the validated opcode
1822 if (VarBlockData
.Scope
> 0) {
1823 VarBlockData
.Scope
= (UINT8
) (VarBlockData
.Scope
+ IfrOpHdr
->Scope
);
1828 // Go to the next opcode
1830 IfrOffset
+= IfrOpHdr
->Length
;
1833 // Only one form is in a package list.
1839 // Go to next package.
1841 PackageOffset
+= PackageHeader
.Length
;
1848 This internal function parses IFR data to validate current setting.
1850 @param ConfigElement ConfigResp element string contains the current setting.
1851 @param CurrentBlockArray Current block array.
1852 @param VarBuffer Data buffer for this varstore.
1854 @retval EFI_SUCCESS The current setting is valid.
1855 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
1856 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
1860 IN CHAR16
*ConfigElement
,
1861 OUT IFR_BLOCK_DATA
**CurrentBlockArray
,
1862 OUT UINT8
**VarBuffer
1865 IFR_BLOCK_DATA
*BlockData
;
1866 IFR_BLOCK_DATA
*NewBlockData
;
1867 EFI_STRING StringPtr
;
1873 UINTN MaxBufferSize
;
1875 IFR_BLOCK_DATA
*BlockArray
;
1879 // Initialize the local variables.
1881 Status
= EFI_SUCCESS
;
1883 NewBlockData
= NULL
;
1886 MaxBufferSize
= HII_LIB_DEFAULT_VARSTORE_SIZE
;
1887 DataBuffer
= AllocateZeroPool (MaxBufferSize
);
1888 if (DataBuffer
== NULL
) {
1889 return EFI_OUT_OF_RESOURCES
;
1895 BlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1896 if (BlockArray
== NULL
) {
1897 Status
= EFI_OUT_OF_RESOURCES
;
1900 InitializeListHead (&BlockArray
->Entry
);
1902 StringPtr
= StrStr (ConfigElement
, L
"&OFFSET=");
1903 ASSERT (StringPtr
!= NULL
);
1906 // Parse each <RequestElement> if exists
1907 // Only <BlockName> format is supported by this help function.
1908 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1910 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1912 // Skip the &OFFSET= string
1914 StringPtr
+= StrLen (L
"&OFFSET=");
1919 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1920 if (EFI_ERROR (Status
)) {
1927 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1929 FreePool (TmpBuffer
);
1932 StringPtr
+= Length
;
1933 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1934 Status
= EFI_INVALID_PARAMETER
;
1937 StringPtr
+= StrLen (L
"&WIDTH=");
1942 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1943 if (EFI_ERROR (Status
)) {
1950 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1952 FreePool (TmpBuffer
);
1955 StringPtr
+= Length
;
1956 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1957 Status
= EFI_INVALID_PARAMETER
;
1961 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1962 Status
= EFI_INVALID_PARAMETER
;
1965 StringPtr
+= StrLen (L
"&VALUE=");
1970 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1971 if (EFI_ERROR (Status
)) {
1975 StringPtr
+= Length
;
1976 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1977 Status
= EFI_INVALID_PARAMETER
;
1982 // Check whether VarBuffer is enough
1984 if ((UINT32
)Offset
+ Width
> MaxBufferSize
) {
1985 DataBuffer
= ReallocatePool (
1987 Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
,
1990 if (DataBuffer
== NULL
) {
1991 Status
= EFI_OUT_OF_RESOURCES
;
1994 MaxBufferSize
= Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
;
1998 // Update the Block with configuration info
2000 CopyMem (DataBuffer
+ Offset
, TmpBuffer
, Width
);
2001 FreePool (TmpBuffer
);
2005 // Set new Block Data
2007 NewBlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2008 if (NewBlockData
== NULL
) {
2009 Status
= EFI_OUT_OF_RESOURCES
;
2012 NewBlockData
->Offset
= Offset
;
2013 NewBlockData
->Width
= Width
;
2016 // Insert the new block data into the block data array.
2018 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
2019 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2020 if (NewBlockData
->Offset
== BlockData
->Offset
) {
2021 if (NewBlockData
->Width
> BlockData
->Width
) {
2022 BlockData
->Width
= NewBlockData
->Width
;
2024 FreePool (NewBlockData
);
2026 } else if (NewBlockData
->Offset
< BlockData
->Offset
) {
2028 // Insert new block data as the previous one of this link.
2030 InsertTailList (Link
, &NewBlockData
->Entry
);
2036 // Insert new block data into the array tail.
2038 if (Link
== &BlockArray
->Entry
) {
2039 InsertTailList (Link
, &NewBlockData
->Entry
);
2043 // If '\0', parsing is finished.
2045 if (*StringPtr
== 0) {
2049 // Go to next ConfigBlock
2054 // Merge the aligned block data into the single block data.
2056 Link
= BlockArray
->Entry
.ForwardLink
;
2057 while ((Link
!= &BlockArray
->Entry
) && (Link
->ForwardLink
!= &BlockArray
->Entry
)) {
2058 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2059 NewBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2060 if ((NewBlockData
->Offset
>= BlockData
->Offset
) && (NewBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2061 if ((NewBlockData
->Offset
+ NewBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2062 BlockData
->Width
= (UINT16
) (NewBlockData
->Offset
+ NewBlockData
->Width
- BlockData
->Offset
);
2064 RemoveEntryList (Link
->ForwardLink
);
2065 FreePool (NewBlockData
);
2068 Link
= Link
->ForwardLink
;
2071 *VarBuffer
= DataBuffer
;
2072 *CurrentBlockArray
= BlockArray
;
2076 if (DataBuffer
!= NULL
) {
2077 FreePool (DataBuffer
);
2080 if (BlockArray
!= NULL
) {
2082 // Free Link Array CurrentBlockArray
2084 while (!IsListEmpty (&BlockArray
->Entry
)) {
2085 BlockData
= BASE_CR (BlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2086 RemoveEntryList (&BlockData
->Entry
);
2087 FreePool (BlockData
);
2089 FreePool (BlockArray
);
2096 This internal function parses IFR data to validate current setting.
2098 @param ConfigResp ConfigResp string contains the current setting.
2099 @param HiiPackageList Point to Hii package list.
2100 @param PackageListLength The length of the pacakge.
2101 @param VarGuid Guid of the buffer storage.
2102 @param VarName Name of the buffer storage.
2103 @param HiiHandle The HiiHandle for this package.
2105 @retval EFI_SUCCESS The current setting is valid.
2106 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
2107 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
2111 InternalHiiValidateCurrentSetting (
2112 IN EFI_STRING ConfigResp
,
2113 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
2114 IN UINTN PackageListLength
,
2115 IN EFI_GUID
*VarGuid
,
2117 IN EFI_HII_HANDLE HiiHandle
2122 IFR_BLOCK_DATA
*CurrentBlockArray
;
2123 IFR_BLOCK_DATA
*BlockData
;
2125 BOOLEAN NameValueType
;
2127 CurrentBlockArray
= NULL
;
2130 Status
= EFI_SUCCESS
;
2133 // If StringPtr != NULL, get the request elements.
2135 if (StrStr (ConfigResp
, L
"&OFFSET=") != NULL
) {
2136 Status
= GetBlockDataInfo(ConfigResp
, &CurrentBlockArray
, &VarBuffer
);
2137 if (EFI_ERROR (Status
)) {
2140 NameValueType
= FALSE
;
2143 // Skip header part.
2145 StringPtr
= StrStr (ConfigResp
, L
"PATH=");
2146 ASSERT (StringPtr
!= NULL
);
2148 if (StrStr (StringPtr
, L
"&") != NULL
) {
2149 NameValueType
= TRUE
;
2152 // Not found Request element, return success.
2158 Status
= ValidateQuestionFromVfr(
2170 if (VarBuffer
!= NULL
) {
2171 FreePool (VarBuffer
);
2174 if (CurrentBlockArray
!= NULL
) {
2176 // Free Link Array CurrentBlockArray
2178 while (!IsListEmpty (&CurrentBlockArray
->Entry
)) {
2179 BlockData
= BASE_CR (CurrentBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2180 RemoveEntryList (&BlockData
->Entry
);
2181 FreePool (BlockData
);
2183 FreePool (CurrentBlockArray
);
2190 Check whether the ConfigRequest string has the request elements.
2191 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
2192 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
2194 @param ConfigRequest The input config request string.
2196 @retval TRUE The input include config request elements.
2197 @retval FALSE The input string not includes.
2201 GetElementsFromRequest (
2202 IN EFI_STRING ConfigRequest
2205 EFI_STRING TmpRequest
;
2207 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
2208 ASSERT (TmpRequest
!= NULL
);
2210 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
2218 This function parses the input ConfigRequest string and its matched IFR code
2219 string for setting default value and validating current setting.
2221 1. For setting default action, Reset the default value specified by DefaultId
2222 to the driver configuration got by Request string.
2223 2. For validating current setting, Validate the current configuration
2224 by parsing HII form IFR opcode.
2226 NULL request string support depends on the ExportConfig interface of
2227 HiiConfigRouting protocol in UEFI specification.
2229 @param Request A null-terminated Unicode string in
2230 <MultiConfigRequest> format. It can be NULL.
2231 If it is NULL, all current configuration for the
2232 entirety of the current HII database will be validated.
2233 If it is NULL, all configuration for the
2234 entirety of the current HII database will be reset.
2235 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.
2236 @param ActionType Action supports setting defaults and validate current setting.
2238 @retval TRUE Action runs successfully.
2239 @retval FALSE Action is not valid or Action can't be executed successfully..
2243 InternalHiiIfrValueAction (
2244 IN CONST EFI_STRING Request
, OPTIONAL
2245 IN UINT16 DefaultId
,
2249 EFI_STRING ConfigAltResp
;
2250 EFI_STRING ConfigAltHdr
;
2251 EFI_STRING ConfigResp
;
2252 EFI_STRING Progress
;
2253 EFI_STRING StringPtr
;
2254 EFI_STRING StringHdr
;
2256 EFI_HANDLE DriverHandle
;
2257 EFI_HANDLE TempDriverHandle
;
2258 EFI_HII_HANDLE
*HiiHandleBuffer
;
2259 EFI_HII_HANDLE HiiHandle
;
2264 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
2265 UINTN PackageListLength
;
2267 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2268 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2270 ConfigAltResp
= NULL
;
2275 ConfigAltHdr
= NULL
;
2276 HiiHandleBuffer
= NULL
;
2278 TempDriverHandle
= NULL
;
2280 HiiPackageList
= NULL
;
2283 // Only support set default and validate setting action.
2285 if ((ActionType
!= ACTION_SET_DEFAUTL_VALUE
) && (ActionType
!= ACTION_VALIDATE_SETTING
)) {
2290 // Get the full requested value and deault value string.
2292 if (Request
!= NULL
) {
2293 Status
= gHiiConfigRouting
->ExtractConfig (
2300 Status
= gHiiConfigRouting
->ExportConfig (
2306 if (EFI_ERROR (Status
)) {
2310 StringPtr
= ConfigAltResp
;
2311 ASSERT (StringPtr
!= NULL
);
2313 while (*StringPtr
!= L
'\0') {
2315 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
2317 StringHdr
= StringPtr
;
2322 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2323 Status
= EFI_INVALID_PARAMETER
;
2326 StringPtr
+= StrLen (L
"GUID=");
2327 Status
= InternalHiiGetBufferFromString (StringPtr
, GUID_CONFIG_STRING_TYPE
, (UINT8
**) &VarGuid
);
2328 if (EFI_ERROR (Status
)) {
2333 // Get Name value VarName
2335 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2338 if (*StringPtr
== L
'\0') {
2339 Status
= EFI_INVALID_PARAMETER
;
2342 StringPtr
+= StrLen (L
"&NAME=");
2343 Status
= InternalHiiGetBufferFromString (StringPtr
, NAME_CONFIG_STRING_TYPE
, (UINT8
**) &VarName
);
2344 if (EFI_ERROR (Status
)) {
2349 // Get Path value DevicePath
2351 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2354 if (*StringPtr
== L
'\0') {
2355 Status
= EFI_INVALID_PARAMETER
;
2358 StringPtr
+= StrLen (L
"&PATH=");
2359 Status
= InternalHiiGetBufferFromString (StringPtr
, PATH_CONFIG_STRING_TYPE
, (UINT8
**) &DevicePath
);
2360 if (EFI_ERROR (Status
)) {
2365 // Get the Driver handle by the got device path.
2367 TempDevicePath
= DevicePath
;
2368 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDevicePath
, &DriverHandle
);
2369 if (EFI_ERROR (Status
)) {
2374 // Find the matched Hii Handle for the found Driver handle
2376 HiiHandleBuffer
= HiiGetHiiHandles (NULL
);
2377 if (HiiHandleBuffer
== NULL
) {
2378 Status
= EFI_NOT_FOUND
;
2382 for (Index
= 0; HiiHandleBuffer
[Index
] != NULL
; Index
++) {
2383 gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, HiiHandleBuffer
[Index
], &TempDriverHandle
);
2384 if (TempDriverHandle
== DriverHandle
) {
2389 HiiHandle
= HiiHandleBuffer
[Index
];
2390 FreePool (HiiHandleBuffer
);
2392 if (HiiHandle
== NULL
) {
2394 // This request string has no its Hii package.
2395 // Its default value and validating can't execute by parsing IFR data.
2396 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
2398 Status
= EFI_SUCCESS
;
2399 goto NextConfigAltResp
;
2403 // 2. Get HiiPackage by HiiHandle
2405 PackageListLength
= 0;
2406 HiiPackageList
= NULL
;
2407 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2410 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
2412 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2413 Status
= EFI_INVALID_PARAMETER
;
2417 HiiPackageList
= AllocatePool (PackageListLength
);
2418 if (HiiPackageList
== NULL
) {
2419 Status
= EFI_OUT_OF_RESOURCES
;
2424 // Get PackageList on HiiHandle
2426 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
2427 if (EFI_ERROR (Status
)) {
2432 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2433 // Get the default configuration string according to the default ID.
2435 Status
= gHiiConfigRouting
->GetAltConfig (
2441 (ActionType
== ACTION_SET_DEFAUTL_VALUE
) ? &DefaultId
:NULL
, // it can be NULL to get the current setting.
2446 // The required setting can't be found. So, it is not required to be validated and set.
2448 if (EFI_ERROR (Status
)) {
2449 Status
= EFI_SUCCESS
;
2450 goto NextConfigAltResp
;
2453 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
2455 if (!GetElementsFromRequest (ConfigResp
)) {
2456 goto NextConfigAltResp
;
2460 // 4. Set the default configuration information or Validate current setting by parse IFR code.
2461 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2463 if (ActionType
== ACTION_SET_DEFAUTL_VALUE
) {
2465 // Set the default configuration information.
2467 Status
= gHiiConfigRouting
->RouteConfig (gHiiConfigRouting
, ConfigResp
, &Progress
);
2470 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
2472 Status
= InternalHiiValidateCurrentSetting (ConfigResp
, HiiPackageList
, PackageListLength
, VarGuid
, VarName
, HiiHandle
);
2475 if (EFI_ERROR (Status
)) {
2481 // Free the allocated pacakge buffer and the got ConfigResp string.
2483 if (HiiPackageList
!= NULL
) {
2484 FreePool (HiiPackageList
);
2485 HiiPackageList
= NULL
;
2488 if (ConfigResp
!= NULL
) {
2489 FreePool (ConfigResp
);
2494 // Free the allocated buffer.
2502 FreePool (DevicePath
);
2506 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
2510 // Get and Skip ConfigHdr
2512 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2515 if (*StringPtr
== L
'\0') {
2520 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"
2521 // | 1 | StrLen (ConfigHdr) | 8 | 1 |
2523 MaxLen
= 1 + StringPtr
- StringHdr
+ 8 + 1;
2524 ConfigAltHdr
= AllocateZeroPool ( MaxLen
* sizeof (CHAR16
));
2525 if (ConfigAltHdr
== NULL
) {
2526 Status
= EFI_OUT_OF_RESOURCES
;
2529 StrCpyS (ConfigAltHdr
, MaxLen
, L
"&");
2530 StrnCatS (ConfigAltHdr
, MaxLen
, StringHdr
, StringPtr
- StringHdr
);
2531 StrCatS (ConfigAltHdr
, MaxLen
, L
"&ALTCFG=");
2534 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
2536 while ((StringHdr
= StrStr (StringPtr
, ConfigAltHdr
)) != NULL
) {
2537 StringPtr
= StringHdr
+ StrLen (ConfigAltHdr
);
2538 if (*StringPtr
== L
'\0') {
2544 // Free the allocated ConfigAltHdr string
2546 FreePool (ConfigAltHdr
);
2547 if (*StringPtr
== L
'\0') {
2552 // Find &GUID as the next ConfigHdr
2554 StringPtr
= StrStr (StringPtr
, L
"&GUID");
2555 if (StringPtr
== NULL
) {
2566 if (VarGuid
!= NULL
) {
2570 if (VarName
!= NULL
) {
2574 if (DevicePath
!= NULL
) {
2575 FreePool (DevicePath
);
2578 if (ConfigResp
!= NULL
) {
2579 FreePool (ConfigResp
);
2582 if (ConfigAltResp
!= NULL
) {
2583 FreePool (ConfigAltResp
);
2586 if (HiiPackageList
!= NULL
) {
2587 FreePool (HiiPackageList
);
2590 if (EFI_ERROR (Status
)) {
2598 Validate the current configuration by parsing HII form IFR opcode.
2600 NULL request string support depends on the ExportConfig interface of
2601 HiiConfigRouting protocol in UEFI specification.
2603 @param Request A null-terminated Unicode string in
2604 <MultiConfigRequest> format. It can be NULL.
2605 If it is NULL, all current configuration for the
2606 entirety of the current HII database will be validated.
2608 @retval TRUE Current configuration is valid.
2609 @retval FALSE Current configuration is invalid.
2613 HiiValidateSettings (
2614 IN CONST EFI_STRING Request OPTIONAL
2617 return InternalHiiIfrValueAction (Request
, 0, ACTION_VALIDATE_SETTING
);
2621 Reset the default value specified by DefaultId to the driver
2622 configuration got by Request string.
2624 NULL request string support depends on the ExportConfig interface of
2625 HiiConfigRouting protocol in UEFI specification.
2627 @param Request A null-terminated Unicode string in
2628 <MultiConfigRequest> format. It can be NULL.
2629 If it is NULL, all configuration for the
2630 entirety of the current HII database will be reset.
2631 @param DefaultId Specifies the type of defaults to retrieve.
2633 @retval TRUE The default value is set successfully.
2634 @retval FALSE The default value can't be found and set.
2639 IN CONST EFI_STRING Request
, OPTIONAL
2643 return InternalHiiIfrValueAction (Request
, DefaultId
, ACTION_SET_DEFAUTL_VALUE
);
2647 Determines if two values in config strings match.
2649 Compares the substring between StartSearchString and StopSearchString in
2650 FirstString to the substring between StartSearchString and StopSearchString
2651 in SecondString. If the two substrings match, then TRUE is returned. If the
2652 two substrings do not match, then FALSE is returned.
2654 If FirstString is NULL, then ASSERT().
2655 If SecondString is NULL, then ASSERT().
2656 If StartSearchString is NULL, then ASSERT().
2657 If StopSearchString is NULL, then ASSERT().
2659 @param FirstString Pointer to the first Null-terminated Unicode string.
2660 @param SecondString Pointer to the second Null-terminated Unicode string.
2661 @param StartSearchString Pointer to the Null-terminated Unicode string that
2662 marks the start of the value string to compare.
2663 @param StopSearchString Pointer to the Null-terminated Unicode string that
2664 marks the end of the value string to compare.
2666 @retval FALSE StartSearchString is not present in FirstString.
2667 @retval FALSE StartSearchString is not present in SecondString.
2668 @retval FALSE StopSearchString is not present in FirstString.
2669 @retval FALSE StopSearchString is not present in SecondString.
2670 @retval FALSE The length of the substring in FirstString is not the
2671 same length as the substring in SecondString.
2672 @retval FALSE The value string in FirstString does not matche the
2673 value string in SecondString.
2674 @retval TRUE The value string in FirstString matches the value
2675 string in SecondString.
2680 InternalHiiCompareSubString (
2681 IN CHAR16
*FirstString
,
2682 IN CHAR16
*SecondString
,
2683 IN CHAR16
*StartSearchString
,
2684 IN CHAR16
*StopSearchString
2687 CHAR16
*EndFirstString
;
2688 CHAR16
*EndSecondString
;
2690 ASSERT (FirstString
!= NULL
);
2691 ASSERT (SecondString
!= NULL
);
2692 ASSERT (StartSearchString
!= NULL
);
2693 ASSERT (StopSearchString
!= NULL
);
2695 FirstString
= StrStr (FirstString
, StartSearchString
);
2696 if (FirstString
== NULL
) {
2700 SecondString
= StrStr (SecondString
, StartSearchString
);
2701 if (SecondString
== NULL
) {
2705 EndFirstString
= StrStr (FirstString
, StopSearchString
);
2706 if (EndFirstString
== NULL
) {
2710 EndSecondString
= StrStr (SecondString
, StopSearchString
);
2711 if (EndSecondString
== NULL
) {
2715 if ((EndFirstString
- FirstString
) != (EndSecondString
- SecondString
)) {
2719 return (BOOLEAN
)(StrnCmp (FirstString
, SecondString
, EndFirstString
- FirstString
) == 0);
2723 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
2725 If ConfigHdr is NULL, then ASSERT().
2727 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
2728 @param[in] Guid GUID of the storage.
2729 @param[in] Name NAME of the storage.
2731 @retval TRUE Routing information matches <ConfigHdr>.
2732 @retval FALSE Routing information does not match <ConfigHdr>.
2737 HiiIsConfigHdrMatch (
2738 IN CONST EFI_STRING ConfigHdr
,
2739 IN CONST EFI_GUID
*Guid
, OPTIONAL
2740 IN CONST CHAR16
*Name OPTIONAL
2743 EFI_STRING CompareConfigHdr
;
2746 ASSERT (ConfigHdr
!= NULL
);
2749 // Use Guid and Name to generate a <ConfigHdr> string
2751 CompareConfigHdr
= HiiConstructConfigHdr (Guid
, Name
, NULL
);
2752 if (CompareConfigHdr
== NULL
) {
2759 // Compare GUID value strings
2761 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"GUID=", L
"&NAME=");
2764 if (Result
&& Name
!= NULL
) {
2766 // Compare NAME value strings
2768 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"&NAME=", L
"&PATH=");
2772 // Free the <ConfigHdr> string
2774 FreePool (CompareConfigHdr
);
2780 Retrieves uncommitted data from the Form Browser and converts it to a binary
2783 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2784 parameter that may be NULL.
2785 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2786 is an optional parameter that may be NULL.
2787 @param[in] BufferSize Length in bytes of buffer to hold retrieved data.
2788 @param[out] Buffer Buffer of data to be updated.
2790 @retval FALSE The uncommitted data could not be retrieved.
2791 @retval TRUE The uncommitted data was retrieved.
2797 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2798 IN CONST CHAR16
*VariableName
, OPTIONAL
2799 IN UINTN BufferSize
,
2803 EFI_STRING ResultsData
;
2805 EFI_STRING ConfigResp
;
2810 // Retrieve the results data from the Browser Callback
2812 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, NULL
);
2813 if (ResultsData
== NULL
) {
2818 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
2820 Size
= (StrLen (mConfigHdrTemplate
) + 1) * sizeof (CHAR16
);
2821 Size
= Size
+ (StrLen (ResultsData
) + 1) * sizeof (CHAR16
);
2822 ConfigResp
= AllocateZeroPool (Size
);
2823 UnicodeSPrint (ConfigResp
, Size
, L
"%s&%s", mConfigHdrTemplate
, ResultsData
);
2826 // Free the allocated buffer
2828 FreePool (ResultsData
);
2829 if (ConfigResp
== NULL
) {
2834 // Convert <ConfigResp> to a buffer
2836 Status
= gHiiConfigRouting
->ConfigToBlock (
2844 // Free the allocated buffer
2846 FreePool (ConfigResp
);
2848 if (EFI_ERROR (Status
)) {
2856 Updates uncommitted data in the Form Browser.
2858 If Buffer is NULL, then ASSERT().
2860 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2861 parameter that may be NULL.
2862 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2863 is an optional parameter that may be NULL.
2864 @param[in] BufferSize Length, in bytes, of Buffer.
2865 @param[in] Buffer Buffer of data to commit.
2866 @param[in] RequestElement An optional field to specify which part of the
2867 buffer data will be send back to Browser. If NULL,
2868 the whole buffer of data will be committed to
2870 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
2872 @retval FALSE The uncommitted data could not be updated.
2873 @retval TRUE The uncommitted data was updated.
2879 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2880 IN CONST CHAR16
*VariableName
, OPTIONAL
2881 IN UINTN BufferSize
,
2882 IN CONST UINT8
*Buffer
,
2883 IN CONST CHAR16
*RequestElement OPTIONAL
2887 EFI_STRING ConfigRequest
;
2888 EFI_STRING ConfigResp
;
2889 EFI_STRING ResultsData
;
2891 ASSERT (Buffer
!= NULL
);
2894 // Construct <ConfigRequest>
2896 if (RequestElement
== NULL
) {
2898 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2899 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2901 Size
= (StrLen (mConfigHdrTemplate
) + 32 + 1) * sizeof (CHAR16
);
2902 ConfigRequest
= AllocateZeroPool (Size
);
2903 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate
, (UINT64
)BufferSize
);
2906 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2907 // followed by <RequestElement> followed by a Null-terminator
2909 Size
= StrLen (mConfigHdrTemplate
) * sizeof (CHAR16
);
2910 Size
= Size
+ (StrLen (RequestElement
) + 1) * sizeof (CHAR16
);
2911 ConfigRequest
= AllocateZeroPool (Size
);
2912 UnicodeSPrint (ConfigRequest
, Size
, L
"%s%s", mConfigHdrTemplate
, RequestElement
);
2914 if (ConfigRequest
== NULL
) {
2919 // Convert <ConfigRequest> to <ConfigResp>
2921 ConfigResp
= InternalHiiBlockToConfig (ConfigRequest
, Buffer
, BufferSize
);
2922 FreePool (ConfigRequest
);
2923 if (ConfigResp
== NULL
) {
2928 // Set data in the uncommitted browser state information
2930 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, ConfigResp
+ StrLen(mConfigHdrTemplate
) + 1);
2931 FreePool (ConfigResp
);
2933 return (BOOLEAN
)(ResultsData
!= NULL
);
2936 /////////////////////////////////////////
2937 /////////////////////////////////////////
2939 /////////////////////////////////////////
2940 /////////////////////////////////////////
2942 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
2948 } HII_LIB_OPCODE_BUFFER
;
2951 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
2953 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth
[] = {
2954 1, // EFI_IFR_TYPE_NUM_SIZE_8
2955 2, // EFI_IFR_TYPE_NUM_SIZE_16
2956 4, // EFI_IFR_TYPE_NUM_SIZE_32
2957 8, // EFI_IFR_TYPE_NUM_SIZE_64
2958 1, // EFI_IFR_TYPE_BOOLEAN
2959 3, // EFI_IFR_TYPE_TIME
2960 4, // EFI_IFR_TYPE_DATE
2961 2 // EFI_IFR_TYPE_STRING
2965 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
2966 HiiFreeOpCodeHandle().
2968 @retval NULL There are not enough resources to allocate a new OpCode Handle.
2969 @retval Other A new OpCode handle.
2974 HiiAllocateOpCodeHandle (
2978 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2980 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER
));
2981 if (OpCodeBuffer
== NULL
) {
2984 OpCodeBuffer
->Buffer
= (UINT8
*)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE
);
2985 if (OpCodeBuffer
->Buffer
== NULL
) {
2986 FreePool (OpCodeBuffer
);
2989 OpCodeBuffer
->BufferSize
= HII_LIB_OPCODE_ALLOCATION_SIZE
;
2990 OpCodeBuffer
->Position
= 0;
2991 return (VOID
*)OpCodeBuffer
;
2995 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
2996 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
2997 Handle are also freed.
2999 If OpCodeHandle is NULL, then ASSERT().
3001 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3006 HiiFreeOpCodeHandle (
3010 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
3012 ASSERT (OpCodeHandle
!= NULL
);
3014 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
3015 if (OpCodeBuffer
->Buffer
!= NULL
) {
3016 FreePool (OpCodeBuffer
->Buffer
);
3018 FreePool (OpCodeBuffer
);
3022 Internal function gets the current position of opcode buffer.
3024 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3026 @return Current position of opcode buffer.
3030 InternalHiiOpCodeHandlePosition (
3031 IN VOID
*OpCodeHandle
3034 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Position
;
3038 Internal function gets the start pointer of opcode buffer.
3040 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3042 @return Pointer to the opcode buffer base.
3046 InternalHiiOpCodeHandleBuffer (
3047 IN VOID
*OpCodeHandle
3050 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Buffer
;
3054 Internal function reserves the enough buffer for current opcode.
3055 When the buffer is not enough, Opcode buffer will be extended.
3057 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3058 @param[in] Size Size of current opcode.
3060 @return Pointer to the current opcode.
3064 InternalHiiGrowOpCodeHandle (
3065 IN VOID
*OpCodeHandle
,
3069 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
3072 ASSERT (OpCodeHandle
!= NULL
);
3074 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
3075 if (OpCodeBuffer
->Position
+ Size
> OpCodeBuffer
->BufferSize
) {
3076 Buffer
= ReallocatePool (
3077 OpCodeBuffer
->BufferSize
,
3078 OpCodeBuffer
->BufferSize
+ (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
),
3079 OpCodeBuffer
->Buffer
3081 ASSERT (Buffer
!= NULL
);
3082 OpCodeBuffer
->Buffer
= Buffer
;
3083 OpCodeBuffer
->BufferSize
+= (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
);
3085 Buffer
= OpCodeBuffer
->Buffer
+ OpCodeBuffer
->Position
;
3086 OpCodeBuffer
->Position
+= Size
;
3091 Internal function creates opcode based on the template opcode.
3093 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3094 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
3095 @param[in] OpCode OpCode IFR value.
3096 @param[in] OpCodeSize Size of opcode.
3097 @param[in] ExtensionSize Size of extended opcode.
3098 @param[in] Scope Scope bit of opcode.
3100 @return Pointer to the current opcode with opcode data.
3104 InternalHiiCreateOpCodeExtended (
3105 IN VOID
*OpCodeHandle
,
3106 IN VOID
*OpCodeTemplate
,
3108 IN UINTN OpCodeSize
,
3109 IN UINTN ExtensionSize
,
3113 EFI_IFR_OP_HEADER
*Header
;
3116 ASSERT (OpCodeTemplate
!= NULL
);
3117 ASSERT ((OpCodeSize
+ ExtensionSize
) <= 0x7F);
3119 Header
= (EFI_IFR_OP_HEADER
*)OpCodeTemplate
;
3120 Header
->OpCode
= OpCode
;
3121 Header
->Scope
= Scope
;
3122 Header
->Length
= (UINT8
)(OpCodeSize
+ ExtensionSize
);
3123 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, Header
->Length
);
3124 return (UINT8
*)CopyMem (Buffer
, Header
, OpCodeSize
);
3128 Internal function creates opcode based on the template opcode for the normal opcode.
3130 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3131 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
3132 @param[in] OpCode OpCode IFR value.
3133 @param[in] OpCodeSize Size of opcode.
3135 @return Pointer to the current opcode with opcode data.
3139 InternalHiiCreateOpCode (
3140 IN VOID
*OpCodeHandle
,
3141 IN VOID
*OpCodeTemplate
,
3146 return InternalHiiCreateOpCodeExtended (OpCodeHandle
, OpCodeTemplate
, OpCode
, OpCodeSize
, 0, 0);
3150 Append raw opcodes to an OpCodeHandle.
3152 If OpCodeHandle is NULL, then ASSERT().
3153 If RawBuffer is NULL, then ASSERT();
3155 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3156 @param[in] RawBuffer Buffer of opcodes to append.
3157 @param[in] RawBufferSize The size, in bytes, of Buffer.
3159 @retval NULL There is not enough space left in Buffer to add the opcode.
3160 @retval Other A pointer to the appended opcodes.
3165 HiiCreateRawOpCodes (
3166 IN VOID
*OpCodeHandle
,
3167 IN UINT8
*RawBuffer
,
3168 IN UINTN RawBufferSize
3173 ASSERT (RawBuffer
!= NULL
);
3175 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, RawBufferSize
);
3176 return (UINT8
*)CopyMem (Buffer
, RawBuffer
, RawBufferSize
);
3180 Append opcodes from one OpCode Handle to another OpCode handle.
3182 If OpCodeHandle is NULL, then ASSERT().
3183 If RawOpCodeHandle is NULL, then ASSERT();
3185 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3186 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
3188 @retval NULL There is not enough space left in Buffer to add the opcode.
3189 @retval Other A pointer to the appended opcodes.
3194 InternalHiiAppendOpCodes (
3195 IN VOID
*OpCodeHandle
,
3196 IN VOID
*RawOpCodeHandle
3199 HII_LIB_OPCODE_BUFFER
*RawOpCodeBuffer
;
3201 ASSERT (RawOpCodeHandle
!= NULL
);
3203 RawOpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)RawOpCodeHandle
;
3204 return HiiCreateRawOpCodes (OpCodeHandle
, RawOpCodeBuffer
->Buffer
, RawOpCodeBuffer
->Position
);
3208 Create EFI_IFR_END_OP opcode.
3210 If OpCodeHandle is NULL, then ASSERT().
3212 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3214 @retval NULL There is not enough space left in Buffer to add the opcode.
3215 @retval Other A pointer to the created opcode.
3220 HiiCreateEndOpCode (
3221 IN VOID
*OpCodeHandle
3226 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_END_OP
, sizeof (OpCode
));
3230 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
3232 If OpCodeHandle is NULL, then ASSERT().
3233 If Type is invalid, then ASSERT().
3234 If Flags is invalid, then ASSERT().
3236 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3237 @param[in] StringId StringId for the option
3238 @param[in] Flags Flags for the option
3239 @param[in] Type Type for the option
3240 @param[in] Value Value for the option
3242 @retval NULL There is not enough space left in Buffer to add the opcode.
3243 @retval Other A pointer to the created opcode.
3248 HiiCreateOneOfOptionOpCode (
3249 IN VOID
*OpCodeHandle
,
3256 EFI_IFR_ONE_OF_OPTION OpCode
;
3258 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
3260 ZeroMem (&OpCode
, sizeof (OpCode
));
3261 OpCode
.Option
= StringId
;
3262 OpCode
.Flags
= (UINT8
) (Flags
& (EFI_IFR_OPTION_DEFAULT
| EFI_IFR_OPTION_DEFAULT_MFG
));
3264 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
3266 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OPTION_OP
, OFFSET_OF(EFI_IFR_ONE_OF_OPTION
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
3270 Create EFI_IFR_DEFAULT_OP opcode.
3272 If OpCodeHandle is NULL, then ASSERT().
3273 If Type is invalid, then ASSERT().
3275 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3276 @param[in] DefaultId DefaultId for the default
3277 @param[in] Type Type for the default
3278 @param[in] Value Value for the default
3280 @retval NULL There is not enough space left in Buffer to add the opcode.
3281 @retval Other A pointer to the created opcode.
3286 HiiCreateDefaultOpCode (
3287 IN VOID
*OpCodeHandle
,
3288 IN UINT16 DefaultId
,
3293 EFI_IFR_DEFAULT OpCode
;
3295 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
3297 ZeroMem (&OpCode
, sizeof (OpCode
));
3299 OpCode
.DefaultId
= DefaultId
;
3300 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
3302 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DEFAULT_OP
, OFFSET_OF(EFI_IFR_DEFAULT
, Value
) + mHiiDefaultTypeToWidth
[Type
]);
3306 Create EFI_IFR_GUID opcode.
3308 If OpCodeHandle is NULL, then ASSERT().
3309 If Guid is NULL, then ASSERT().
3310 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
3312 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3313 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
3314 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
3315 optional parameter that may be NULL. If this
3316 parameter is NULL, then the GUID extension
3317 region of the created opcode is filled with zeros.
3318 If this parameter is not NULL, then the GUID
3319 extension region of GuidData will be copied to
3320 the GUID extension region of the created opcode.
3321 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
3322 must be >= sizeof(EFI_IFR_GUID).
3324 @retval NULL There is not enough space left in Buffer to add the opcode.
3325 @retval Other A pointer to the created opcode.
3330 HiiCreateGuidOpCode (
3331 IN VOID
*OpCodeHandle
,
3332 IN CONST EFI_GUID
*Guid
,
3333 IN CONST VOID
*GuidOpCode
, OPTIONAL
3337 EFI_IFR_GUID OpCode
;
3338 EFI_IFR_GUID
*OpCodePointer
;
3340 ASSERT (Guid
!= NULL
);
3341 ASSERT (OpCodeSize
>= sizeof (OpCode
));
3343 ZeroMem (&OpCode
, sizeof (OpCode
));
3344 CopyGuid ((EFI_GUID
*)(VOID
*)&OpCode
.Guid
, Guid
);
3346 OpCodePointer
= (EFI_IFR_GUID
*)InternalHiiCreateOpCodeExtended (
3351 OpCodeSize
- sizeof (OpCode
),
3354 if (OpCodePointer
!= NULL
&& GuidOpCode
!= NULL
) {
3355 CopyMem (OpCodePointer
+ 1, (EFI_IFR_GUID
*)GuidOpCode
+ 1, OpCodeSize
- sizeof (OpCode
));
3357 return (UINT8
*)OpCodePointer
;
3361 Create EFI_IFR_ACTION_OP opcode.
3363 If OpCodeHandle is NULL, then ASSERT().
3364 If any reserved bits are set in QuestionFlags, then ASSERT().
3366 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3367 @param[in] QuestionId Question ID
3368 @param[in] Prompt String ID for Prompt
3369 @param[in] Help String ID for Help
3370 @param[in] QuestionFlags Flags in Question Header
3371 @param[in] QuestionConfig String ID for configuration
3373 @retval NULL There is not enough space left in Buffer to add the opcode.
3374 @retval Other A pointer to the created opcode.
3379 HiiCreateActionOpCode (
3380 IN VOID
*OpCodeHandle
,
3381 IN EFI_QUESTION_ID QuestionId
,
3382 IN EFI_STRING_ID Prompt
,
3383 IN EFI_STRING_ID Help
,
3384 IN UINT8 QuestionFlags
,
3385 IN EFI_STRING_ID QuestionConfig
3388 EFI_IFR_ACTION OpCode
;
3390 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3392 ZeroMem (&OpCode
, sizeof (OpCode
));
3393 OpCode
.Question
.QuestionId
= QuestionId
;
3394 OpCode
.Question
.Header
.Prompt
= Prompt
;
3395 OpCode
.Question
.Header
.Help
= Help
;
3396 OpCode
.Question
.Flags
= QuestionFlags
;
3397 OpCode
.QuestionConfig
= QuestionConfig
;
3399 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ACTION_OP
, sizeof (OpCode
));
3403 Create EFI_IFR_SUBTITLE_OP opcode.
3405 If OpCodeHandle is NULL, then ASSERT().
3406 If any reserved bits are set in Flags, then ASSERT().
3407 If Scope > 1, then ASSERT().
3409 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3410 @param[in] Prompt String ID for Prompt
3411 @param[in] Help String ID for Help
3412 @param[in] Flags Subtitle opcode flags
3413 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
3414 0 if this opcode is within the current scope.
3416 @retval NULL There is not enough space left in Buffer to add the opcode.
3417 @retval Other A pointer to the created opcode.
3422 HiiCreateSubTitleOpCode (
3423 IN VOID
*OpCodeHandle
,
3424 IN EFI_STRING_ID Prompt
,
3425 IN EFI_STRING_ID Help
,
3430 EFI_IFR_SUBTITLE OpCode
;
3432 ASSERT (Scope
<= 1);
3433 ASSERT ((Flags
& (~(EFI_IFR_FLAGS_HORIZONTAL
))) == 0);
3435 ZeroMem (&OpCode
, sizeof (OpCode
));
3436 OpCode
.Statement
.Prompt
= Prompt
;
3437 OpCode
.Statement
.Help
= Help
;
3438 OpCode
.Flags
= Flags
;
3440 return InternalHiiCreateOpCodeExtended (
3443 EFI_IFR_SUBTITLE_OP
,
3451 Create EFI_IFR_REF_OP opcode.
3453 If OpCodeHandle is NULL, then ASSERT().
3454 If any reserved bits are set in QuestionFlags, then ASSERT().
3456 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3457 @param[in] FormId Destination Form ID
3458 @param[in] Prompt String ID for Prompt
3459 @param[in] Help String ID for Help
3460 @param[in] QuestionFlags Flags in Question Header
3461 @param[in] QuestionId Question ID
3463 @retval NULL There is not enough space left in Buffer to add the opcode.
3464 @retval Other A pointer to the created opcode.
3469 HiiCreateGotoOpCode (
3470 IN VOID
*OpCodeHandle
,
3471 IN EFI_FORM_ID FormId
,
3472 IN EFI_STRING_ID Prompt
,
3473 IN EFI_STRING_ID Help
,
3474 IN UINT8 QuestionFlags
,
3475 IN EFI_QUESTION_ID QuestionId
3480 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3482 ZeroMem (&OpCode
, sizeof (OpCode
));
3483 OpCode
.Question
.Header
.Prompt
= Prompt
;
3484 OpCode
.Question
.Header
.Help
= Help
;
3485 OpCode
.Question
.QuestionId
= QuestionId
;
3486 OpCode
.Question
.Flags
= QuestionFlags
;
3487 OpCode
.FormId
= FormId
;
3489 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, sizeof (OpCode
));
3493 Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.
3495 When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.
3496 When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.
3497 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.
3498 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.
3500 If OpCodeHandle is NULL, then ASSERT().
3501 If any reserved bits are set in QuestionFlags, then ASSERT().
3503 @param[in] OpCodeHandle The handle to the buffer of opcodes.
3504 @param[in] RefFormId The Destination Form ID.
3505 @param[in] Prompt The string ID for Prompt.
3506 @param[in] Help The string ID for Help.
3507 @param[in] QuestionFlags The flags in Question Header
3508 @param[in] QuestionId Question ID.
3509 @param[in] RefQuestionId The question on the form to which this link is referring.
3510 If its value is zero, then the link refers to the top of the form.
3511 @param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is
3512 zero, then the link is to the current form set.
3513 @param[in] RefDevicePath The string identifier that specifies the string containing the text representation of
3514 the device path to which the form set containing the form specified by FormId.
3515 If its value is zero, then the link refers to the current page.
3517 @retval NULL There is not enough space left in Buffer to add the opcode.
3518 @retval Other A pointer to the created opcode.
3523 HiiCreateGotoExOpCode (
3524 IN VOID
*OpCodeHandle
,
3525 IN EFI_FORM_ID RefFormId
,
3526 IN EFI_STRING_ID Prompt
,
3527 IN EFI_STRING_ID Help
,
3528 IN UINT8 QuestionFlags
,
3529 IN EFI_QUESTION_ID QuestionId
,
3530 IN EFI_QUESTION_ID RefQuestionId
,
3531 IN EFI_GUID
*RefFormSetId
, OPTIONAL
3532 IN EFI_STRING_ID RefDevicePath
3535 EFI_IFR_REF4 OpCode
;
3538 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3540 ZeroMem (&OpCode
, sizeof (OpCode
));
3541 OpCode
.Question
.Header
.Prompt
= Prompt
;
3542 OpCode
.Question
.Header
.Help
= Help
;
3543 OpCode
.Question
.QuestionId
= QuestionId
;
3544 OpCode
.Question
.Flags
= QuestionFlags
;
3545 OpCode
.FormId
= RefFormId
;
3546 OpCode
.QuestionId
= RefQuestionId
;
3547 OpCode
.DevicePath
= RefDevicePath
;
3548 if (RefFormSetId
!= NULL
) {
3549 CopyMem (&OpCode
.FormSetId
, RefFormSetId
, sizeof (OpCode
.FormSetId
));
3553 // Cacluate OpCodeSize based on the input Ref value.
3554 // Try to use the small OpCode to save size.
3556 OpCodeSize
= sizeof (EFI_IFR_REF
);
3557 if (RefDevicePath
!= 0) {
3558 OpCodeSize
= sizeof (EFI_IFR_REF4
);
3559 } else if (RefFormSetId
!= NULL
) {
3560 OpCodeSize
= sizeof (EFI_IFR_REF3
);
3561 } else if (RefQuestionId
!= 0) {
3562 OpCodeSize
= sizeof (EFI_IFR_REF2
);
3565 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, OpCodeSize
);
3569 Create EFI_IFR_CHECKBOX_OP opcode.
3571 If OpCodeHandle is NULL, then ASSERT().
3572 If any reserved bits are set in QuestionFlags, then ASSERT().
3573 If any reserved bits are set in CheckBoxFlags, then ASSERT().
3575 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3576 @param[in] QuestionId Question ID
3577 @param[in] VarStoreId Storage ID
3578 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3579 for this name/value pair.
3580 @param[in] Prompt String ID for Prompt
3581 @param[in] Help String ID for Help
3582 @param[in] QuestionFlags Flags in Question Header
3583 @param[in] CheckBoxFlags Flags for checkbox opcode
3584 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3585 is an optional parameter that may be NULL.
3587 @retval NULL There is not enough space left in Buffer to add the opcode.
3588 @retval Other A pointer to the created opcode.
3593 HiiCreateCheckBoxOpCode (
3594 IN VOID
*OpCodeHandle
,
3595 IN EFI_QUESTION_ID QuestionId
,
3596 IN EFI_VARSTORE_ID VarStoreId
,
3597 IN UINT16 VarOffset
,
3598 IN EFI_STRING_ID Prompt
,
3599 IN EFI_STRING_ID Help
,
3600 IN UINT8 QuestionFlags
,
3601 IN UINT8 CheckBoxFlags
,
3602 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3605 EFI_IFR_CHECKBOX OpCode
;
3608 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3610 ZeroMem (&OpCode
, sizeof (OpCode
));
3611 OpCode
.Question
.QuestionId
= QuestionId
;
3612 OpCode
.Question
.VarStoreId
= VarStoreId
;
3613 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3614 OpCode
.Question
.Header
.Prompt
= Prompt
;
3615 OpCode
.Question
.Header
.Help
= Help
;
3616 OpCode
.Question
.Flags
= QuestionFlags
;
3617 OpCode
.Flags
= CheckBoxFlags
;
3619 if (DefaultsOpCodeHandle
== NULL
) {
3620 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
));
3623 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3624 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
), 0, 1);
3625 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3626 HiiCreateEndOpCode (OpCodeHandle
);
3627 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3631 Create EFI_IFR_NUMERIC_OP opcode.
3633 If OpCodeHandle is NULL, then ASSERT().
3634 If any reserved bits are set in QuestionFlags, then ASSERT().
3635 If any reserved bits are set in NumericFlags, then ASSERT().
3637 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3638 @param[in] QuestionId Question ID
3639 @param[in] VarStoreId Storage ID
3640 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3641 for this name/value pair.
3642 @param[in] Prompt String ID for Prompt
3643 @param[in] Help String ID for Help
3644 @param[in] QuestionFlags Flags in Question Header
3645 @param[in] NumericFlags Flags for numeric opcode
3646 @param[in] Minimum Numeric minimum value
3647 @param[in] Maximum Numeric maximum value
3648 @param[in] Step Numeric step for edit
3649 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3650 is an optional parameter that may be NULL.
3652 @retval NULL There is not enough space left in Buffer to add the opcode.
3653 @retval Other A pointer to the created opcode.
3658 HiiCreateNumericOpCode (
3659 IN VOID
*OpCodeHandle
,
3660 IN EFI_QUESTION_ID QuestionId
,
3661 IN EFI_VARSTORE_ID VarStoreId
,
3662 IN UINT16 VarOffset
,
3663 IN EFI_STRING_ID Prompt
,
3664 IN EFI_STRING_ID Help
,
3665 IN UINT8 QuestionFlags
,
3666 IN UINT8 NumericFlags
,
3670 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3673 EFI_IFR_NUMERIC OpCode
;
3677 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3680 ZeroMem (&OpCode
, sizeof (OpCode
));
3681 OpCode
.Question
.QuestionId
= QuestionId
;
3682 OpCode
.Question
.VarStoreId
= VarStoreId
;
3683 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3684 OpCode
.Question
.Header
.Prompt
= Prompt
;
3685 OpCode
.Question
.Header
.Help
= Help
;
3686 OpCode
.Question
.Flags
= QuestionFlags
;
3687 OpCode
.Flags
= NumericFlags
;
3689 switch (NumericFlags
& EFI_IFR_NUMERIC_SIZE
) {
3690 case EFI_IFR_NUMERIC_SIZE_1
:
3691 OpCode
.data
.u8
.MinValue
= (UINT8
)Minimum
;
3692 OpCode
.data
.u8
.MaxValue
= (UINT8
)Maximum
;
3693 OpCode
.data
.u8
.Step
= (UINT8
)Step
;
3697 case EFI_IFR_NUMERIC_SIZE_2
:
3698 OpCode
.data
.u16
.MinValue
= (UINT16
)Minimum
;
3699 OpCode
.data
.u16
.MaxValue
= (UINT16
)Maximum
;
3700 OpCode
.data
.u16
.Step
= (UINT16
)Step
;
3704 case EFI_IFR_NUMERIC_SIZE_4
:
3705 OpCode
.data
.u32
.MinValue
= (UINT32
)Minimum
;
3706 OpCode
.data
.u32
.MaxValue
= (UINT32
)Maximum
;
3707 OpCode
.data
.u32
.Step
= (UINT32
)Step
;
3711 case EFI_IFR_NUMERIC_SIZE_8
:
3712 OpCode
.data
.u64
.MinValue
= Minimum
;
3713 OpCode
.data
.u64
.MaxValue
= Maximum
;
3714 OpCode
.data
.u64
.Step
= Step
;
3719 Length
+= OFFSET_OF (EFI_IFR_NUMERIC
, data
);
3721 if (DefaultsOpCodeHandle
== NULL
) {
3722 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
);
3725 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3726 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, Length
, 0, 1);
3727 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3728 HiiCreateEndOpCode (OpCodeHandle
);
3729 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3733 Create EFI_IFR_STRING_OP opcode.
3735 If OpCodeHandle is NULL, then ASSERT().
3736 If any reserved bits are set in QuestionFlags, then ASSERT().
3737 If any reserved bits are set in StringFlags, then ASSERT().
3739 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3740 @param[in] QuestionId Question ID
3741 @param[in] VarStoreId Storage ID
3742 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3743 for this name/value pair.
3744 @param[in] Prompt String ID for Prompt
3745 @param[in] Help String ID for Help
3746 @param[in] QuestionFlags Flags in Question Header
3747 @param[in] StringFlags Flags for string opcode
3748 @param[in] MinSize String minimum length
3749 @param[in] MaxSize String maximum length
3750 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3751 is an optional parameter that may be NULL.
3753 @retval NULL There is not enough space left in Buffer to add the opcode.
3754 @retval Other A pointer to the created opcode.
3759 HiiCreateStringOpCode (
3760 IN VOID
*OpCodeHandle
,
3761 IN EFI_QUESTION_ID QuestionId
,
3762 IN EFI_VARSTORE_ID VarStoreId
,
3763 IN UINT16 VarOffset
,
3764 IN EFI_STRING_ID Prompt
,
3765 IN EFI_STRING_ID Help
,
3766 IN UINT8 QuestionFlags
,
3767 IN UINT8 StringFlags
,
3770 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3773 EFI_IFR_STRING OpCode
;
3776 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3778 ZeroMem (&OpCode
, sizeof (OpCode
));
3779 OpCode
.Question
.Header
.Prompt
= Prompt
;
3780 OpCode
.Question
.Header
.Help
= Help
;
3781 OpCode
.Question
.QuestionId
= QuestionId
;
3782 OpCode
.Question
.VarStoreId
= VarStoreId
;
3783 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3784 OpCode
.Question
.Flags
= QuestionFlags
;
3785 OpCode
.MinSize
= MinSize
;
3786 OpCode
.MaxSize
= MaxSize
;
3787 OpCode
.Flags
= (UINT8
) (StringFlags
& EFI_IFR_STRING_MULTI_LINE
);
3789 if (DefaultsOpCodeHandle
== NULL
) {
3790 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
));
3793 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3794 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
), 0, 1);
3795 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3796 HiiCreateEndOpCode (OpCodeHandle
);
3797 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3801 Create EFI_IFR_ONE_OF_OP opcode.
3803 If OpCodeHandle is NULL, then ASSERT().
3804 If any reserved bits are set in QuestionFlags, then ASSERT().
3805 If any reserved bits are set in OneOfFlags, then ASSERT().
3807 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3808 @param[in] QuestionId Question ID
3809 @param[in] VarStoreId Storage ID
3810 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3811 for this name/value pair.
3812 @param[in] Prompt String ID for Prompt
3813 @param[in] Help String ID for Help
3814 @param[in] QuestionFlags Flags in Question Header
3815 @param[in] OneOfFlags Flags for oneof opcode
3816 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3817 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3818 is an optional parameter that may be NULL.
3820 @retval NULL There is not enough space left in Buffer to add the opcode.
3821 @retval Other A pointer to the created opcode.
3826 HiiCreateOneOfOpCode (
3827 IN VOID
*OpCodeHandle
,
3828 IN EFI_QUESTION_ID QuestionId
,
3829 IN EFI_VARSTORE_ID VarStoreId
,
3830 IN UINT16 VarOffset
,
3831 IN EFI_STRING_ID Prompt
,
3832 IN EFI_STRING_ID Help
,
3833 IN UINT8 QuestionFlags
,
3834 IN UINT8 OneOfFlags
,
3835 IN VOID
*OptionsOpCodeHandle
,
3836 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3839 EFI_IFR_ONE_OF OpCode
;
3843 ASSERT (OptionsOpCodeHandle
!= NULL
);
3844 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3846 ZeroMem (&OpCode
, sizeof (OpCode
));
3847 OpCode
.Question
.Header
.Prompt
= Prompt
;
3848 OpCode
.Question
.Header
.Help
= Help
;
3849 OpCode
.Question
.QuestionId
= QuestionId
;
3850 OpCode
.Question
.VarStoreId
= VarStoreId
;
3851 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3852 OpCode
.Question
.Flags
= QuestionFlags
;
3853 OpCode
.Flags
= OneOfFlags
;
3855 Length
= OFFSET_OF (EFI_IFR_ONE_OF
, data
);
3856 Length
+= (1 << (OneOfFlags
& EFI_IFR_NUMERIC_SIZE
)) * 3;
3858 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3859 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OP
, Length
, 0, 1);
3860 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3861 if (DefaultsOpCodeHandle
!= NULL
) {
3862 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3864 HiiCreateEndOpCode (OpCodeHandle
);
3865 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3869 Create EFI_IFR_ORDERED_LIST_OP opcode.
3871 If OpCodeHandle is NULL, then ASSERT().
3872 If any reserved bits are set in QuestionFlags, then ASSERT().
3873 If any reserved bits are set in OrderedListFlags, then ASSERT().
3875 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3876 @param[in] QuestionId Question ID
3877 @param[in] VarStoreId Storage ID
3878 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3879 for this name/value pair.
3880 @param[in] Prompt String ID for Prompt
3881 @param[in] Help String ID for Help
3882 @param[in] QuestionFlags Flags in Question Header
3883 @param[in] OrderedListFlags Flags for ordered list opcode
3884 @param[in] DataType Type for option value
3885 @param[in] MaxContainers Maximum count for options in this ordered list
3886 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3887 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3888 is an optional parameter that may be NULL.
3890 @retval NULL There is not enough space left in Buffer to add the opcode.
3891 @retval Other A pointer to the created opcode.
3896 HiiCreateOrderedListOpCode (
3897 IN VOID
*OpCodeHandle
,
3898 IN EFI_QUESTION_ID QuestionId
,
3899 IN EFI_VARSTORE_ID VarStoreId
,
3900 IN UINT16 VarOffset
,
3901 IN EFI_STRING_ID Prompt
,
3902 IN EFI_STRING_ID Help
,
3903 IN UINT8 QuestionFlags
,
3904 IN UINT8 OrderedListFlags
,
3906 IN UINT8 MaxContainers
,
3907 IN VOID
*OptionsOpCodeHandle
,
3908 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3911 EFI_IFR_ORDERED_LIST OpCode
;
3914 ASSERT (OptionsOpCodeHandle
!= NULL
);
3915 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3917 ZeroMem (&OpCode
, sizeof (OpCode
));
3918 OpCode
.Question
.Header
.Prompt
= Prompt
;
3919 OpCode
.Question
.Header
.Help
= Help
;
3920 OpCode
.Question
.QuestionId
= QuestionId
;
3921 OpCode
.Question
.VarStoreId
= VarStoreId
;
3922 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3923 OpCode
.Question
.Flags
= QuestionFlags
;
3924 OpCode
.MaxContainers
= MaxContainers
;
3925 OpCode
.Flags
= OrderedListFlags
;
3927 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3928 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ORDERED_LIST_OP
, sizeof (OpCode
), 0, 1);
3929 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3930 if (DefaultsOpCodeHandle
!= NULL
) {
3931 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3933 HiiCreateEndOpCode (OpCodeHandle
);
3934 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3938 Create EFI_IFR_TEXT_OP opcode.
3940 If OpCodeHandle is NULL, then ASSERT().
3942 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3943 @param[in] Prompt String ID for Prompt.
3944 @param[in] Help String ID for Help.
3945 @param[in] TextTwo String ID for TextTwo.
3947 @retval NULL There is not enough space left in Buffer to add the opcode.
3948 @retval Other A pointer to the created opcode.
3953 HiiCreateTextOpCode (
3954 IN VOID
*OpCodeHandle
,
3955 IN EFI_STRING_ID Prompt
,
3956 IN EFI_STRING_ID Help
,
3957 IN EFI_STRING_ID TextTwo
3960 EFI_IFR_TEXT OpCode
;
3962 ZeroMem (&OpCode
, sizeof (OpCode
));
3963 OpCode
.Statement
.Prompt
= Prompt
;
3964 OpCode
.Statement
.Help
= Help
;
3965 OpCode
.TextTwo
= TextTwo
;
3967 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TEXT_OP
, sizeof (OpCode
));
3971 Create EFI_IFR_DATE_OP opcode.
3973 If OpCodeHandle is NULL, then ASSERT().
3974 If any reserved bits are set in QuestionFlags, then ASSERT().
3975 If any reserved bits are set in DateFlags, then ASSERT().
3977 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3978 @param[in] QuestionId Question ID
3979 @param[in] VarStoreId Storage ID, optional. If DateFlags is not
3980 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3981 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
3982 for this name/value pair, optional. If DateFlags is not
3983 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3984 @param[in] Prompt String ID for Prompt
3985 @param[in] Help String ID for Help
3986 @param[in] QuestionFlags Flags in Question Header
3987 @param[in] DateFlags Flags for date opcode
3988 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3989 is an optional parameter that may be NULL.
3991 @retval NULL There is not enough space left in Buffer to add the opcode.
3992 @retval Other A pointer to the created opcode.
3997 HiiCreateDateOpCode (
3998 IN VOID
*OpCodeHandle
,
3999 IN EFI_QUESTION_ID QuestionId
,
4000 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
4001 IN UINT16 VarOffset
, OPTIONAL
4002 IN EFI_STRING_ID Prompt
,
4003 IN EFI_STRING_ID Help
,
4004 IN UINT8 QuestionFlags
,
4006 IN VOID
*DefaultsOpCodeHandle OPTIONAL
4009 EFI_IFR_DATE OpCode
;
4012 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
4013 ASSERT ((DateFlags
& (~(EFI_QF_DATE_YEAR_SUPPRESS
| EFI_QF_DATE_MONTH_SUPPRESS
| EFI_QF_DATE_DAY_SUPPRESS
| EFI_QF_DATE_STORAGE
))) == 0);
4015 ZeroMem (&OpCode
, sizeof (OpCode
));
4016 OpCode
.Question
.Header
.Prompt
= Prompt
;
4017 OpCode
.Question
.Header
.Help
= Help
;
4018 OpCode
.Question
.QuestionId
= QuestionId
;
4019 OpCode
.Question
.VarStoreId
= VarStoreId
;
4020 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
4021 OpCode
.Question
.Flags
= QuestionFlags
;
4022 OpCode
.Flags
= DateFlags
;
4024 if (DefaultsOpCodeHandle
== NULL
) {
4025 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
));
4028 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
4029 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
), 0, 1);
4030 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
4031 HiiCreateEndOpCode (OpCodeHandle
);
4032 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
4036 Create EFI_IFR_TIME_OP opcode.
4038 If OpCodeHandle is NULL, then ASSERT().
4039 If any reserved bits are set in QuestionFlags, then ASSERT().
4040 If any reserved bits are set in TimeFlags, then ASSERT().
4042 @param[in] OpCodeHandle Handle to the buffer of opcodes.
4043 @param[in] QuestionId Question ID
4044 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not
4045 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
4046 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)
4047 for this name/value pair, optional. If TimeFlags is not
4048 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
4049 @param[in] Prompt String ID for Prompt
4050 @param[in] Help String ID for Help
4051 @param[in] QuestionFlags Flags in Question Header
4052 @param[in] TimeFlags Flags for time opcode
4053 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
4054 is an optional parameter that may be NULL.
4056 @retval NULL There is not enough space left in Buffer to add the opcode.
4057 @retval Other A pointer to the created opcode.
4062 HiiCreateTimeOpCode (
4063 IN VOID
*OpCodeHandle
,
4064 IN EFI_QUESTION_ID QuestionId
,
4065 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
4066 IN UINT16 VarOffset
, OPTIONAL
4067 IN EFI_STRING_ID Prompt
,
4068 IN EFI_STRING_ID Help
,
4069 IN UINT8 QuestionFlags
,
4071 IN VOID
*DefaultsOpCodeHandle OPTIONAL
4074 EFI_IFR_TIME OpCode
;
4077 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
4078 ASSERT ((TimeFlags
& (~(QF_TIME_HOUR_SUPPRESS
| QF_TIME_MINUTE_SUPPRESS
| QF_TIME_SECOND_SUPPRESS
| QF_TIME_STORAGE
))) == 0);
4080 ZeroMem (&OpCode
, sizeof (OpCode
));
4081 OpCode
.Question
.Header
.Prompt
= Prompt
;
4082 OpCode
.Question
.Header
.Help
= Help
;
4083 OpCode
.Question
.QuestionId
= QuestionId
;
4084 OpCode
.Question
.VarStoreId
= VarStoreId
;
4085 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
4086 OpCode
.Question
.Flags
= QuestionFlags
;
4087 OpCode
.Flags
= TimeFlags
;
4089 if (DefaultsOpCodeHandle
== NULL
) {
4090 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
));
4093 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
4094 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
), 0, 1);
4095 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
4096 HiiCreateEndOpCode (OpCodeHandle
);
4097 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
4101 This is the internal worker function to update the data in
4102 a form specified by FormSetGuid, FormId and Label.
4104 @param[in] FormSetGuid The optional Formset GUID.
4105 @param[in] FormId The Form ID.
4106 @param[in] Package The package header.
4107 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR
4108 opcodes to be inserted or replaced in the form.
4109 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode
4110 that marks the end of a replace operation in the form.
4111 @param[out] TempPackage The resultant package.
4113 @retval EFI_SUCCESS The function completes successfully.
4114 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.
4119 InternalHiiUpdateFormPackageData (
4120 IN EFI_GUID
*FormSetGuid
, OPTIONAL
4121 IN EFI_FORM_ID FormId
,
4122 IN EFI_HII_PACKAGE_HEADER
*Package
,
4123 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
,
4124 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
, OPTIONAL
4125 OUT EFI_HII_PACKAGE_HEADER
*TempPackage
4130 EFI_HII_PACKAGE_HEADER PackageHeader
;
4132 EFI_IFR_OP_HEADER
*IfrOpHdr
;
4133 EFI_IFR_OP_HEADER
*UpdateIfrOpHdr
;
4137 UINTN UpdatePackageLength
;
4139 CopyMem (TempPackage
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4140 UpdatePackageLength
= sizeof (EFI_HII_PACKAGE_HEADER
);
4141 BufferPos
= (UINT8
*) (TempPackage
+ 1);
4143 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4144 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
4145 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
4146 GetFormSet
= (BOOLEAN
) ((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
4150 while (Offset
< PackageHeader
.Length
) {
4151 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
4152 BufferPos
+= IfrOpHdr
->Length
;
4153 UpdatePackageLength
+= IfrOpHdr
->Length
;
4156 // Find the matched FormSet and Form
4158 if ((IfrOpHdr
->OpCode
== EFI_IFR_FORM_SET_OP
) && (FormSetGuid
!= NULL
)) {
4159 if (CompareGuid((GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
)) {
4164 } else if (IfrOpHdr
->OpCode
== EFI_IFR_FORM_OP
|| IfrOpHdr
->OpCode
== EFI_IFR_FORM_MAP_OP
) {
4165 if (CompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
4173 // The matched Form is found, and Update data in this form
4175 if (GetFormSet
&& GetForm
) {
4176 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
;
4177 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
4178 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
4180 // Remove the original data when End OpCode buffer exist.
4182 if (OpCodeBufferEnd
!= NULL
) {
4183 Offset
+= IfrOpHdr
->Length
;
4184 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
4185 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferEnd
->Buffer
;
4186 while (Offset
< PackageHeader
.Length
) {
4188 // Search the matched end opcode
4190 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
4191 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
4195 // Go to the next Op-Code
4197 Offset
+= IfrOpHdr
->Length
;
4198 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
4201 if (Offset
>= PackageHeader
.Length
) {
4203 // The end opcode is not found.
4205 return EFI_NOT_FOUND
;
4210 // Insert the updated data
4212 AddSize
= ((EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
)->Length
;
4213 CopyMem (BufferPos
, OpCodeBufferStart
->Buffer
+ AddSize
, OpCodeBufferStart
->Position
- AddSize
);
4214 BufferPos
+= OpCodeBufferStart
->Position
- AddSize
;
4215 UpdatePackageLength
+= OpCodeBufferStart
->Position
- AddSize
;
4217 if (OpCodeBufferEnd
!= NULL
) {
4219 // Add the end opcode
4221 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
4222 BufferPos
+= IfrOpHdr
->Length
;
4223 UpdatePackageLength
+= IfrOpHdr
->Length
;
4227 // Copy the left package data.
4229 Offset
+= IfrOpHdr
->Length
;
4230 CopyMem (BufferPos
, (UINT8
*) Package
+ Offset
, PackageHeader
.Length
- Offset
);
4231 UpdatePackageLength
+= PackageHeader
.Length
- Offset
;
4242 // Go to the next Op-Code
4244 Offset
+= IfrOpHdr
->Length
;
4245 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
4250 // The updated opcode buffer is not found.
4252 return EFI_NOT_FOUND
;
4255 // Update the package length.
4257 PackageHeader
.Length
= (UINT32
) UpdatePackageLength
;
4258 CopyMem (TempPackage
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4264 This function updates a form that has previously been registered with the HII
4265 Database. This function will perform at most one update operation.
4267 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
4268 comparisons of IFR opcodes are performed from the beginning of the form being
4269 updated until an IFR opcode is found that exactly matches the first IFR opcode
4270 specified by StartOpCodeHandle. The following rules are used to determine if
4271 an insert, replace, or delete operation is performed.
4273 1) If no matches are found, then NULL is returned.
4274 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
4275 from StartOpCodeHandle except the first opcode are inserted immediately after
4276 the matching IFR opcode in the form to be updated.
4277 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
4278 from the matching IFR opcode until an IFR opcode exactly matches the first
4279 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
4280 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
4281 is found, then all of the IFR opcodes between the start match and the end
4282 match are deleted from the form being updated and all of the IFR opcodes
4283 from StartOpCodeHandle except the first opcode are inserted immediately after
4284 the matching start IFR opcode. If StartOpCcodeHandle only contains one
4285 IFR instruction, then the result of this operation will delete all of the IFR
4286 opcodes between the start end matches.
4288 If HiiHandle is NULL, then ASSERT().
4289 If StartOpCodeHandle is NULL, then ASSERT().
4291 @param[in] HiiHandle The HII Handle of the form to update.
4292 @param[in] FormSetGuid The Formset GUID of the form to update. This
4293 is an optional parameter that may be NULL.
4294 If it is NULL, all FormSet will be updated.
4295 @param[in] FormId The ID of the form to update.
4296 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
4297 opcodes to be inserted or replaced in the form.
4298 The first IFR instruction in StartOpCodeHandle
4299 is used to find matching IFR opcode in the
4301 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
4302 that marks the end of a replace operation in
4303 the form. This is an optional parameter that
4304 may be NULL. If it is NULL, then an the IFR
4305 opcodes specified by StartOpCodeHandle are
4306 inserted into the form.
4308 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
4309 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
4310 1) The form specified by HiiHandle, FormSetGuid,
4311 and FormId could not be found in the HII Database.
4312 2) No IFR opcodes in the target form match the first
4313 IFR opcode in StartOpCodeHandle.
4314 3) EndOpCOde is not NULL, and no IFR opcodes in the
4315 target form following a matching start opcode match
4316 the first IFR opcode in EndOpCodeHandle.
4317 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
4323 IN EFI_HII_HANDLE HiiHandle
,
4324 IN EFI_GUID
*FormSetGuid
, OPTIONAL
4325 IN EFI_FORM_ID FormId
,
4326 IN VOID
*StartOpCodeHandle
,
4327 IN VOID
*EndOpCodeHandle OPTIONAL
4331 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4332 UINT32 PackageListLength
;
4334 EFI_HII_PACKAGE_LIST_HEADER
*UpdatePackageList
;
4336 UINT8
*UpdateBufferPos
;
4337 EFI_HII_PACKAGE_HEADER
*Package
;
4338 EFI_HII_PACKAGE_HEADER
*TempPackage
;
4339 EFI_HII_PACKAGE_HEADER PackageHeader
;
4341 HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
;
4342 HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
;
4345 // Input update data can't be NULL.
4347 ASSERT (HiiHandle
!= NULL
);
4348 ASSERT (StartOpCodeHandle
!= NULL
);
4349 UpdatePackageList
= NULL
;
4351 HiiPackageList
= NULL
;
4354 // Retrieve buffer data from Opcode Handle
4356 OpCodeBufferStart
= (HII_LIB_OPCODE_BUFFER
*) StartOpCodeHandle
;
4357 OpCodeBufferEnd
= (HII_LIB_OPCODE_BUFFER
*) EndOpCodeHandle
;
4360 // Get the original package list
4363 HiiPackageList
= NULL
;
4364 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4366 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
4368 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4372 HiiPackageList
= AllocatePool (BufferSize
);
4373 if (HiiPackageList
== NULL
) {
4374 Status
= EFI_OUT_OF_RESOURCES
;
4378 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
4379 if (EFI_ERROR (Status
)) {
4384 // Calculate and allocate space for retrieval of IFR data
4386 BufferSize
+= OpCodeBufferStart
->Position
;
4387 UpdatePackageList
= AllocateZeroPool (BufferSize
);
4388 if (UpdatePackageList
== NULL
) {
4389 Status
= EFI_OUT_OF_RESOURCES
;
4394 // Allocate temp buffer to store the temp updated package buffer
4396 TempPackage
= AllocateZeroPool (BufferSize
);
4397 if (TempPackage
== NULL
) {
4398 Status
= EFI_OUT_OF_RESOURCES
;
4402 UpdateBufferPos
= (UINT8
*) UpdatePackageList
;
4405 // Copy the package list header
4407 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
4408 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4411 // Go through each package to find the matched package and update one by one
4414 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4415 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
4416 while (Offset
< PackageListLength
) {
4417 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
4418 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4419 Offset
+= Package
->Length
;
4421 if (Package
->Type
== EFI_HII_PACKAGE_FORMS
) {
4423 // Check this package is the matched package.
4425 Status
= InternalHiiUpdateFormPackageData (FormSetGuid
, FormId
, Package
, OpCodeBufferStart
, OpCodeBufferEnd
, TempPackage
);
4427 // The matched package is found. Its package buffer will be updated by the input new data.
4429 if (!EFI_ERROR(Status
)) {
4435 // Add updated package buffer
4437 Package
= TempPackage
;
4442 // Add pacakge buffer
4444 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4445 CopyMem (UpdateBufferPos
, Package
, PackageHeader
.Length
);
4446 UpdateBufferPos
+= PackageHeader
.Length
;
4451 // Update package list length
4453 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdatePackageList
;
4454 WriteUnaligned32 (&UpdatePackageList
->PackageLength
, (UINT32
) BufferSize
);
4457 // Update Package to show form
4459 Status
= gHiiDatabase
->UpdatePackageList (gHiiDatabase
, HiiHandle
, UpdatePackageList
);
4462 // Not matched form is found and updated.
4464 Status
= EFI_NOT_FOUND
;
4468 if (HiiPackageList
!= NULL
) {
4469 FreePool (HiiPackageList
);
4472 if (UpdatePackageList
!= NULL
) {
4473 FreePool (UpdatePackageList
);
4476 if (TempPackage
!= NULL
) {
4477 FreePool (TempPackage
);