2 HII Library implementation that uses DXE protocols and services.
4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "InternalHiiLib.h"
17 #define GUID_CONFIG_STRING_TYPE 0x00
18 #define NAME_CONFIG_STRING_TYPE 0x01
19 #define PATH_CONFIG_STRING_TYPE 0x02
21 #define ACTION_SET_DEFAUTL_VALUE 0x01
22 #define ACTION_VALIDATE_SETTING 0x02
24 #define HII_LIB_DEFAULT_VARSTORE_SIZE 0x200
27 LIST_ENTRY Entry
; // Link to Block array
35 // <ConfigHdr> Template
37 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";
39 EFI_FORM_BROWSER2_PROTOCOL
*mUefiFormBrowser2
= NULL
;
42 // Template used to mark the end of a list of packages
44 GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER mEndOfPakageList
= {
45 sizeof (EFI_HII_PACKAGE_HEADER
),
50 Extract Hii package list GUID for given HII handle.
52 If HiiHandle could not be found in the HII database, then ASSERT.
53 If Guid is NULL, then ASSERT.
55 @param Handle Hii handle
56 @param Guid Package list GUID
58 @retval EFI_SUCCESS Successfully extract GUID from Hii database.
63 InternalHiiExtractGuidFromHiiHandle (
64 IN EFI_HII_HANDLE Handle
,
70 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
72 ASSERT (Guid
!= NULL
);
73 ASSERT (Handle
!= NULL
);
76 // Get HII PackageList
79 HiiPackageList
= NULL
;
81 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
82 ASSERT (Status
!= EFI_NOT_FOUND
);
84 if (Status
== EFI_BUFFER_TOO_SMALL
) {
85 HiiPackageList
= AllocatePool (BufferSize
);
86 ASSERT (HiiPackageList
!= NULL
);
88 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
90 if (EFI_ERROR (Status
)) {
91 FreePool (HiiPackageList
);
98 CopyGuid (Guid
, &HiiPackageList
->PackageListGuid
);
100 FreePool (HiiPackageList
);
106 Registers a list of packages in the HII Database and returns the HII Handle
107 associated with that registration. If an HII Handle has already been registered
108 with the same PackageListGuid and DeviceHandle, then NULL is returned. If there
109 are not enough resources to perform the registration, then NULL is returned.
110 If an empty list of packages is passed in, then NULL is returned. If the size of
111 the list of package is 0, then NULL is returned.
113 The variable arguments are pointers which point to package header that defined
114 by UEFI VFR compiler and StringGather tool.
116 #pragma pack (push, 1)
119 EFI_HII_PACKAGE_HEADER PackageHeader;
120 } EDKII_AUTOGEN_PACKAGES_HEADER;
123 @param[in] PackageListGuid The GUID of the package list.
124 @param[in] DeviceHandle If not NULL, the Device Handle on which
125 an instance of DEVICE_PATH_PROTOCOL is installed.
126 This Device Handle uniquely defines the device that
127 the added packages are associated with.
128 @param[in] ... The variable argument list that contains pointers
129 to packages terminated by a NULL.
131 @retval NULL A HII Handle has already been registered in the HII Database with
132 the same PackageListGuid.
133 @retval NULL The HII Handle could not be created.
134 @retval NULL An empty list of packages was passed in.
135 @retval NULL All packages are empty.
136 @retval Other The HII Handle associated with the newly registered package list.
142 IN CONST EFI_GUID
*PackageListGuid
,
143 IN EFI_HANDLE DeviceHandle OPTIONAL
,
150 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
151 EFI_HII_HANDLE HiiHandle
;
155 ASSERT (PackageListGuid
!= NULL
);
158 // Calculate the length of all the packages in the variable argument list
160 for (Length
= 0, VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
161 Length
+= (ReadUnaligned32 (Package
) - sizeof (UINT32
));
166 // If there are no packages in the variable argument list or all the packages
167 // are empty, then return a NULL HII Handle
174 // Add the length of the Package List Header and the terminating Package Header
176 Length
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
) + sizeof (EFI_HII_PACKAGE_HEADER
);
179 // Allocate the storage for the entire Package List
181 PackageListHeader
= AllocateZeroPool (Length
);
184 // If the Package List can not be allocated, then return a NULL HII Handle
186 if (PackageListHeader
== NULL
) {
191 // Fill in the GUID and Length of the Package List Header
193 CopyGuid (&PackageListHeader
->PackageListGuid
, PackageListGuid
);
194 PackageListHeader
->PackageLength
= Length
;
197 // Initialize a pointer to the beginning if the Package List data
199 Data
= (UINT8
*)(PackageListHeader
+ 1);
202 // Copy the data from each package in the variable argument list
204 for (VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
205 Length
= ReadUnaligned32 (Package
) - sizeof (UINT32
);
206 CopyMem (Data
, Package
+ 1, Length
);
212 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list
214 CopyMem (Data
, &mEndOfPakageList
, sizeof (mEndOfPakageList
));
217 // Register the package list with the HII Database
219 Status
= gHiiDatabase
->NewPackageList (
225 if (EFI_ERROR (Status
)) {
230 // Free the allocated package list
232 FreePool (PackageListHeader
);
235 // Return the new HII Handle
241 Removes a package list from the HII database.
243 If HiiHandle is NULL, then ASSERT.
244 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.
246 @param[in] HiiHandle The handle that was previously registered in the HII database
252 IN EFI_HII_HANDLE HiiHandle
257 ASSERT (HiiHandle
!= NULL
);
258 Status
= gHiiDatabase
->RemovePackageList (gHiiDatabase
, HiiHandle
);
259 ASSERT_EFI_ERROR (Status
);
264 Retrieves the array of all the HII Handles or the HII handles of a specific
265 package list GUID in the HII Database.
266 This array is terminated with a NULL HII Handle.
267 This function allocates the returned array using AllocatePool().
268 The caller is responsible for freeing the array with FreePool().
270 @param[in] PackageListGuid An optional parameter that is used to request
271 HII Handles associated with a specific
272 Package List GUID. If this parameter is NULL,
273 then all the HII Handles in the HII Database
274 are returned. If this parameter is not NULL,
275 then zero or more HII Handles associated with
276 PackageListGuid are returned.
278 @retval NULL No HII handles were found in the HII database
279 @retval NULL The array of HII Handles could not be retrieved
280 @retval Other A pointer to the NULL terminated array of HII Handles
286 IN CONST EFI_GUID
*PackageListGuid OPTIONAL
290 UINTN HandleBufferLength
;
291 EFI_HII_HANDLE TempHiiHandleBuffer
;
292 EFI_HII_HANDLE
*HiiHandleBuffer
;
298 // Retrieve the size required for the buffer of all HII handles.
300 HandleBufferLength
= 0;
301 Status
= gHiiDatabase
->ListPackageLists (
303 EFI_HII_PACKAGE_TYPE_ALL
,
310 // If ListPackageLists() returns EFI_SUCCESS for a zero size,
311 // then there are no HII handles in the HII database. If ListPackageLists()
312 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII
313 // handles in the HII database.
315 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
317 // Return NULL if the size can not be retrieved, or if there are no HII
318 // handles in the HII Database
324 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator
326 HiiHandleBuffer
= AllocateZeroPool (HandleBufferLength
+ sizeof (EFI_HII_HANDLE
));
327 if (HiiHandleBuffer
== NULL
) {
329 // Return NULL if allocation fails.
335 // Retrieve the array of HII Handles in the HII Database
337 Status
= gHiiDatabase
->ListPackageLists (
339 EFI_HII_PACKAGE_TYPE_ALL
,
344 if (EFI_ERROR (Status
)) {
346 // Free the buffer and return NULL if the HII handles can not be retrieved.
348 FreePool (HiiHandleBuffer
);
352 if (PackageListGuid
== NULL
) {
354 // Return the NULL terminated array of HII handles in the HII Database
356 return HiiHandleBuffer
;
358 for (Index1
= 0, Index2
= 0; HiiHandleBuffer
[Index1
] != NULL
; Index1
++) {
359 Status
= InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer
[Index1
], &Guid
);
360 ASSERT_EFI_ERROR (Status
);
361 if (CompareGuid (&Guid
, PackageListGuid
)) {
362 HiiHandleBuffer
[Index2
++] = HiiHandleBuffer
[Index1
];
366 HiiHandleBuffer
[Index2
] = NULL
;
367 return HiiHandleBuffer
;
369 FreePool (HiiHandleBuffer
);
376 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
377 hex digits that appear between a '=' and a '&' in a config string.
379 If ConfigString is NULL, then ASSERT().
381 @param[in] ConfigString Pointer to a Null-terminated Unicode string.
383 @return Pointer to the Null-terminated Unicode result string.
388 InternalHiiLowerConfigString (
389 IN EFI_STRING ConfigString
395 ASSERT (ConfigString
!= NULL
);
398 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
400 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
401 if (*String
== L
'=') {
403 } else if (*String
== L
'&') {
405 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
406 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
414 Uses the BlockToConfig() service of the Config Routing Protocol to
415 convert <ConfigRequest> and a buffer to a <ConfigResp>
417 If ConfigRequest is NULL, then ASSERT().
418 If Block is NULL, then ASSERT().
420 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.
421 @param[in] Block Pointer to a block of data.
422 @param[in] BlockSize The zie, in bytes, of Block.
424 @retval NULL The <ConfigResp> string could not be generated.
425 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.
430 InternalHiiBlockToConfig (
431 IN CONST EFI_STRING ConfigRequest
,
432 IN CONST UINT8
*Block
,
437 EFI_STRING ConfigResp
;
440 ASSERT (ConfigRequest
!= NULL
);
441 ASSERT (Block
!= NULL
);
444 // Convert <ConfigRequest> to <ConfigResp>
446 Status
= gHiiConfigRouting
->BlockToConfig (
454 if (EFI_ERROR (Status
)) {
461 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve
462 or set uncommitted data. If sata i being retrieved, then the buffer is
463 allocated using AllocatePool(). The caller is then responsible for freeing
464 the buffer using FreePool().
466 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
467 parameter that may be NULL.
468 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
469 is an optional parameter that may be NULL.
470 @param[in] SetResultsData If not NULL, then this parameter specified the buffer
471 of uncommited data to set. If this parameter is NULL,
472 then the caller is requesting to get the uncommited data
473 from the Form Browser.
475 @retval NULL The uncommitted data could not be retrieved.
476 @retval Other A pointer to a buffer containing the uncommitted data.
481 InternalHiiBrowserCallback (
482 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
483 IN CONST CHAR16
*VariableName
, OPTIONAL
484 IN CONST EFI_STRING SetResultsData OPTIONAL
488 UINTN ResultsDataSize
;
489 EFI_STRING ResultsData
;
490 CHAR16 TempResultsData
;
495 if (mUefiFormBrowser2
== NULL
) {
496 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mUefiFormBrowser2
);
497 if (EFI_ERROR (Status
) || mUefiFormBrowser2
== NULL
) {
504 if (SetResultsData
!= NULL
) {
506 // Request to to set data in the uncommitted browser state information
508 ResultsData
= SetResultsData
;
511 // Retrieve the length of the buffer required ResultsData from the Browser Callback
513 Status
= mUefiFormBrowser2
->BrowserCallback (
522 if (!EFI_ERROR (Status
)) {
524 // No Resluts Data, only allocate one char for '\0'
526 ResultsData
= AllocateZeroPool (sizeof (CHAR16
));
530 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
535 // Allocate the ResultsData buffer
537 ResultsData
= AllocateZeroPool (ResultsDataSize
);
538 if (ResultsData
== NULL
) {
544 // Retrieve or set the ResultsData from the Browser Callback
546 Status
= mUefiFormBrowser2
->BrowserCallback (
550 (BOOLEAN
)(SetResultsData
== NULL
),
554 if (EFI_ERROR (Status
)) {
562 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing
563 information that includes a GUID, an optional Unicode string name, and a device
564 path. The string returned is allocated with AllocatePool(). The caller is
565 responsible for freeing the allocated string with FreePool().
567 The format of a <ConfigHdr> is as follows:
569 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
571 @param[in] Guid Pointer to an EFI_GUID that is the routing information
572 GUID. Each of the 16 bytes in Guid is converted to
573 a 2 Unicode character hexidecimal string. This is
574 an optional parameter that may be NULL.
575 @param[in] Name Pointer to a Null-terminated Unicode string that is
576 the routing information NAME. This is an optional
577 parameter that may be NULL. Each 16-bit Unicode
578 character in Name is converted to a 4 character Unicode
580 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
581 that is the routing information PATH. Each byte of
582 the Device Path associated with DriverHandle is converted
583 to a 2 Unicode character hexidecimal string.
585 @retval NULL DriverHandle does not support the Device Path Protocol.
586 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
591 HiiConstructConfigHdr (
592 IN CONST EFI_GUID
*Guid
, OPTIONAL
593 IN CONST CHAR16
*Name
, OPTIONAL
594 IN EFI_HANDLE DriverHandle
598 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
599 UINTN DevicePathSize
;
601 CHAR16
*ReturnString
;
606 // Compute the length of Name in Unicode characters.
607 // If Name is NULL, then the length is 0.
611 NameLength
= StrLen (Name
);
617 // Retrieve DevicePath Protocol associated with DriverHandle
619 if (DriverHandle
!= NULL
) {
620 DevicePath
= DevicePathFromHandle (DriverHandle
);
621 if (DevicePath
== NULL
) {
625 // Compute the size of the device path in bytes
627 DevicePathSize
= GetDevicePathSize (DevicePath
);
631 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
632 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
634 String
= AllocateZeroPool ((5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
));
635 if (String
== NULL
) {
640 // Start with L"GUID="
642 ReturnString
= StrCpy (String
, L
"GUID=");
643 String
+= StrLen (String
);
647 // Append Guid converted to <HexCh>32
649 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
650 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
657 StrCpy (String
, L
"&NAME=");
658 String
+= StrLen (String
);
662 // Append Name converted to <Char>NameLength
664 for (; *Name
!= L
'\0'; Name
++) {
665 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *Name
, 4);
672 StrCpy (String
, L
"&PATH=");
673 String
+= StrLen (String
);
676 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
678 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
679 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
683 // Null terminate the Unicode string
688 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
690 return InternalHiiLowerConfigString (ReturnString
);
694 Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path
695 to binary buffer from <ConfigHdr>.
697 This is a internal function.
699 @param String UEFI configuration string.
700 @param Flag Flag specifies what type buffer will be retrieved.
701 @param Buffer Binary of Guid, Name or Device path.
703 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
704 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
705 @retval EFI_SUCCESS The buffer data is retrieved and translated to
710 InternalHiiGetBufferFromString (
711 IN EFI_STRING String
,
717 EFI_STRING ConfigHdr
;
724 if (String
== NULL
|| Buffer
== NULL
) {
725 return EFI_INVALID_PARAMETER
;
732 // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element
733 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.
735 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
738 case GUID_CONFIG_STRING_TYPE
:
739 case PATH_CONFIG_STRING_TYPE
:
741 // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order
742 // as the device path and Guid resides in RAM memory.
743 // Translate the data into binary.
745 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
746 if (DataBuffer
== NULL
) {
747 return EFI_OUT_OF_RESOURCES
;
750 // Convert binary byte one by one
752 ZeroMem (TemStr
, sizeof (TemStr
));
753 for (Index
= 0; Index
< Length
; Index
++) {
754 TemStr
[0] = ConfigHdr
[Index
];
755 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
756 if ((Index
& 1) == 0) {
757 DataBuffer
[Index
/2] = DigitUint8
;
759 DataBuffer
[Index
/2] = (UINT8
) ((DataBuffer
[Index
/2] << 4) + DigitUint8
);
763 *Buffer
= DataBuffer
;
766 case NAME_CONFIG_STRING_TYPE
:
768 // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"
772 // Add the tailling char L'\0'
774 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
/4 + 1) * sizeof (CHAR16
));
775 if (DataBuffer
== NULL
) {
776 return EFI_OUT_OF_RESOURCES
;
779 // Convert character one by one
781 StringPtr
= (CHAR16
*) DataBuffer
;
782 ZeroMem (TemStr
, sizeof (TemStr
));
783 for (Index
= 0; Index
< Length
; Index
+= 4) {
784 StrnCpy (TemStr
, ConfigHdr
+ Index
, 4);
785 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
788 // Add tailing L'\0' character
790 StringPtr
[Index
/4] = L
'\0';
792 *Buffer
= DataBuffer
;
796 return EFI_INVALID_PARAMETER
;
804 This function checks VarOffset and VarWidth is in the block range.
806 @param BlockArray The block array is to be checked.
807 @param VarOffset Offset of var to the structure
808 @param VarWidth Width of var.
810 @retval TRUE This Var is in the block range.
811 @retval FALSE This Var is not in the block range.
815 IN IFR_BLOCK_DATA
*BlockArray
,
821 IFR_BLOCK_DATA
*BlockData
;
824 // No Request Block array, all vars are got.
826 if (BlockArray
== NULL
) {
831 // Check the input var is in the request block range.
833 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
834 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
835 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
844 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
846 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
848 @param ValueString String in <BlockConfig> format and points to the
849 first character of <Number>.
850 @param ValueData The output value. Caller takes the responsibility
852 @param ValueLength Length of the <Number>, in characters.
854 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
856 @retval EFI_SUCCESS Value of <Number> is outputted in Number
862 InternalHiiGetValueOfNumber (
863 IN EFI_STRING ValueString
,
864 OUT UINT8
**ValueData
,
865 OUT UINTN
*ValueLength
868 EFI_STRING StringPtr
;
875 ASSERT (ValueString
!= NULL
&& ValueData
!= NULL
&& ValueLength
!= NULL
);
876 ASSERT (*ValueString
!= L
'\0');
879 // Get the length of value string
881 StringPtr
= ValueString
;
882 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
885 Length
= StringPtr
- ValueString
;
888 // Allocate buffer to store the value
890 Buf
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
892 return EFI_OUT_OF_RESOURCES
;
896 // Convert character one by one to the value buffer
898 ZeroMem (TemStr
, sizeof (TemStr
));
899 for (Index
= 0; Index
< Length
; Index
++) {
900 TemStr
[0] = ValueString
[Length
- Index
- 1];
901 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
902 if ((Index
& 1) == 0) {
903 Buf
[Index
/2] = DigitUint8
;
905 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
910 // Set the converted value and string length.
913 *ValueLength
= Length
;
918 This internal function parses IFR data to validate current setting.
920 @param ConfigResp ConfigResp string contains the current setting.
921 @param HiiPackageList Point to Hii package list.
922 @param PackageListLength The length of the pacakge.
923 @param VarGuid Guid of the buffer storage.
924 @param VarName Name of the buffer storage.
926 @retval EFI_SUCCESS The current setting is valid.
927 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
928 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
932 InternalHiiValidateCurrentSetting (
933 IN EFI_STRING ConfigResp
,
934 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
935 IN UINTN PackageListLength
,
936 IN EFI_GUID
*VarGuid
,
940 IFR_BLOCK_DATA
*CurrentBlockArray
;
941 IFR_BLOCK_DATA
*BlockData
;
942 IFR_BLOCK_DATA
*NewBlockData
;
943 IFR_BLOCK_DATA VarBlockData
;
944 EFI_STRING StringPtr
;
954 EFI_HII_PACKAGE_HEADER PacakgeHeader
;
955 UINT32 PackageOffset
;
958 EFI_IFR_OP_HEADER
*IfrOpHdr
;
959 EFI_IFR_VARSTORE
*IfrVarStore
;
960 EFI_IFR_ONE_OF
*IfrOneOf
;
961 EFI_IFR_NUMERIC
*IfrNumeric
;
962 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
963 EFI_IFR_CHECKBOX
*IfrCheckBox
;
964 EFI_IFR_STRING
*IfrString
;
969 // 1. Get the current setting to current block data array and Convert them into VarBuffer
973 // Skip ConfigHdr string
975 StringPtr
= ConfigResp
;
976 StringPtr
= StrStr (ConfigResp
, L
"&OFFSET");
977 if (StringPtr
== NULL
) {
979 // No ConfigBlock value is required to be validated.
980 // EFI_SUCCESS directly return.
986 // Initialize the local variables.
990 Status
= EFI_SUCCESS
;
994 MaxBufferSize
= HII_LIB_DEFAULT_VARSTORE_SIZE
;
995 VarBuffer
= AllocateZeroPool (MaxBufferSize
);
996 if (VarBuffer
== NULL
) {
997 return EFI_OUT_OF_RESOURCES
;
1001 // Init CurrentBlockArray
1003 CurrentBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1004 if (CurrentBlockArray
== NULL
) {
1005 Status
= EFI_OUT_OF_RESOURCES
;
1008 InitializeListHead (&CurrentBlockArray
->Entry
);
1011 // Parse each <RequestElement> if exists
1012 // Only <BlockName> format is supported by this help function.
1013 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1015 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1017 // Skip the &OFFSET= string
1019 StringPtr
+= StrLen (L
"&OFFSET=");
1024 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1025 if (EFI_ERROR (Status
)) {
1032 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1034 FreePool (TmpBuffer
);
1037 StringPtr
+= Length
;
1038 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1039 Status
= EFI_INVALID_PARAMETER
;
1042 StringPtr
+= StrLen (L
"&WIDTH=");
1047 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1048 if (EFI_ERROR (Status
)) {
1055 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1057 FreePool (TmpBuffer
);
1060 StringPtr
+= Length
;
1061 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1062 Status
= EFI_INVALID_PARAMETER
;
1066 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1067 Status
= EFI_INVALID_PARAMETER
;
1070 StringPtr
+= StrLen (L
"&VALUE=");
1075 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1076 if (EFI_ERROR (Status
)) {
1080 StringPtr
+= Length
;
1081 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1082 Status
= EFI_INVALID_PARAMETER
;
1087 // Check whether VarBuffer is enough
1089 if ((UINTN
) (Offset
+ Width
) > MaxBufferSize
) {
1090 VarBuffer
= ReallocatePool (
1092 Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
,
1095 if (VarBuffer
== NULL
) {
1096 Status
= EFI_OUT_OF_RESOURCES
;
1099 MaxBufferSize
= Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
;
1103 // Update the Block with configuration info
1105 CopyMem (VarBuffer
+ Offset
, TmpBuffer
, Width
);
1106 FreePool (TmpBuffer
);
1110 // Set new Block Data
1112 NewBlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1113 if (NewBlockData
== NULL
) {
1114 Status
= EFI_OUT_OF_RESOURCES
;
1117 NewBlockData
->Offset
= Offset
;
1118 NewBlockData
->Width
= Width
;
1121 // Insert the new block data into the block data array.
1123 for (Link
= CurrentBlockArray
->Entry
.ForwardLink
; Link
!= &CurrentBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1124 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1125 if (NewBlockData
->Offset
== BlockData
->Offset
) {
1126 if (NewBlockData
->Width
> BlockData
->Width
) {
1127 BlockData
->Width
= NewBlockData
->Width
;
1129 FreePool (NewBlockData
);
1131 } else if (NewBlockData
->Offset
< BlockData
->Offset
) {
1133 // Insert new block data as the previous one of this link.
1135 InsertTailList (Link
, &NewBlockData
->Entry
);
1141 // Insert new block data into the array tail.
1143 if (Link
== &CurrentBlockArray
->Entry
) {
1144 InsertTailList (Link
, &NewBlockData
->Entry
);
1148 // If '\0', parsing is finished.
1150 if (*StringPtr
== 0) {
1154 // Go to next ConfigBlock
1159 // Merge the aligned block data into the single block data.
1161 Link
= CurrentBlockArray
->Entry
.ForwardLink
;
1162 while ((Link
!= &CurrentBlockArray
->Entry
) && (Link
->ForwardLink
!= &CurrentBlockArray
->Entry
)) {
1163 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1164 NewBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1165 if ((NewBlockData
->Offset
>= BlockData
->Offset
) && (NewBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1166 if ((NewBlockData
->Offset
+ NewBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1167 BlockData
->Width
= (UINT16
) (NewBlockData
->Offset
+ NewBlockData
->Width
- BlockData
->Offset
);
1169 RemoveEntryList (Link
->ForwardLink
);
1170 FreePool (NewBlockData
);
1173 Link
= Link
->ForwardLink
;
1176 if (IsListEmpty (&CurrentBlockArray
->Entry
)) {
1177 Status
= EFI_SUCCESS
;
1182 // 2. Check IFR value is in block data, then Validate Value
1184 ZeroMem (&VarBlockData
, sizeof (VarBlockData
));
1187 PackageOffset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1188 while (PackageOffset
< PackageListLength
) {
1189 CopyMem (&PacakgeHeader
, (UINT8
*) HiiPackageList
+ PackageOffset
, sizeof (PacakgeHeader
));
1192 // Parse IFR opcode from the form package.
1194 if (PacakgeHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1195 IfrOffset
= sizeof (PacakgeHeader
);
1196 PackageData
= (UINT8
*) HiiPackageList
+ PackageOffset
;
1197 while (IfrOffset
< PacakgeHeader
.Length
) {
1198 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (PackageData
+ IfrOffset
);
1200 // Validate current setting to the value built in IFR opcode
1202 switch (IfrOpHdr
->OpCode
) {
1203 case EFI_IFR_VARSTORE_OP
:
1205 // VarStoreId has been found. No further found.
1207 if (IfrVarStore
!= NULL
) {
1211 // Find the matched VarStoreId to the input VarGuid and VarName
1213 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1214 if (CompareGuid ((EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
, VarGuid
)) {
1215 VarStoreName
= (CHAR8
*) IfrVarStore
->Name
;
1216 for (Index
= 0; VarStoreName
[Index
] != 0; Index
++) {
1217 if ((CHAR16
) VarStoreName
[Index
] != VarName
[Index
]) {
1222 // The matched VarStore is found.
1224 if ((VarStoreName
[Index
] != 0) || (VarName
[Index
] != 0)) {
1231 case EFI_IFR_FORM_OP
:
1232 case EFI_IFR_FORM_MAP_OP
:
1234 // Check the matched VarStoreId is found.
1236 if (IfrVarStore
== NULL
) {
1237 Status
= EFI_SUCCESS
;
1241 case EFI_IFR_ONE_OF_OP
:
1243 // Check whether current value is the one of option.
1247 // OneOf question is not in IFR Form. This IFR form is not valid.
1249 if (IfrVarStore
== NULL
) {
1250 Status
= EFI_INVALID_PARAMETER
;
1254 // Check whether this question is for the requested varstore.
1256 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1257 if (IfrOneOf
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1262 // Get Offset by Question header and Width by DataType Flags
1264 Offset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1265 Width
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1267 // Check whether this question is in current block array.
1269 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1271 // This question is not in the current configuration string. Skip it.
1276 // Check this var question is in the var storage
1278 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1280 // This question exceeds the var store size.
1282 Status
= EFI_INVALID_PARAMETER
;
1287 // Get the current value for oneof opcode
1290 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1292 // Set Block Data, to be checked in the following Oneof option opcode.
1294 VarBlockData
.Offset
= Offset
;
1295 VarBlockData
.Width
= Width
;
1296 VarBlockData
.OpCode
= IfrOpHdr
->OpCode
;
1297 VarBlockData
.Scope
= IfrOpHdr
->Scope
;
1299 case EFI_IFR_NUMERIC_OP
:
1301 // Check the current value is in the numeric range.
1305 // Numeric question is not in IFR Form. This IFR form is not valid.
1307 if (IfrVarStore
== NULL
) {
1308 Status
= EFI_INVALID_PARAMETER
;
1312 // Check whether this question is for the requested varstore.
1314 IfrNumeric
= (EFI_IFR_NUMERIC
*) IfrOpHdr
;
1315 if (IfrNumeric
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1320 // Get Offset by Question header and Width by DataType Flags
1322 Offset
= IfrNumeric
->Question
.VarStoreInfo
.VarOffset
;
1323 Width
= (UINT16
) (1 << (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1325 // Check whether this question is in current block array.
1327 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1329 // This question is not in the current configuration string. Skip it.
1334 // Check this var question is in the var storage
1336 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1338 // This question exceeds the var store size.
1340 Status
= EFI_INVALID_PARAMETER
;
1345 // Check the current value is in the numeric range.
1348 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1349 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1350 case EFI_IFR_NUMERIC_SIZE_1
:
1351 if ((UINT8
) VarValue
< IfrNumeric
->data
.u8
.MinValue
|| (UINT8
) VarValue
> IfrNumeric
->data
.u8
.MaxValue
) {
1353 // Not in the valid range.
1355 Status
= EFI_INVALID_PARAMETER
;
1359 case EFI_IFR_NUMERIC_SIZE_2
:
1360 if ((UINT16
) VarValue
< IfrNumeric
->data
.u16
.MinValue
|| (UINT16
) VarValue
> IfrNumeric
->data
.u16
.MaxValue
) {
1362 // Not in the valid range.
1364 Status
= EFI_INVALID_PARAMETER
;
1368 case EFI_IFR_NUMERIC_SIZE_4
:
1369 if ((UINT32
) VarValue
< IfrNumeric
->data
.u32
.MinValue
|| (UINT32
) VarValue
> IfrNumeric
->data
.u32
.MaxValue
) {
1371 // Not in the valid range.
1373 Status
= EFI_INVALID_PARAMETER
;
1377 case EFI_IFR_NUMERIC_SIZE_8
:
1378 if ((UINT64
) VarValue
< IfrNumeric
->data
.u64
.MinValue
|| (UINT64
) VarValue
> IfrNumeric
->data
.u64
.MaxValue
) {
1380 // Not in the valid range.
1382 Status
= EFI_INVALID_PARAMETER
;
1389 case EFI_IFR_CHECKBOX_OP
:
1391 // Check value is BOOLEAN type, only 0 and 1 is valid.
1395 // CheckBox question is not in IFR Form. This IFR form is not valid.
1397 if (IfrVarStore
== NULL
) {
1398 Status
= EFI_INVALID_PARAMETER
;
1403 // Check whether this question is for the requested varstore.
1405 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1406 if (IfrCheckBox
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1411 // Get Offset by Question header
1413 Offset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1414 Width
= (UINT16
) sizeof (BOOLEAN
);
1416 // Check whether this question is in current block array.
1418 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1420 // This question is not in the current configuration string. Skip it.
1425 // Check this var question is in the var storage
1427 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1429 // This question exceeds the var store size.
1431 Status
= EFI_INVALID_PARAMETER
;
1436 // Boolean type, only 1 and 0 is valid.
1438 if (*(VarBuffer
+ Offset
) > 1) {
1439 Status
= EFI_INVALID_PARAMETER
;
1444 case EFI_IFR_STRING_OP
:
1446 // Check current string length is less than maxsize
1450 // CheckBox question is not in IFR Form. This IFR form is not valid.
1452 if (IfrVarStore
== NULL
) {
1453 Status
= EFI_INVALID_PARAMETER
;
1458 // Check whether this question is for the requested varstore.
1460 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1461 if (IfrString
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1466 // Get Offset/Width by Question header and OneOf Flags
1468 Offset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1469 Width
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1471 // Check whether this question is in current block array.
1473 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1475 // This question is not in the current configuration string. Skip it.
1480 // Check this var question is in the var storage
1482 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1484 // This question exceeds the var store size.
1486 Status
= EFI_INVALID_PARAMETER
;
1491 // Check current string length is less than maxsize
1493 if (StrSize ((CHAR16
*) (VarBuffer
+ Offset
)) > Width
) {
1494 Status
= EFI_INVALID_PARAMETER
;
1498 case EFI_IFR_ONE_OF_OPTION_OP
:
1500 // Opcode Scope is zero. This one of option is not to be checked.
1502 if (VarBlockData
.Scope
== 0) {
1507 // Only check for OneOf and OrderList opcode
1509 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1510 if (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
) {
1512 // Check current value is the value of one of option.
1514 if (VarValue
== IfrOneOfOption
->Value
.u64
) {
1516 // The value is one of option value.
1517 // Set OpCode to Zero, don't need check again.
1519 VarBlockData
.OpCode
= 0;
1524 case EFI_IFR_END_OP
:
1526 // Decrease opcode scope for the validated opcode
1528 if (VarBlockData
.Scope
> 0) {
1529 VarBlockData
.Scope
--;
1533 // OneOf value doesn't belong to one of option value.
1535 if ((VarBlockData
.Scope
== 0) && (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
)) {
1536 Status
= EFI_INVALID_PARAMETER
;
1542 // Increase Scope for the validated opcode
1544 if (VarBlockData
.Scope
> 0) {
1545 VarBlockData
.Scope
= (UINT8
) (VarBlockData
.Scope
+ IfrOpHdr
->Scope
);
1550 // Go to the next opcode
1552 IfrOffset
+= IfrOpHdr
->Length
;
1555 // Only one form is in a package list.
1561 // Go to next package.
1563 PackageOffset
+= PacakgeHeader
.Length
;
1567 if (VarBuffer
!= NULL
) {
1568 FreePool (VarBuffer
);
1571 if (CurrentBlockArray
!= NULL
) {
1573 // Free Link Array CurrentBlockArray
1575 while (!IsListEmpty (&CurrentBlockArray
->Entry
)) {
1576 BlockData
= BASE_CR (CurrentBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1577 RemoveEntryList (&BlockData
->Entry
);
1578 FreePool (BlockData
);
1580 FreePool (CurrentBlockArray
);
1587 This function parses the input ConfigRequest string and its matched IFR code
1588 string for setting default value and validating current setting.
1590 1. For setting default action, Reset the default value specified by DefaultId
1591 to the driver configuration got by Request string.
1592 2. For validating current setting, Validate the current configuration
1593 by parsing HII form IFR opcode.
1595 NULL request string support depends on the ExportConfig interface of
1596 HiiConfigRouting protocol in UEFI specification.
1598 @param Request A null-terminated Unicode string in
1599 <MultiConfigRequest> format. It can be NULL.
1600 If it is NULL, all current configuration for the
1601 entirety of the current HII database will be validated.
1602 If it is NULL, all configuration for the
1603 entirety of the current HII database will be reset.
1604 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.
1605 @param ActionType Action supports setting defaults and validate current setting.
1607 @retval TURE Action runs successfully.
1608 @retval FALSE Action is not valid or Action can't be executed successfully..
1612 InternalHiiIfrValueAction (
1613 IN CONST EFI_STRING Request
, OPTIONAL
1614 IN UINT16 DefaultId
,
1618 EFI_STRING ConfigAltResp
;
1619 EFI_STRING ConfigAltHdr
;
1620 EFI_STRING ConfigResp
;
1621 EFI_STRING Progress
;
1622 EFI_STRING StringPtr
;
1623 EFI_STRING StringHdr
;
1625 EFI_HANDLE DriverHandle
;
1626 EFI_HANDLE TempDriverHandle
;
1627 EFI_HII_HANDLE
*HiiHandleBuffer
;
1628 EFI_HII_HANDLE HiiHandle
;
1634 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1635 UINTN PackageListLength
;
1636 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1637 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1639 ConfigAltResp
= NULL
;
1644 ConfigAltHdr
= NULL
;
1645 HiiHandleBuffer
= NULL
;
1647 TempDriverHandle
= NULL
;
1650 HiiPackageList
= NULL
;
1653 // Only support set default and validate setting action.
1655 if ((ActionType
!= ACTION_SET_DEFAUTL_VALUE
) && (ActionType
!= ACTION_VALIDATE_SETTING
)) {
1660 // Get the full requested value and deault value string.
1662 if (Request
!= NULL
) {
1663 Status
= gHiiConfigRouting
->ExtractConfig (
1670 Status
= gHiiConfigRouting
->ExportConfig (
1676 if (EFI_ERROR (Status
)) {
1680 StringPtr
= ConfigAltResp
;
1682 while (StringPtr
!= L
'\0') {
1684 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1686 StringHdr
= StringPtr
;
1691 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1692 Status
= EFI_INVALID_PARAMETER
;
1695 StringPtr
+= StrLen (L
"GUID=");
1696 Status
= InternalHiiGetBufferFromString (StringPtr
, GUID_CONFIG_STRING_TYPE
, (UINT8
**) &VarGuid
);
1697 if (EFI_ERROR (Status
)) {
1702 // Get Name value VarName
1704 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1707 if (*StringPtr
== L
'\0') {
1708 Status
= EFI_INVALID_PARAMETER
;
1711 StringPtr
+= StrLen (L
"&NAME=");
1712 Status
= InternalHiiGetBufferFromString (StringPtr
, NAME_CONFIG_STRING_TYPE
, (UINT8
**) &VarName
);
1713 if (EFI_ERROR (Status
)) {
1718 // Get Path value DevicePath
1720 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1723 if (*StringPtr
== L
'\0') {
1724 Status
= EFI_INVALID_PARAMETER
;
1727 StringPtr
+= StrLen (L
"&PATH=");
1728 Status
= InternalHiiGetBufferFromString (StringPtr
, PATH_CONFIG_STRING_TYPE
, (UINT8
**) &DevicePath
);
1729 if (EFI_ERROR (Status
)) {
1734 // Get the Driver handle by the got device path.
1736 TempDevicePath
= DevicePath
;
1737 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDevicePath
, &DriverHandle
);
1738 if (EFI_ERROR (Status
)) {
1743 // Find the matched Hii Handle for the found Driver handle
1745 HiiHandleBuffer
= HiiGetHiiHandles (NULL
);
1746 if (HiiHandleBuffer
== NULL
) {
1747 Status
= EFI_NOT_FOUND
;
1751 for (Index
= 0; HiiHandleBuffer
[Index
] != NULL
; Index
++) {
1752 gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, HiiHandleBuffer
[Index
], &TempDriverHandle
);
1753 if (TempDriverHandle
== DriverHandle
) {
1758 HiiHandle
= HiiHandleBuffer
[Index
];
1759 FreePool (HiiHandleBuffer
);
1761 if (HiiHandle
== NULL
) {
1763 // This request string has no its Hii package.
1764 // Its default value and validating can't execute by parsing IFR data.
1765 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
1767 Status
= EFI_SUCCESS
;
1768 goto NextConfigAltResp
;
1772 // 2. Get HiiPackage by HiiHandle
1774 PackageListLength
= 0;
1775 HiiPackageList
= NULL
;
1776 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
1779 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
1781 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1782 Status
= EFI_INVALID_PARAMETER
;
1786 HiiPackageList
= AllocatePool (PackageListLength
);
1787 if (HiiPackageList
== NULL
) {
1788 Status
= EFI_OUT_OF_RESOURCES
;
1793 // Get PackageList on HiiHandle
1795 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
1796 if (EFI_ERROR (Status
)) {
1801 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
1802 // Get the default configuration string according to the default ID.
1804 Status
= gHiiConfigRouting
->GetAltConfig (
1810 (ActionType
== ACTION_SET_DEFAUTL_VALUE
) ? &DefaultId
:NULL
, // it can be NULL to get the current setting.
1815 // The required setting can't be found. So, it is not required to be validated and set.
1817 if (EFI_ERROR (Status
)) {
1818 Status
= EFI_SUCCESS
;
1819 goto NextConfigAltResp
;
1822 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
1824 if (StrStr (ConfigResp
, L
"&OFFSET=") == NULL
) {
1825 goto NextConfigAltResp
;
1829 // 4. Set the default configuration information or Validate current setting by parse IFR code.
1830 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
1832 if (ActionType
== ACTION_SET_DEFAUTL_VALUE
) {
1834 // Set the default configuration information.
1836 Status
= gHiiConfigRouting
->RouteConfig (gHiiConfigRouting
, ConfigResp
, &Progress
);
1839 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
1841 Status
= InternalHiiValidateCurrentSetting (ConfigResp
, HiiPackageList
, PackageListLength
, VarGuid
, VarName
);
1844 if (EFI_ERROR (Status
)) {
1850 // Free the allocated pacakge buffer and the got ConfigResp string.
1852 if (HiiPackageList
!= NULL
) {
1853 FreePool (HiiPackageList
);
1854 HiiPackageList
= NULL
;
1857 if (ConfigResp
!= NULL
) {
1858 FreePool (ConfigResp
);
1863 // Free the allocated buffer.
1871 FreePool (DevicePath
);
1875 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
1879 // Get and Skip ConfigHdr
1881 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1884 if (*StringPtr
== L
'\0') {
1889 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"
1890 // | 1 | StrLen (ConfigHdr) | 8 | 1 |
1892 ConfigAltHdr
= AllocateZeroPool ((1 + StringPtr
- StringHdr
+ 8 + 1) * sizeof (CHAR16
));
1893 if (ConfigAltHdr
== NULL
) {
1894 Status
= EFI_OUT_OF_RESOURCES
;
1897 StrCpy (ConfigAltHdr
, L
"&");
1898 StrnCat (ConfigAltHdr
, StringHdr
, StringPtr
- StringHdr
);
1899 StrCat (ConfigAltHdr
, L
"&ALTCFG=");
1902 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
1904 while ((StringHdr
= StrStr (StringPtr
, ConfigAltHdr
)) != NULL
) {
1905 StringPtr
= StringHdr
+ StrLen (ConfigAltHdr
);
1906 if (*StringPtr
== L
'\0') {
1912 // Free the allocated ConfigAltHdr string
1914 FreePool (ConfigAltHdr
);
1915 if (*StringPtr
== L
'\0') {
1920 // Find &GUID as the next ConfigHdr
1922 StringPtr
= StrStr (StringPtr
, L
"&GUID");
1923 if (StringPtr
== NULL
) {
1934 if (VarGuid
!= NULL
) {
1938 if (VarName
!= NULL
) {
1942 if (DevicePath
!= NULL
) {
1943 FreePool (DevicePath
);
1946 if (ConfigResp
!= NULL
) {
1947 FreePool (ConfigResp
);
1950 if (ConfigAltResp
!= NULL
) {
1951 FreePool (ConfigAltResp
);
1954 if (HiiPackageList
!= NULL
) {
1955 FreePool (HiiPackageList
);
1958 if (EFI_ERROR (Status
)) {
1966 Validate the current configuration by parsing HII form IFR opcode.
1968 NULL request string support depends on the ExportConfig interface of
1969 HiiConfigRouting protocol in UEFI specification.
1971 @param Request A null-terminated Unicode string in
1972 <MultiConfigRequest> format. It can be NULL.
1973 If it is NULL, all current configuration for the
1974 entirety of the current HII database will be validated.
1976 @retval TRUE Current configuration is valid.
1977 @retval FALSE Current configuration is invalid.
1981 HiiValidateSettings (
1982 IN CONST EFI_STRING Request OPTIONAL
1985 return InternalHiiIfrValueAction (Request
, 0, ACTION_VALIDATE_SETTING
);
1989 Reset the default value specified by DefaultId to the driver
1990 configuration got by Request string.
1992 NULL request string support depends on the ExportConfig interface of
1993 HiiConfigRouting protocol in UEFI specification.
1995 @param Request A null-terminated Unicode string in
1996 <MultiConfigRequest> format. It can be NULL.
1997 If it is NULL, all configuration for the
1998 entirety of the current HII database will be reset.
1999 @param DefaultId Specifies the type of defaults to retrieve.
2001 @retval TURE The default value is set successfully.
2002 @retval FALSE The default value can't be found and set.
2007 IN CONST EFI_STRING Request
, OPTIONAL
2011 return InternalHiiIfrValueAction (Request
, DefaultId
, ACTION_SET_DEFAUTL_VALUE
);
2015 Determines if two values in config strings match.
2017 Compares the substring between StartSearchString and StopSearchString in
2018 FirstString to the substring between StartSearchString and StopSearchString
2019 in SecondString. If the two substrings match, then TRUE is returned. If the
2020 two substrings do not match, then FALSE is returned.
2022 If FirstString is NULL, then ASSERT().
2023 If SecondString is NULL, then ASSERT().
2024 If StartSearchString is NULL, then ASSERT().
2025 If StopSearchString is NULL, then ASSERT().
2027 @param FirstString Pointer to the first Null-terminated Unicode string.
2028 @param SecondString Pointer to the second Null-terminated Unicode string.
2029 @param StartSearchString Pointer to the Null-terminated Unicode string that
2030 marks the start of the value string to compare.
2031 @param StopSearchString Pointer to the Null-terminated Unicode string that
2032 marks the end of the value string to compare.
2034 @retval FALSE StartSearchString is not present in FirstString.
2035 @retval FALSE StartSearchString is not present in SecondString.
2036 @retval FALSE StopSearchString is not present in FirstString.
2037 @retval FALSE StopSearchString is not present in SecondString.
2038 @retval FALSE The length of the substring in FirstString is not the
2039 same length as the substring in SecondString.
2040 @retval FALSE The value string in FirstString does not matche the
2041 value string in SecondString.
2042 @retval TRUE The value string in FirstString matches the value
2043 string in SecondString.
2048 InternalHiiCompareSubString (
2049 IN CHAR16
*FirstString
,
2050 IN CHAR16
*SecondString
,
2051 IN CHAR16
*StartSearchString
,
2052 IN CHAR16
*StopSearchString
2055 CHAR16
*EndFirstString
;
2056 CHAR16
*EndSecondString
;
2058 ASSERT (FirstString
!= NULL
);
2059 ASSERT (SecondString
!= NULL
);
2060 ASSERT (StartSearchString
!= NULL
);
2061 ASSERT (StopSearchString
!= NULL
);
2063 FirstString
= StrStr (FirstString
, StartSearchString
);
2064 if (FirstString
== NULL
) {
2068 SecondString
= StrStr (SecondString
, StartSearchString
);
2069 if (SecondString
== NULL
) {
2073 EndFirstString
= StrStr (FirstString
, StopSearchString
);
2074 if (EndFirstString
== NULL
) {
2078 EndSecondString
= StrStr (SecondString
, StopSearchString
);
2079 if (EndSecondString
== NULL
) {
2083 if ((EndFirstString
- FirstString
) != (EndSecondString
- SecondString
)) {
2087 return (BOOLEAN
)(StrnCmp (FirstString
, SecondString
, EndFirstString
- FirstString
) == 0);
2091 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
2093 If ConfigHdr is NULL, then ASSERT().
2095 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
2096 @param[in] Guid GUID of the storage.
2097 @param[in] Name NAME of the storage.
2099 @retval TRUE Routing information matches <ConfigHdr>.
2100 @retval FALSE Routing information does not match <ConfigHdr>.
2105 HiiIsConfigHdrMatch (
2106 IN CONST EFI_STRING ConfigHdr
,
2107 IN CONST EFI_GUID
*Guid
, OPTIONAL
2108 IN CONST CHAR16
*Name OPTIONAL
2111 EFI_STRING CompareConfigHdr
;
2114 ASSERT (ConfigHdr
!= NULL
);
2117 // Use Guid and Name to generate a <ConfigHdr> string
2119 CompareConfigHdr
= HiiConstructConfigHdr (Guid
, Name
, NULL
);
2120 if (CompareConfigHdr
== NULL
) {
2127 // Compare GUID value strings
2129 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"GUID=", L
"&NAME=");
2132 if (Result
&& Name
!= NULL
) {
2134 // Compare NAME value strings
2136 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"&NAME=", L
"&PATH=");
2140 // Free the <ConfigHdr> string
2142 FreePool (CompareConfigHdr
);
2148 Retrieves uncommitted data from the Form Browser and converts it to a binary
2151 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2152 parameter that may be NULL.
2153 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2154 is an optional parameter that may be NULL.
2155 @param[in] BufferSize Length in bytes of buffer to hold retrieved data.
2156 @param[out] Buffer Buffer of data to be updated.
2158 @retval FALSE The uncommitted data could not be retrieved.
2159 @retval TRUE The uncommitted data was retrieved.
2165 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2166 IN CONST CHAR16
*VariableName
, OPTIONAL
2167 IN UINTN BufferSize
,
2171 EFI_STRING ResultsData
;
2173 EFI_STRING ConfigResp
;
2178 // Retrieve the results data from the Browser Callback
2180 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, NULL
);
2181 if (ResultsData
== NULL
) {
2186 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
2188 Size
= (StrLen (mConfigHdrTemplate
) + 1) * sizeof (CHAR16
);
2189 Size
= Size
+ (StrLen (ResultsData
) + 1) * sizeof (CHAR16
);
2190 ConfigResp
= AllocateZeroPool (Size
);
2191 UnicodeSPrint (ConfigResp
, Size
, L
"%s&%s", mConfigHdrTemplate
, ResultsData
);
2194 // Free the allocated buffer
2196 FreePool (ResultsData
);
2197 if (ConfigResp
== NULL
) {
2202 // Convert <ConfigResp> to a buffer
2204 Status
= gHiiConfigRouting
->ConfigToBlock (
2212 // Free the allocated buffer
2214 FreePool (ConfigResp
);
2216 if (EFI_ERROR (Status
)) {
2224 Updates uncommitted data in the Form Browser.
2226 If Buffer is NULL, then ASSERT().
2228 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2229 parameter that may be NULL.
2230 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2231 is an optional parameter that may be NULL.
2232 @param[in] BufferSize Length, in bytes, of Buffer.
2233 @param[in] Buffer Buffer of data to commit.
2234 @param[in] RequestElement An optional field to specify which part of the
2235 buffer data will be send back to Browser. If NULL,
2236 the whole buffer of data will be committed to
2238 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
2240 @retval FALSE The uncommitted data could not be updated.
2241 @retval TRUE The uncommitted data was updated.
2247 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2248 IN CONST CHAR16
*VariableName
, OPTIONAL
2249 IN UINTN BufferSize
,
2250 IN CONST UINT8
*Buffer
,
2251 IN CONST CHAR16
*RequestElement OPTIONAL
2255 EFI_STRING ConfigRequest
;
2256 EFI_STRING ConfigResp
;
2257 EFI_STRING ResultsData
;
2259 ASSERT (Buffer
!= NULL
);
2262 // Construct <ConfigRequest>
2264 if (RequestElement
== NULL
) {
2266 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2267 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2269 Size
= (StrLen (mConfigHdrTemplate
) + 32 + 1) * sizeof (CHAR16
);
2270 ConfigRequest
= AllocateZeroPool (Size
);
2271 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate
, (UINT64
)BufferSize
);
2274 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2275 // followed by <RequestElement> followed by a Null-terminator
2277 Size
= StrLen (mConfigHdrTemplate
) * sizeof (CHAR16
);
2278 Size
= Size
+ (StrLen (RequestElement
) + 1) * sizeof (CHAR16
);
2279 ConfigRequest
= AllocateZeroPool (Size
);
2280 UnicodeSPrint (ConfigRequest
, Size
, L
"%s%s", mConfigHdrTemplate
, RequestElement
);
2282 if (ConfigRequest
== NULL
) {
2287 // Convert <ConfigRequest> to <ConfigResp>
2289 ConfigResp
= InternalHiiBlockToConfig (ConfigRequest
, Buffer
, BufferSize
);
2290 FreePool (ConfigRequest
);
2291 if (ConfigResp
== NULL
) {
2296 // Set data in the uncommitted browser state information
2298 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, ConfigResp
+ StrLen(mConfigHdrTemplate
) + 1);
2299 FreePool (ConfigResp
);
2301 return (BOOLEAN
)(ResultsData
!= NULL
);
2304 /////////////////////////////////////////
2305 /////////////////////////////////////////
2307 /////////////////////////////////////////
2308 /////////////////////////////////////////
2310 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
2316 } HII_LIB_OPCODE_BUFFER
;
2319 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
2321 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth
[] = {
2322 1, // EFI_IFR_TYPE_NUM_SIZE_8
2323 2, // EFI_IFR_TYPE_NUM_SIZE_16
2324 4, // EFI_IFR_TYPE_NUM_SIZE_32
2325 8, // EFI_IFR_TYPE_NUM_SIZE_64
2326 1, // EFI_IFR_TYPE_BOOLEAN
2327 3, // EFI_IFR_TYPE_TIME
2328 4, // EFI_IFR_TYPE_DATE
2329 2 // EFI_IFR_TYPE_STRING
2333 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
2334 HiiFreeOpCodeHandle().
2336 @retval NULL There are not enough resources to allocate a new OpCode Handle.
2337 @retval Other A new OpCode handle.
2342 HiiAllocateOpCodeHandle (
2346 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2348 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER
));
2349 if (OpCodeBuffer
== NULL
) {
2352 OpCodeBuffer
->Buffer
= (UINT8
*)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE
);
2353 if (OpCodeBuffer
->Buffer
== NULL
) {
2354 FreePool (OpCodeBuffer
);
2357 OpCodeBuffer
->BufferSize
= HII_LIB_OPCODE_ALLOCATION_SIZE
;
2358 OpCodeBuffer
->Position
= 0;
2359 return (VOID
*)OpCodeBuffer
;
2363 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
2364 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
2365 Handle are also freed.
2367 If OpCodeHandle is NULL, then ASSERT().
2369 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2374 HiiFreeOpCodeHandle (
2378 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2380 ASSERT (OpCodeHandle
!= NULL
);
2382 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2383 if (OpCodeBuffer
->Buffer
!= NULL
) {
2384 FreePool (OpCodeBuffer
->Buffer
);
2386 FreePool (OpCodeBuffer
);
2390 Internal function gets the current position of opcode buffer.
2392 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2394 @return Current position of opcode buffer.
2398 InternalHiiOpCodeHandlePosition (
2399 IN VOID
*OpCodeHandle
2402 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Position
;
2406 Internal function gets the start pointer of opcode buffer.
2408 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2410 @return Pointer to the opcode buffer base.
2414 InternalHiiOpCodeHandleBuffer (
2415 IN VOID
*OpCodeHandle
2418 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Buffer
;
2422 Internal function reserves the enough buffer for current opcode.
2423 When the buffer is not enough, Opcode buffer will be extended.
2425 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2426 @param[in] Size Size of current opcode.
2428 @return Pointer to the current opcode.
2432 InternalHiiGrowOpCodeHandle (
2433 IN VOID
*OpCodeHandle
,
2437 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2440 ASSERT (OpCodeHandle
!= NULL
);
2442 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2443 if (OpCodeBuffer
->Position
+ Size
> OpCodeBuffer
->BufferSize
) {
2444 Buffer
= ReallocatePool (
2445 OpCodeBuffer
->BufferSize
,
2446 OpCodeBuffer
->BufferSize
+ (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
),
2447 OpCodeBuffer
->Buffer
2449 if (Buffer
== NULL
) {
2452 OpCodeBuffer
->Buffer
= Buffer
;
2453 OpCodeBuffer
->BufferSize
+= (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
);
2455 Buffer
= OpCodeBuffer
->Buffer
+ OpCodeBuffer
->Position
;
2456 OpCodeBuffer
->Position
+= Size
;
2461 Internal function creates opcode based on the template opcode.
2463 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2464 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2465 @param[in] OpCode OpCode IFR value.
2466 @param[in] OpCodeSize Size of opcode.
2467 @param[in] ExtensionSize Size of extended opcode.
2468 @param[in] Scope Scope bit of opcode.
2470 @return Pointer to the current opcode with opcode data.
2474 InternalHiiCreateOpCodeExtended (
2475 IN VOID
*OpCodeHandle
,
2476 IN VOID
*OpCodeTemplate
,
2478 IN UINTN OpCodeSize
,
2479 IN UINTN ExtensionSize
,
2483 EFI_IFR_OP_HEADER
*Header
;
2486 ASSERT (OpCodeTemplate
!= NULL
);
2487 ASSERT ((OpCodeSize
+ ExtensionSize
) <= 0x7F);
2489 Header
= (EFI_IFR_OP_HEADER
*)OpCodeTemplate
;
2490 Header
->OpCode
= OpCode
;
2491 Header
->Scope
= Scope
;
2492 Header
->Length
= (UINT8
)(OpCodeSize
+ ExtensionSize
);
2493 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, Header
->Length
);
2494 return (UINT8
*)CopyMem (Buffer
, Header
, OpCodeSize
);
2498 Internal function creates opcode based on the template opcode for the normal opcode.
2500 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2501 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2502 @param[in] OpCode OpCode IFR value.
2503 @param[in] OpCodeSize Size of opcode.
2505 @return Pointer to the current opcode with opcode data.
2509 InternalHiiCreateOpCode (
2510 IN VOID
*OpCodeHandle
,
2511 IN VOID
*OpCodeTemplate
,
2516 return InternalHiiCreateOpCodeExtended (OpCodeHandle
, OpCodeTemplate
, OpCode
, OpCodeSize
, 0, 0);
2520 Append raw opcodes to an OpCodeHandle.
2522 If OpCodeHandle is NULL, then ASSERT().
2523 If RawBuffer is NULL, then ASSERT();
2525 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2526 @param[in] RawBuffer Buffer of opcodes to append.
2527 @param[in] RawBufferSize The size, in bytes, of Buffer.
2529 @retval NULL There is not enough space left in Buffer to add the opcode.
2530 @retval Other A pointer to the appended opcodes.
2535 HiiCreateRawOpCodes (
2536 IN VOID
*OpCodeHandle
,
2537 IN UINT8
*RawBuffer
,
2538 IN UINTN RawBufferSize
2543 ASSERT (RawBuffer
!= NULL
);
2545 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, RawBufferSize
);
2546 return (UINT8
*)CopyMem (Buffer
, RawBuffer
, RawBufferSize
);
2550 Append opcodes from one OpCode Handle to another OpCode handle.
2552 If OpCodeHandle is NULL, then ASSERT().
2553 If RawOpCodeHandle is NULL, then ASSERT();
2555 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2556 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
2558 @retval NULL There is not enough space left in Buffer to add the opcode.
2559 @retval Other A pointer to the appended opcodes.
2564 InternalHiiAppendOpCodes (
2565 IN VOID
*OpCodeHandle
,
2566 IN VOID
*RawOpCodeHandle
2569 HII_LIB_OPCODE_BUFFER
*RawOpCodeBuffer
;
2571 ASSERT (RawOpCodeHandle
!= NULL
);
2573 RawOpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)RawOpCodeHandle
;
2574 return HiiCreateRawOpCodes (OpCodeHandle
, RawOpCodeBuffer
->Buffer
, RawOpCodeBuffer
->Position
);
2578 Create EFI_IFR_END_OP opcode.
2580 If OpCodeHandle is NULL, then ASSERT().
2582 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2584 @retval NULL There is not enough space left in Buffer to add the opcode.
2585 @retval Other A pointer to the created opcode.
2590 HiiCreateEndOpCode (
2591 IN VOID
*OpCodeHandle
2596 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_END_OP
, sizeof (OpCode
));
2600 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
2602 If OpCodeHandle is NULL, then ASSERT().
2603 If Type is invalid, then ASSERT().
2604 If Flags is invalid, then ASSERT().
2606 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2607 @param[in] StringId StringId for the option
2608 @param[in] Flags Flags for the option
2609 @param[in] Type Type for the option
2610 @param[in] Value Value for the option
2612 @retval NULL There is not enough space left in Buffer to add the opcode.
2613 @retval Other A pointer to the created opcode.
2618 HiiCreateOneOfOptionOpCode (
2619 IN VOID
*OpCodeHandle
,
2626 EFI_IFR_ONE_OF_OPTION OpCode
;
2628 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
2630 ZeroMem (&OpCode
, sizeof (OpCode
));
2631 OpCode
.Option
= StringId
;
2632 OpCode
.Flags
= (UINT8
) (Flags
& (EFI_IFR_OPTION_DEFAULT
| EFI_IFR_OPTION_DEFAULT_MFG
));
2634 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
2636 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OPTION_OP
, sizeof (OpCode
));
2640 Create EFI_IFR_DEFAULT_OP opcode.
2642 If OpCodeHandle is NULL, then ASSERT().
2643 If Type is invalid, then ASSERT().
2645 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2646 @param[in] DefaultId DefaultId for the default
2647 @param[in] Type Type for the default
2648 @param[in] Value Value for the default
2650 @retval NULL There is not enough space left in Buffer to add the opcode.
2651 @retval Other A pointer to the created opcode.
2656 HiiCreateDefaultOpCode (
2657 IN VOID
*OpCodeHandle
,
2658 IN UINT16 DefaultId
,
2663 EFI_IFR_DEFAULT OpCode
;
2665 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
2667 ZeroMem (&OpCode
, sizeof (OpCode
));
2669 OpCode
.DefaultId
= DefaultId
;
2670 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
2672 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DEFAULT_OP
, sizeof (OpCode
));
2676 Create EFI_IFR_GUID opcode.
2678 If OpCodeHandle is NULL, then ASSERT().
2679 If Guid is NULL, then ASSERT().
2680 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
2682 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2683 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
2684 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
2685 optional parameter that may be NULL. If this
2686 parameter is NULL, then the GUID extension
2687 region of the created opcode is filled with zeros.
2688 If this parameter is not NULL, then the GUID
2689 extension region of GuidData will be copied to
2690 the GUID extension region of the created opcode.
2691 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
2692 must be >= sizeof(EFI_IFR_GUID).
2694 @retval NULL There is not enough space left in Buffer to add the opcode.
2695 @retval Other A pointer to the created opcode.
2700 HiiCreateGuidOpCode (
2701 IN VOID
*OpCodeHandle
,
2702 IN CONST EFI_GUID
*Guid
,
2703 IN CONST VOID
*GuidOpCode
, OPTIONAL
2707 EFI_IFR_GUID OpCode
;
2708 EFI_IFR_GUID
*OpCodePointer
;
2710 ASSERT (Guid
!= NULL
);
2711 ASSERT (OpCodeSize
>= sizeof (OpCode
));
2713 ZeroMem (&OpCode
, sizeof (OpCode
));
2714 CopyGuid ((EFI_GUID
*)(VOID
*)&OpCode
.Guid
, Guid
);
2716 OpCodePointer
= (EFI_IFR_GUID
*)InternalHiiCreateOpCodeExtended (
2721 OpCodeSize
- sizeof (OpCode
),
2724 if (OpCodePointer
!= NULL
&& GuidOpCode
!= NULL
) {
2725 CopyMem (OpCodePointer
+ 1, (EFI_IFR_GUID
*)GuidOpCode
+ 1, OpCodeSize
- sizeof (OpCode
));
2727 return (UINT8
*)OpCodePointer
;
2731 Create EFI_IFR_ACTION_OP opcode.
2733 If OpCodeHandle is NULL, then ASSERT().
2734 If any reserved bits are set in QuestionFlags, then ASSERT().
2736 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2737 @param[in] QuestionId Question ID
2738 @param[in] Prompt String ID for Prompt
2739 @param[in] Help String ID for Help
2740 @param[in] QuestionFlags Flags in Question Header
2741 @param[in] QuestionConfig String ID for configuration
2743 @retval NULL There is not enough space left in Buffer to add the opcode.
2744 @retval Other A pointer to the created opcode.
2749 HiiCreateActionOpCode (
2750 IN VOID
*OpCodeHandle
,
2751 IN EFI_QUESTION_ID QuestionId
,
2752 IN EFI_STRING_ID Prompt
,
2753 IN EFI_STRING_ID Help
,
2754 IN UINT8 QuestionFlags
,
2755 IN EFI_STRING_ID QuestionConfig
2758 EFI_IFR_ACTION OpCode
;
2760 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
2762 ZeroMem (&OpCode
, sizeof (OpCode
));
2763 OpCode
.Question
.QuestionId
= QuestionId
;
2764 OpCode
.Question
.Header
.Prompt
= Prompt
;
2765 OpCode
.Question
.Header
.Help
= Help
;
2766 OpCode
.Question
.Flags
= QuestionFlags
;
2767 OpCode
.QuestionConfig
= QuestionConfig
;
2769 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ACTION_OP
, sizeof (OpCode
));
2773 Create EFI_IFR_SUBTITLE_OP opcode.
2775 If OpCodeHandle is NULL, then ASSERT().
2776 If any reserved bits are set in Flags, then ASSERT().
2777 If Scope > 1, then ASSERT().
2779 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2780 @param[in] Prompt String ID for Prompt
2781 @param[in] Help String ID for Help
2782 @param[in] Flags Subtitle opcode flags
2783 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
2784 0 if this opcode is within the current scope.
2786 @retval NULL There is not enough space left in Buffer to add the opcode.
2787 @retval Other A pointer to the created opcode.
2792 HiiCreateSubTitleOpCode (
2793 IN VOID
*OpCodeHandle
,
2794 IN EFI_STRING_ID Prompt
,
2795 IN EFI_STRING_ID Help
,
2800 EFI_IFR_SUBTITLE OpCode
;
2802 ASSERT (Scope
<= 1);
2803 ASSERT ((Flags
& (~(EFI_IFR_FLAGS_HORIZONTAL
))) == 0);
2805 ZeroMem (&OpCode
, sizeof (OpCode
));
2806 OpCode
.Statement
.Prompt
= Prompt
;
2807 OpCode
.Statement
.Help
= Help
;
2808 OpCode
.Flags
= Flags
;
2810 return InternalHiiCreateOpCodeExtended (
2813 EFI_IFR_SUBTITLE_OP
,
2821 Create EFI_IFR_REF_OP opcode.
2823 If OpCodeHandle is NULL, then ASSERT().
2824 If any reserved bits are set in QuestionFlags, then ASSERT().
2826 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2827 @param[in] FormId Destination Form ID
2828 @param[in] Prompt String ID for Prompt
2829 @param[in] Help String ID for Help
2830 @param[in] QuestionFlags Flags in Question Header
2831 @param[in] QuestionId Question ID
2833 @retval NULL There is not enough space left in Buffer to add the opcode.
2834 @retval Other A pointer to the created opcode.
2839 HiiCreateGotoOpCode (
2840 IN VOID
*OpCodeHandle
,
2841 IN EFI_FORM_ID FormId
,
2842 IN EFI_STRING_ID Prompt
,
2843 IN EFI_STRING_ID Help
,
2844 IN UINT8 QuestionFlags
,
2845 IN EFI_QUESTION_ID QuestionId
2850 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
2852 ZeroMem (&OpCode
, sizeof (OpCode
));
2853 OpCode
.Question
.Header
.Prompt
= Prompt
;
2854 OpCode
.Question
.Header
.Help
= Help
;
2855 OpCode
.Question
.QuestionId
= QuestionId
;
2856 OpCode
.Question
.Flags
= QuestionFlags
;
2857 OpCode
.FormId
= FormId
;
2859 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, sizeof (OpCode
));
2863 Create EFI_IFR_CHECKBOX_OP opcode.
2865 If OpCodeHandle is NULL, then ASSERT().
2866 If any reserved bits are set in QuestionFlags, then ASSERT().
2867 If any reserved bits are set in CheckBoxFlags, then ASSERT().
2869 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2870 @param[in] QuestionId Question ID
2871 @param[in] VarStoreId Storage ID
2872 @param[in] VarOffset Offset in Storage
2873 @param[in] Prompt String ID for Prompt
2874 @param[in] Help String ID for Help
2875 @param[in] QuestionFlags Flags in Question Header
2876 @param[in] CheckBoxFlags Flags for checkbox opcode
2877 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2878 is an optional parameter that may be NULL.
2880 @retval NULL There is not enough space left in Buffer to add the opcode.
2881 @retval Other A pointer to the created opcode.
2886 HiiCreateCheckBoxOpCode (
2887 IN VOID
*OpCodeHandle
,
2888 IN EFI_QUESTION_ID QuestionId
,
2889 IN EFI_VARSTORE_ID VarStoreId
,
2890 IN UINT16 VarOffset
,
2891 IN EFI_STRING_ID Prompt
,
2892 IN EFI_STRING_ID Help
,
2893 IN UINT8 QuestionFlags
,
2894 IN UINT8 CheckBoxFlags
,
2895 IN VOID
*DefaultsOpCodeHandle OPTIONAL
2898 EFI_IFR_CHECKBOX OpCode
;
2901 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
2903 ZeroMem (&OpCode
, sizeof (OpCode
));
2904 OpCode
.Question
.QuestionId
= QuestionId
;
2905 OpCode
.Question
.VarStoreId
= VarStoreId
;
2906 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
2907 OpCode
.Question
.Header
.Prompt
= Prompt
;
2908 OpCode
.Question
.Header
.Help
= Help
;
2909 OpCode
.Question
.Flags
= QuestionFlags
;
2910 OpCode
.Flags
= CheckBoxFlags
;
2912 if (DefaultsOpCodeHandle
== NULL
) {
2913 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
));
2916 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
2917 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
), 0, 1);
2918 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
2919 HiiCreateEndOpCode (OpCodeHandle
);
2920 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
2924 Create EFI_IFR_NUMERIC_OP opcode.
2926 If OpCodeHandle is NULL, then ASSERT().
2927 If any reserved bits are set in QuestionFlags, then ASSERT().
2928 If any reserved bits are set in NumericFlags, then ASSERT().
2930 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2931 @param[in] QuestionId Question ID
2932 @param[in] VarStoreId Storage ID
2933 @param[in] VarOffset Offset in Storage
2934 @param[in] Prompt String ID for Prompt
2935 @param[in] Help String ID for Help
2936 @param[in] QuestionFlags Flags in Question Header
2937 @param[in] NumericFlags Flags for numeric opcode
2938 @param[in] Minimum Numeric minimum value
2939 @param[in] Maximum Numeric maximum value
2940 @param[in] Step Numeric step for edit
2941 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2942 is an optional parameter that may be NULL.
2944 @retval NULL There is not enough space left in Buffer to add the opcode.
2945 @retval Other A pointer to the created opcode.
2950 HiiCreateNumericOpCode (
2951 IN VOID
*OpCodeHandle
,
2952 IN EFI_QUESTION_ID QuestionId
,
2953 IN EFI_VARSTORE_ID VarStoreId
,
2954 IN UINT16 VarOffset
,
2955 IN EFI_STRING_ID Prompt
,
2956 IN EFI_STRING_ID Help
,
2957 IN UINT8 QuestionFlags
,
2958 IN UINT8 NumericFlags
,
2962 IN VOID
*DefaultsOpCodeHandle OPTIONAL
2965 EFI_IFR_NUMERIC OpCode
;
2968 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
2970 ZeroMem (&OpCode
, sizeof (OpCode
));
2971 OpCode
.Question
.QuestionId
= QuestionId
;
2972 OpCode
.Question
.VarStoreId
= VarStoreId
;
2973 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
2974 OpCode
.Question
.Header
.Prompt
= Prompt
;
2975 OpCode
.Question
.Header
.Help
= Help
;
2976 OpCode
.Question
.Flags
= QuestionFlags
;
2977 OpCode
.Flags
= NumericFlags
;
2979 switch (NumericFlags
& EFI_IFR_NUMERIC_SIZE
) {
2980 case EFI_IFR_NUMERIC_SIZE_1
:
2981 OpCode
.data
.u8
.MinValue
= (UINT8
)Minimum
;
2982 OpCode
.data
.u8
.MaxValue
= (UINT8
)Maximum
;
2983 OpCode
.data
.u8
.Step
= (UINT8
)Step
;
2986 case EFI_IFR_NUMERIC_SIZE_2
:
2987 OpCode
.data
.u16
.MinValue
= (UINT16
)Minimum
;
2988 OpCode
.data
.u16
.MaxValue
= (UINT16
)Maximum
;
2989 OpCode
.data
.u16
.Step
= (UINT16
)Step
;
2992 case EFI_IFR_NUMERIC_SIZE_4
:
2993 OpCode
.data
.u32
.MinValue
= (UINT32
)Minimum
;
2994 OpCode
.data
.u32
.MaxValue
= (UINT32
)Maximum
;
2995 OpCode
.data
.u32
.Step
= (UINT32
)Step
;
2998 case EFI_IFR_NUMERIC_SIZE_8
:
2999 OpCode
.data
.u64
.MinValue
= Minimum
;
3000 OpCode
.data
.u64
.MaxValue
= Maximum
;
3001 OpCode
.data
.u64
.Step
= Step
;
3005 if (DefaultsOpCodeHandle
== NULL
) {
3006 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, sizeof (OpCode
));
3009 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3010 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, sizeof (OpCode
), 0, 1);
3011 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3012 HiiCreateEndOpCode (OpCodeHandle
);
3013 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3017 Create EFI_IFR_STRING_OP opcode.
3019 If OpCodeHandle is NULL, then ASSERT().
3020 If any reserved bits are set in QuestionFlags, then ASSERT().
3021 If any reserved bits are set in StringFlags, then ASSERT().
3023 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3024 @param[in] QuestionId Question ID
3025 @param[in] VarStoreId Storage ID
3026 @param[in] VarOffset Offset in Storage
3027 @param[in] Prompt String ID for Prompt
3028 @param[in] Help String ID for Help
3029 @param[in] QuestionFlags Flags in Question Header
3030 @param[in] StringFlags Flags for string opcode
3031 @param[in] MinSize String minimum length
3032 @param[in] MaxSize String maximum length
3033 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3034 is an optional parameter that may be NULL.
3036 @retval NULL There is not enough space left in Buffer to add the opcode.
3037 @retval Other A pointer to the created opcode.
3042 HiiCreateStringOpCode (
3043 IN VOID
*OpCodeHandle
,
3044 IN EFI_QUESTION_ID QuestionId
,
3045 IN EFI_VARSTORE_ID VarStoreId
,
3046 IN UINT16 VarOffset
,
3047 IN EFI_STRING_ID Prompt
,
3048 IN EFI_STRING_ID Help
,
3049 IN UINT8 QuestionFlags
,
3050 IN UINT8 StringFlags
,
3053 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3056 EFI_IFR_STRING OpCode
;
3059 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3061 ZeroMem (&OpCode
, sizeof (OpCode
));
3062 OpCode
.Question
.Header
.Prompt
= Prompt
;
3063 OpCode
.Question
.Header
.Help
= Help
;
3064 OpCode
.Question
.QuestionId
= QuestionId
;
3065 OpCode
.Question
.VarStoreId
= VarStoreId
;
3066 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3067 OpCode
.Question
.Flags
= QuestionFlags
;
3068 OpCode
.MinSize
= MinSize
;
3069 OpCode
.MaxSize
= MaxSize
;
3070 OpCode
.Flags
= (UINT8
) (StringFlags
& EFI_IFR_STRING_MULTI_LINE
);
3072 if (DefaultsOpCodeHandle
== NULL
) {
3073 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
));
3076 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3077 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
), 0, 1);
3078 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3079 HiiCreateEndOpCode (OpCodeHandle
);
3080 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3084 Create EFI_IFR_ONE_OF_OP opcode.
3086 If OpCodeHandle is NULL, then ASSERT().
3087 If any reserved bits are set in QuestionFlags, then ASSERT().
3088 If any reserved bits are set in OneOfFlags, then ASSERT().
3090 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3091 @param[in] QuestionId Question ID
3092 @param[in] VarStoreId Storage ID
3093 @param[in] VarOffset Offset in Storage
3094 @param[in] Prompt String ID for Prompt
3095 @param[in] Help String ID for Help
3096 @param[in] QuestionFlags Flags in Question Header
3097 @param[in] OneOfFlags Flags for oneof opcode
3098 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3099 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3100 is an optional parameter that may be NULL.
3102 @retval NULL There is not enough space left in Buffer to add the opcode.
3103 @retval Other A pointer to the created opcode.
3108 HiiCreateOneOfOpCode (
3109 IN VOID
*OpCodeHandle
,
3110 IN EFI_QUESTION_ID QuestionId
,
3111 IN EFI_VARSTORE_ID VarStoreId
,
3112 IN UINT16 VarOffset
,
3113 IN EFI_STRING_ID Prompt
,
3114 IN EFI_STRING_ID Help
,
3115 IN UINT8 QuestionFlags
,
3116 IN UINT8 OneOfFlags
,
3117 IN VOID
*OptionsOpCodeHandle
,
3118 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3121 EFI_IFR_ONE_OF OpCode
;
3124 ASSERT (OptionsOpCodeHandle
!= NULL
);
3125 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3127 ZeroMem (&OpCode
, sizeof (OpCode
));
3128 OpCode
.Question
.Header
.Prompt
= Prompt
;
3129 OpCode
.Question
.Header
.Help
= Help
;
3130 OpCode
.Question
.QuestionId
= QuestionId
;
3131 OpCode
.Question
.VarStoreId
= VarStoreId
;
3132 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3133 OpCode
.Question
.Flags
= QuestionFlags
;
3134 OpCode
.Flags
= OneOfFlags
;
3136 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3137 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OP
, sizeof (OpCode
), 0, 1);
3138 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3139 if (DefaultsOpCodeHandle
!= NULL
) {
3140 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3142 HiiCreateEndOpCode (OpCodeHandle
);
3143 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3147 Create EFI_IFR_ORDERED_LIST_OP opcode.
3149 If OpCodeHandle is NULL, then ASSERT().
3150 If any reserved bits are set in QuestionFlags, then ASSERT().
3151 If any reserved bits are set in OrderedListFlags, then ASSERT().
3153 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3154 @param[in] QuestionId Question ID
3155 @param[in] VarStoreId Storage ID
3156 @param[in] VarOffset Offset in Storage
3157 @param[in] Prompt String ID for Prompt
3158 @param[in] Help String ID for Help
3159 @param[in] QuestionFlags Flags in Question Header
3160 @param[in] OrderedListFlags Flags for ordered list opcode
3161 @param[in] DataType Type for option value
3162 @param[in] MaxContainers Maximum count for options in this ordered list
3163 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3164 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3165 is an optional parameter that may be NULL.
3167 @retval NULL There is not enough space left in Buffer to add the opcode.
3168 @retval Other A pointer to the created opcode.
3173 HiiCreateOrderedListOpCode (
3174 IN VOID
*OpCodeHandle
,
3175 IN EFI_QUESTION_ID QuestionId
,
3176 IN EFI_VARSTORE_ID VarStoreId
,
3177 IN UINT16 VarOffset
,
3178 IN EFI_STRING_ID Prompt
,
3179 IN EFI_STRING_ID Help
,
3180 IN UINT8 QuestionFlags
,
3181 IN UINT8 OrderedListFlags
,
3183 IN UINT8 MaxContainers
,
3184 IN VOID
*OptionsOpCodeHandle
,
3185 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3188 EFI_IFR_ORDERED_LIST OpCode
;
3191 ASSERT (OptionsOpCodeHandle
!= NULL
);
3192 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3194 ZeroMem (&OpCode
, sizeof (OpCode
));
3195 OpCode
.Question
.Header
.Prompt
= Prompt
;
3196 OpCode
.Question
.Header
.Help
= Help
;
3197 OpCode
.Question
.QuestionId
= QuestionId
;
3198 OpCode
.Question
.VarStoreId
= VarStoreId
;
3199 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3200 OpCode
.Question
.Flags
= QuestionFlags
;
3201 OpCode
.MaxContainers
= MaxContainers
;
3202 OpCode
.Flags
= OrderedListFlags
;
3204 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3205 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ORDERED_LIST_OP
, sizeof (OpCode
), 0, 1);
3206 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3207 if (DefaultsOpCodeHandle
!= NULL
) {
3208 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3210 HiiCreateEndOpCode (OpCodeHandle
);
3211 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3215 Create EFI_IFR_TEXT_OP opcode.
3217 If OpCodeHandle is NULL, then ASSERT().
3219 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3220 @param[in] Prompt String ID for Prompt.
3221 @param[in] Help String ID for Help.
3222 @param[in] TextTwo String ID for TextTwo.
3224 @retval NULL There is not enough space left in Buffer to add the opcode.
3225 @retval Other A pointer to the created opcode.
3230 HiiCreateTextOpCode (
3231 IN VOID
*OpCodeHandle
,
3232 IN EFI_STRING_ID Prompt
,
3233 IN EFI_STRING_ID Help
,
3234 IN EFI_STRING_ID TextTwo
3237 EFI_IFR_TEXT OpCode
;
3239 ZeroMem (&OpCode
, sizeof (OpCode
));
3240 OpCode
.Statement
.Prompt
= Prompt
;
3241 OpCode
.Statement
.Help
= Help
;
3242 OpCode
.TextTwo
= TextTwo
;
3244 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TEXT_OP
, sizeof (OpCode
));
3248 Create EFI_IFR_DATE_OP opcode.
3250 If OpCodeHandle is NULL, then ASSERT().
3251 If any reserved bits are set in QuestionFlags, then ASSERT().
3252 If any reserved bits are set in DateFlags, then ASSERT().
3254 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3255 @param[in] QuestionId Question ID
3256 @param[in] VarStoreId Storage ID, optional. If DateFlags is not
3257 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3258 @param[in] VarOffset Offset in Storage, optional. If DateFlags is not
3259 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3260 @param[in] Prompt String ID for Prompt
3261 @param[in] Help String ID for Help
3262 @param[in] QuestionFlags Flags in Question Header
3263 @param[in] DateFlags Flags for date opcode
3264 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3265 is an optional parameter that may be NULL.
3267 @retval NULL There is not enough space left in Buffer to add the opcode.
3268 @retval Other A pointer to the created opcode.
3273 HiiCreateDateOpCode (
3274 IN VOID
*OpCodeHandle
,
3275 IN EFI_QUESTION_ID QuestionId
,
3276 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
3277 IN UINT16 VarOffset
, OPTIONAL
3278 IN EFI_STRING_ID Prompt
,
3279 IN EFI_STRING_ID Help
,
3280 IN UINT8 QuestionFlags
,
3282 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3285 EFI_IFR_DATE OpCode
;
3288 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3289 ASSERT ((DateFlags
& (~(EFI_QF_DATE_YEAR_SUPPRESS
| EFI_QF_DATE_MONTH_SUPPRESS
| EFI_QF_DATE_DAY_SUPPRESS
| EFI_QF_DATE_STORAGE
))) == 0);
3291 ZeroMem (&OpCode
, sizeof (OpCode
));
3292 OpCode
.Question
.Header
.Prompt
= Prompt
;
3293 OpCode
.Question
.Header
.Help
= Help
;
3294 OpCode
.Question
.QuestionId
= QuestionId
;
3295 OpCode
.Question
.VarStoreId
= VarStoreId
;
3296 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3297 OpCode
.Question
.Flags
= QuestionFlags
;
3298 OpCode
.Flags
= DateFlags
;
3300 if (DefaultsOpCodeHandle
== NULL
) {
3301 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
));
3304 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3305 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_DATE_OP
, sizeof (OpCode
), 0, 1);
3306 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3307 HiiCreateEndOpCode (OpCodeHandle
);
3308 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3312 Create EFI_IFR_TIME_OP opcode.
3314 If OpCodeHandle is NULL, then ASSERT().
3315 If any reserved bits are set in QuestionFlags, then ASSERT().
3316 If any reserved bits are set in TimeFlags, then ASSERT().
3318 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3319 @param[in] QuestionId Question ID
3320 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not
3321 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3322 @param[in] VarOffset Offset in Storage, optional. If TimeFlags is not
3323 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3324 @param[in] Prompt String ID for Prompt
3325 @param[in] Help String ID for Help
3326 @param[in] QuestionFlags Flags in Question Header
3327 @param[in] TimeFlags Flags for time opcode
3328 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3329 is an optional parameter that may be NULL.
3331 @retval NULL There is not enough space left in Buffer to add the opcode.
3332 @retval Other A pointer to the created opcode.
3337 HiiCreateTimeOpCode (
3338 IN VOID
*OpCodeHandle
,
3339 IN EFI_QUESTION_ID QuestionId
,
3340 IN EFI_VARSTORE_ID VarStoreId
, OPTIONAL
3341 IN UINT16 VarOffset
, OPTIONAL
3342 IN EFI_STRING_ID Prompt
,
3343 IN EFI_STRING_ID Help
,
3344 IN UINT8 QuestionFlags
,
3346 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3349 EFI_IFR_TIME OpCode
;
3352 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
))) == 0);
3353 ASSERT ((TimeFlags
& (~(QF_TIME_HOUR_SUPPRESS
| QF_TIME_MINUTE_SUPPRESS
| QF_TIME_SECOND_SUPPRESS
| QF_TIME_STORAGE
))) == 0);
3355 ZeroMem (&OpCode
, sizeof (OpCode
));
3356 OpCode
.Question
.Header
.Prompt
= Prompt
;
3357 OpCode
.Question
.Header
.Help
= Help
;
3358 OpCode
.Question
.QuestionId
= QuestionId
;
3359 OpCode
.Question
.VarStoreId
= VarStoreId
;
3360 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3361 OpCode
.Question
.Flags
= QuestionFlags
;
3362 OpCode
.Flags
= TimeFlags
;
3364 if (DefaultsOpCodeHandle
== NULL
) {
3365 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
));
3368 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3369 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_TIME_OP
, sizeof (OpCode
), 0, 1);
3370 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3371 HiiCreateEndOpCode (OpCodeHandle
);
3372 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3376 This is the internal worker function to update the data in
3377 a form specified by FormSetGuid, FormId and Label.
3379 @param[in] FormSetGuid The optional Formset GUID.
3380 @param[in] FormId The Form ID.
3381 @param[in] Package The package header.
3382 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR
3383 opcodes to be inserted or replaced in the form.
3384 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode
3385 that marks the end of a replace operation in the form.
3386 @param[out] TempPackage The resultant package.
3388 @retval EFI_SUCCESS The function completes successfully.
3389 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.
3394 InternalHiiUpdateFormPackageData (
3395 IN EFI_GUID
*FormSetGuid
, OPTIONAL
3396 IN EFI_FORM_ID FormId
,
3397 IN EFI_HII_PACKAGE_HEADER
*Package
,
3398 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
,
3399 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
, OPTIONAL
3400 OUT EFI_HII_PACKAGE_HEADER
*TempPackage
3405 EFI_HII_PACKAGE_HEADER PackageHeader
;
3407 EFI_IFR_OP_HEADER
*IfrOpHdr
;
3408 EFI_IFR_OP_HEADER
*UpdateIfrOpHdr
;
3412 UINTN UpdatePackageLength
;
3414 CopyMem (TempPackage
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3415 UpdatePackageLength
= sizeof (EFI_HII_PACKAGE_HEADER
);
3416 BufferPos
= (UINT8
*) (TempPackage
+ 1);
3418 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3419 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
3420 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
3421 GetFormSet
= (BOOLEAN
) ((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
3425 while (Offset
< PackageHeader
.Length
) {
3426 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3427 BufferPos
+= IfrOpHdr
->Length
;
3428 UpdatePackageLength
+= IfrOpHdr
->Length
;
3431 // Find the matched FormSet and Form
3433 if ((IfrOpHdr
->OpCode
== EFI_IFR_FORM_SET_OP
) && (FormSetGuid
!= NULL
)) {
3434 if (CompareGuid((GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
)) {
3439 } else if (IfrOpHdr
->OpCode
== EFI_IFR_FORM_OP
|| IfrOpHdr
->OpCode
== EFI_IFR_FORM_MAP_OP
) {
3440 if (CompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
3448 // The matched Form is found, and Update data in this form
3450 if (GetFormSet
&& GetForm
) {
3451 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
;
3452 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3453 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3455 // Remove the original data when End OpCode buffer exist.
3457 if (OpCodeBufferEnd
!= NULL
) {
3458 Offset
+= IfrOpHdr
->Length
;
3459 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3460 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferEnd
->Buffer
;
3461 while (Offset
< PackageHeader
.Length
) {
3463 // Search the matched end opcode
3465 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3466 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3470 // Go to the next Op-Code
3472 Offset
+= IfrOpHdr
->Length
;
3473 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3476 if (Offset
>= PackageHeader
.Length
) {
3478 // The end opcode is not found.
3480 return EFI_NOT_FOUND
;
3485 // Insert the updated data
3487 AddSize
= ((EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
)->Length
;
3488 CopyMem (BufferPos
, OpCodeBufferStart
->Buffer
+ AddSize
, OpCodeBufferStart
->Position
- AddSize
);
3489 BufferPos
+= OpCodeBufferStart
->Position
- AddSize
;
3490 UpdatePackageLength
+= OpCodeBufferStart
->Position
- AddSize
;
3492 if (OpCodeBufferEnd
!= NULL
) {
3494 // Add the end opcode
3496 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3497 BufferPos
+= IfrOpHdr
->Length
;
3498 UpdatePackageLength
+= IfrOpHdr
->Length
;
3502 // Copy the left package data.
3504 Offset
+= IfrOpHdr
->Length
;
3505 CopyMem (BufferPos
, (UINT8
*) Package
+ Offset
, PackageHeader
.Length
- Offset
);
3506 UpdatePackageLength
+= PackageHeader
.Length
- Offset
;
3517 // Go to the next Op-Code
3519 Offset
+= IfrOpHdr
->Length
;
3520 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3525 // The updated opcode buffer is not found.
3527 return EFI_NOT_FOUND
;
3530 // Update the package length.
3532 PackageHeader
.Length
= (UINT32
) UpdatePackageLength
;
3533 CopyMem (TempPackage
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3539 This function updates a form that has previously been registered with the HII
3540 Database. This function will perform at most one update operation.
3542 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
3543 comparisons of IFR opcodes are performed from the beginning of the form being
3544 updated until an IFR opcode is found that exactly matches the first IFR opcode
3545 specified by StartOpCodeHandle. The following rules are used to determine if
3546 an insert, replace, or delete operation is performed.
3548 1) If no matches are found, then NULL is returned.
3549 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
3550 from StartOpCodeHandle except the first opcode are inserted immediately after
3551 the matching IFR opcode in the form to be updated.
3552 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
3553 from the matching IFR opcode until an IFR opcode exactly matches the first
3554 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
3555 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
3556 is found, then all of the IFR opcodes between the start match and the end
3557 match are deleted from the form being updated and all of the IFR opcodes
3558 from StartOpCodeHandle except the first opcode are inserted immediately after
3559 the matching start IFR opcode. If StartOpCcodeHandle only contains one
3560 IFR instruction, then the result of this operation will delete all of the IFR
3561 opcodes between the start end matches.
3563 If HiiHandle is NULL, then ASSERT().
3564 If StartOpCodeHandle is NULL, then ASSERT().
3566 @param[in] HiiHandle The HII Handle of the form to update.
3567 @param[in] FormSetGuid The Formset GUID of the form to update. This
3568 is an optional parameter that may be NULL.
3569 If it is NULL, all FormSet will be updated.
3570 @param[in] FormId The ID of the form to update.
3571 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
3572 opcodes to be inserted or replaced in the form.
3573 The first IFR instruction in StartOpCodeHandle
3574 is used to find matching IFR opcode in the
3576 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
3577 that marks the end of a replace operation in
3578 the form. This is an optional parameter that
3579 may be NULL. If it is NULL, then an the IFR
3580 opcodes specified by StartOpCodeHandle are
3581 inserted into the form.
3583 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
3584 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
3585 1) The form specified by HiiHandle, FormSetGuid,
3586 and FormId could not be found in the HII Database.
3587 2) No IFR opcodes in the target form match the first
3588 IFR opcode in StartOpCodeHandle.
3589 3) EndOpCOde is not NULL, and no IFR opcodes in the
3590 target form following a matching start opcode match
3591 the first IFR opcode in EndOpCodeHandle.
3592 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
3598 IN EFI_HII_HANDLE HiiHandle
,
3599 IN EFI_GUID
*FormSetGuid
, OPTIONAL
3600 IN EFI_FORM_ID FormId
,
3601 IN VOID
*StartOpCodeHandle
,
3602 IN VOID
*EndOpCodeHandle OPTIONAL
3606 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3607 UINT32 PackageListLength
;
3609 EFI_HII_PACKAGE_LIST_HEADER
*UpdatePackageList
;
3611 UINT8
*UpdateBufferPos
;
3612 EFI_HII_PACKAGE_HEADER
*Package
;
3613 EFI_HII_PACKAGE_HEADER
*TempPacakge
;
3614 EFI_HII_PACKAGE_HEADER PackageHeader
;
3616 HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
;
3617 HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
;
3620 // Input update data can't be NULL.
3622 ASSERT (HiiHandle
!= NULL
);
3623 ASSERT (StartOpCodeHandle
!= NULL
);
3624 UpdatePackageList
= NULL
;
3626 HiiPackageList
= NULL
;
3629 // Retrieve buffer data from Opcode Handle
3631 OpCodeBufferStart
= (HII_LIB_OPCODE_BUFFER
*) StartOpCodeHandle
;
3632 OpCodeBufferEnd
= (HII_LIB_OPCODE_BUFFER
*) EndOpCodeHandle
;
3635 // Get the original package list
3638 HiiPackageList
= NULL
;
3639 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
3641 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
3643 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3647 HiiPackageList
= AllocatePool (BufferSize
);
3648 if (HiiPackageList
== NULL
) {
3649 Status
= EFI_OUT_OF_RESOURCES
;
3653 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
3654 if (EFI_ERROR (Status
)) {
3659 // Calculate and allocate space for retrieval of IFR data
3661 BufferSize
+= OpCodeBufferStart
->Position
;
3662 UpdatePackageList
= AllocateZeroPool (BufferSize
);
3663 if (UpdatePackageList
== NULL
) {
3664 Status
= EFI_OUT_OF_RESOURCES
;
3669 // Allocate temp buffer to store the temp updated package buffer
3671 TempPacakge
= AllocateZeroPool (BufferSize
);
3672 if (TempPacakge
== NULL
) {
3673 Status
= EFI_OUT_OF_RESOURCES
;
3677 UpdateBufferPos
= (UINT8
*) UpdatePackageList
;
3680 // Copy the package list header
3682 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
3683 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3686 // Go through each package to find the matched package and update one by one
3689 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3690 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
3691 while (Offset
< PackageListLength
) {
3692 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
3693 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3694 Offset
+= Package
->Length
;
3696 if (Package
->Type
== EFI_HII_PACKAGE_FORMS
) {
3698 // Check this package is the matched package.
3700 Status
= InternalHiiUpdateFormPackageData (FormSetGuid
, FormId
, Package
, OpCodeBufferStart
, OpCodeBufferEnd
, TempPacakge
);
3702 // The matched package is found. Its package buffer will be updated by the input new data.
3704 if (!EFI_ERROR(Status
)) {
3710 // Add updated package buffer
3712 Package
= TempPacakge
;
3717 // Add pacakge buffer
3719 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3720 CopyMem (UpdateBufferPos
, Package
, PackageHeader
.Length
);
3721 UpdateBufferPos
+= PackageHeader
.Length
;
3726 // Update package list length
3728 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdatePackageList
;
3729 WriteUnaligned32 (&UpdatePackageList
->PackageLength
, (UINT32
) BufferSize
);
3732 // Update Package to show form
3734 Status
= gHiiDatabase
->UpdatePackageList (gHiiDatabase
, HiiHandle
, UpdatePackageList
);
3737 // Not matched form is found and updated.
3739 Status
= EFI_NOT_FOUND
;
3743 if (HiiPackageList
!= NULL
) {
3744 FreePool (HiiPackageList
);
3747 if (UpdatePackageList
!= NULL
) {
3748 FreePool (UpdatePackageList
);
3751 if (TempPacakge
!= NULL
) {
3752 FreePool (TempPacakge
);