2 HII Library implementation that uses DXE protocols and services.
4 Copyright (c) 2006 - 2008, Intel Corporation<BR>
5 All rights reserved. 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, then NULL is returned. If there are not enough
109 resources to perform the registration, then NULL is returned. If an empty list
110 of packages is passed in, then NULL is returned. If the size of the list of
111 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
,
148 EFI_HII_HANDLE
*HiiHandleBuffer
;
151 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
152 EFI_HII_HANDLE HiiHandle
;
156 ASSERT (PackageListGuid
!= NULL
);
159 // Check to see if an HII Handle has already been registered with the same
162 HiiHandleBuffer
= HiiGetHiiHandles (PackageListGuid
);
163 if (HiiHandleBuffer
!= NULL
) {
164 FreePool (HiiHandleBuffer
);
169 // Calculate the length of all the packages in the variable argument list
171 for (Length
= 0, VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
172 Length
+= (ReadUnaligned32 (Package
) - sizeof (UINT32
));
177 // If there are no packages in the variable argument list or all the packages
178 // are empty, then return a NULL HII Handle
185 // Add the length of the Package List Header and the terminating Package Header
187 Length
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
) + sizeof (EFI_HII_PACKAGE_HEADER
);
190 // Allocate the storage for the entire Package List
192 PackageListHeader
= AllocateZeroPool (Length
);
195 // If the Packahge List can not be allocated, then return a NULL HII Handle
197 if (PackageListHeader
== NULL
) {
202 // Fill in the GUID and Length of the Package List Header
204 CopyGuid (&PackageListHeader
->PackageListGuid
, PackageListGuid
);
205 PackageListHeader
->PackageLength
= Length
;
208 // Initialize a pointer to the beginning if the Package List data
210 Data
= (UINT8
*)(PackageListHeader
+ 1);
213 // Copy the data from each package in the variable argument list
215 for (VA_START (Args
, DeviceHandle
); (Package
= VA_ARG (Args
, UINT32
*)) != NULL
; ) {
216 Length
= ReadUnaligned32 (Package
) - sizeof (UINT32
);
217 CopyMem (Data
, Package
+ 1, Length
);
223 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list
225 CopyMem (Data
, &mEndOfPakageList
, sizeof (mEndOfPakageList
));
228 // Register the package list with the HII Database
230 Status
= gHiiDatabase
->NewPackageList (
236 if (EFI_ERROR (Status
)) {
241 // Free the allocated package list
243 FreePool (PackageListHeader
);
246 // Return the new HII Handle
252 Removes a package list from the HII database.
254 If HiiHandle is NULL, then ASSERT.
255 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.
257 @param[in] HiiHandle The handle that was previously registered in the HII database
263 IN EFI_HII_HANDLE HiiHandle
268 ASSERT (HiiHandle
!= NULL
);
269 Status
= gHiiDatabase
->RemovePackageList (gHiiDatabase
, HiiHandle
);
270 ASSERT_EFI_ERROR (Status
);
275 Retrieves the array of all the HII Handles or the HII handle of a specific
276 package list in the HII Database.
277 This array is terminated with a NULL HII Handle.
278 This function allocates the returned array using AllocatePool().
279 The caller is responsible for freeing the array with FreePool().
281 @param[in] PackageListGuid An optional parameter that is used to request
282 an HII Handle that is associatd with a specific
283 Package List GUID. If this parameter is NULL
284 then all the HII Handles in the HII Database
285 are returned. If this parameter is not NULL
286 then at most 1 HII Handle is returned.
288 @retval NULL No HII handles were found in the HII database
289 @retval NULL The array of HII Handles could not be retrieved
290 @retval Other A pointer to the NULL terminated array of HII Handles
296 IN CONST EFI_GUID
*PackageListGuid OPTIONAL
300 UINTN HandleBufferLength
;
301 EFI_HII_HANDLE TempHiiHandleBuffer
;
302 EFI_HII_HANDLE
*HiiHandleBuffer
;
307 // Retrieve the size required for the buffer of all HII handles.
309 HandleBufferLength
= 0;
310 Status
= gHiiDatabase
->ListPackageLists (
312 EFI_HII_PACKAGE_TYPE_ALL
,
319 // If ListPackageLists() returns EFI_SUCCESS for a zero size,
320 // then there are no HII handles in the HII database. If ListPackageLists()
321 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII
322 // handles in the HII database.
324 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
326 // Return NULL if the size can not be retrieved, or if there are no HII
327 // handles in the HII Database
333 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator
335 HiiHandleBuffer
= AllocateZeroPool (HandleBufferLength
+ sizeof (EFI_HII_HANDLE
));
336 if (HiiHandleBuffer
== NULL
) {
338 // Return NULL if allocation fails.
344 // Retrieve the array of HII Handles in the HII Database
346 Status
= gHiiDatabase
->ListPackageLists (
348 EFI_HII_PACKAGE_TYPE_ALL
,
353 if (EFI_ERROR (Status
)) {
355 // Free the buffer and return NULL if the HII handles can not be retrieved.
357 FreePool (HiiHandleBuffer
);
361 if (PackageListGuid
== NULL
) {
363 // Return the NULL terminated array of HII handles in the HII Database
365 return HiiHandleBuffer
;
367 for (Index
= 0; HiiHandleBuffer
[Index
] != NULL
; Index
++) {
368 Status
= InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer
[Index
], &Guid
);
369 ASSERT_EFI_ERROR (Status
);
370 if (CompareGuid (&Guid
, PackageListGuid
)) {
371 HiiHandleBuffer
[0] = HiiHandleBuffer
[Index
];
372 HiiHandleBuffer
[1] = NULL
;
373 return HiiHandleBuffer
;
376 FreePool (HiiHandleBuffer
);
382 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
383 hex digits that appear between a '=' and a '&' in a config string.
385 If String is NULL, then ASSERT().
387 @param[in] String Pointer to a Null-terminated Unicode string.
389 @return Pointer to the Null-terminated Unicode result string.
394 InternalHiiLowerConfigString (
395 IN EFI_STRING ConfigString
401 ASSERT (ConfigString
!= NULL
);
404 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
406 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
407 if (*String
== L
'=') {
409 } else if (*String
== L
'&') {
411 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
412 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
420 Uses the BlockToConfig() service of the Config Routing Protocol to
421 convert <ConfigRequest> and a buffer to a <ConfigResp>
423 If ConfigRequest is NULL, then ASSERT().
424 If Block is NULL, then ASSERT().
426 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.
427 @param[in] Block Pointer to a block of data.
428 @param[in] BlockSize The zie, in bytes, of Block.
430 @retval NULL The <ConfigResp> string could not be generated.
431 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.
436 InternalHiiBlockToConfig (
437 IN CONST EFI_STRING ConfigRequest
,
438 IN CONST UINT8
*Block
,
443 EFI_STRING ConfigResp
;
446 ASSERT (ConfigRequest
!= NULL
);
447 ASSERT (Block
!= NULL
);
450 // Convert <ConfigRequest> to <ConfigResp>
452 Status
= gHiiConfigRouting
->BlockToConfig (
460 if (EFI_ERROR (Status
)) {
467 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve
468 or set uncommitted data. If sata i being retrieved, then the buffer is
469 allocated using AllocatePool(). The caller is then responsible for freeing
470 the buffer using FreePool().
472 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
473 is an optional parameter that may be NULL.
474 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
475 parameter that may be NULL.
476 @param[in] SetResultsData If not NULL, then this parameter specified the buffer
477 of uncommited data to set. If this parameter is NULL,
478 then the caller is requesting to get the uncommited data
479 from the Form Browser.
481 @retval NULL The uncommitted data could not be retrieved.
482 @retval Other A pointer to a buffer containing the uncommitted data.
487 InternalHiiBrowserCallback (
488 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
489 IN CONST CHAR16
*VariableName
, OPTIONAL
490 IN CONST EFI_STRING SetResultsData OPTIONAL
494 UINTN ResultsDataSize
;
495 EFI_STRING ResultsData
;
496 CHAR16 TempResultsData
;
501 if (mUefiFormBrowser2
== NULL
) {
502 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mUefiFormBrowser2
);
503 if (EFI_ERROR (Status
) || mUefiFormBrowser2
== NULL
) {
510 if (SetResultsData
!= NULL
) {
512 // Request to to set data in the uncommitted browser state information
514 ResultsData
= SetResultsData
;
517 // Retrieve the length of the buffer required ResultsData from the Browser Callback
519 Status
= mUefiFormBrowser2
->BrowserCallback (
528 if (!EFI_ERROR (Status
)) {
530 // No Resluts Data, only allocate one char for '\0'
532 ResultsData
= AllocateZeroPool (sizeof (CHAR16
));
536 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
541 // Allocate the ResultsData buffer
543 ResultsData
= AllocateZeroPool (ResultsDataSize
);
544 if (ResultsData
== NULL
) {
550 // Retrieve or set the ResultsData from the Browser Callback
552 Status
= mUefiFormBrowser2
->BrowserCallback (
556 (BOOLEAN
)(SetResultsData
== NULL
),
560 if (EFI_ERROR (Status
)) {
568 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing
569 information that includes a GUID, an optional Unicode string name, and a device
570 path. The string returned is allocated with AllocatePool(). The caller is
571 responsible for freeing the allocated string with FreePool().
573 The format of a <ConfigHdr> is as follows:
575 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
577 @param[in] Guid Pointer to an EFI_GUID that is the routing information
578 GUID. Each of the 16 bytes in Guid is converted to
579 a 2 Unicode character hexidecimal string. This is
580 an optional parameter that may be NULL.
581 @param[in] Name Pointer to a Null-terminated Unicode string that is
582 the routing information NAME. This is an optional
583 parameter that may be NULL. Each 16-bit Unicode
584 character in Name is converted to a 4 character Unicode
586 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
587 that is the routing information PATH. Each byte of
588 the Device Path associated with DriverHandle is converted
589 to a 2 Unicode character hexidecimal string.
591 @retval NULL DriverHandle does not support the Device Path Protocol.
592 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
597 HiiConstructConfigHdr (
598 IN CONST EFI_GUID
*Guid
, OPTIONAL
599 IN CONST CHAR16
*Name
, OPTIONAL
600 IN EFI_HANDLE DriverHandle
604 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
605 UINTN DevicePathSize
;
607 CHAR16
*ReturnString
;
612 // Compute the length of Name in Unicode characters.
613 // If Name is NULL, then the length is 0.
617 NameLength
= StrLen (Name
);
623 // Retrieve DevicePath Protocol associated with DriverHandle
625 if (DriverHandle
!= NULL
) {
626 DevicePath
= DevicePathFromHandle (DriverHandle
);
627 if (DevicePath
== NULL
) {
631 // Compute the size of the device path in bytes
633 DevicePathSize
= GetDevicePathSize (DevicePath
);
637 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
638 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
640 String
= AllocateZeroPool ((5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
));
641 if (String
== NULL
) {
646 // Start with L"GUID="
648 ReturnString
= StrCpy (String
, L
"GUID=");
649 String
+= StrLen (String
);
653 // Append Guid converted to <HexCh>32
655 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
656 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
663 StrCpy (String
, L
"&NAME=");
664 String
+= StrLen (String
);
668 // Append Name converted to <Char>NameLength
670 for (; *Name
!= L
'\0'; Name
++) {
671 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *Name
, 4);
678 StrCpy (String
, L
"&PATH=");
679 String
+= StrLen (String
);
682 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
684 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
685 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
689 // Null terminate the Unicode string
694 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
696 return InternalHiiLowerConfigString (ReturnString
);
700 Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path
701 to binary buffer from <ConfigHdr>.
703 This is a internal function.
705 @param String UEFI configuration string.
706 @param Flag Flag specifies what type buffer will be retrieved.
707 @param Buffer Binary of Guid, Name or Device path.
709 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
710 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
711 @retval EFI_SUCCESS The buffer data is retrieved and translated to
716 InternalHiiGetBufferFromString (
717 IN EFI_STRING String
,
723 EFI_STRING ConfigHdr
;
730 if (String
== NULL
|| Buffer
== NULL
) {
731 return EFI_INVALID_PARAMETER
;
738 // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element
739 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.
741 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
744 case GUID_CONFIG_STRING_TYPE
:
745 case PATH_CONFIG_STRING_TYPE
:
747 // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order
748 // as the device path and Guid resides in RAM memory.
749 // Translate the data into binary.
751 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
752 if (DataBuffer
== NULL
) {
753 return EFI_OUT_OF_RESOURCES
;
756 // Convert binary byte one by one
758 ZeroMem (TemStr
, sizeof (TemStr
));
759 for (Index
= 0; Index
< Length
; Index
++) {
760 TemStr
[0] = ConfigHdr
[Index
];
761 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
762 if ((Index
& 1) == 0) {
763 DataBuffer
[Index
/2] = DigitUint8
;
765 DataBuffer
[Index
/2] = (UINT8
) ((DataBuffer
[Index
/2] << 4) + DigitUint8
);
769 *Buffer
= DataBuffer
;
772 case NAME_CONFIG_STRING_TYPE
:
774 // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"
778 // Add the tailling char L'\0'
780 DataBuffer
= (UINT8
*) AllocateZeroPool ((Length
/4 + 1) * sizeof (CHAR16
));
781 if (DataBuffer
== NULL
) {
782 return EFI_OUT_OF_RESOURCES
;
785 // Convert character one by one
787 StringPtr
= (CHAR16
*) DataBuffer
;
788 ZeroMem (TemStr
, sizeof (TemStr
));
789 for (Index
= 0; Index
< Length
; Index
+= 4) {
790 StrnCpy (TemStr
, ConfigHdr
+ Index
, 4);
791 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
794 // Add tailing L'\0' character
796 StringPtr
[Index
/4] = L
'\0';
798 *Buffer
= DataBuffer
;
802 return EFI_INVALID_PARAMETER
;
810 This function checks VarOffset and VarWidth is in the block range.
812 @param BlockArray The block array is to be checked.
813 @param VarOffset Offset of var to the structure
814 @param VarWidth Width of var.
816 @retval TRUE This Var is in the block range.
817 @retval FALSE This Var is not in the block range.
821 IN IFR_BLOCK_DATA
*BlockArray
,
827 IFR_BLOCK_DATA
*BlockData
;
830 // No Request Block array, all vars are got.
832 if (BlockArray
== NULL
) {
837 // Check the input var is in the request block range.
839 for (Link
= BlockArray
->Entry
.ForwardLink
; Link
!= &BlockArray
->Entry
; Link
= Link
->ForwardLink
) {
840 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
841 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
850 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
852 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
854 @param ValueString String in <BlockConfig> format and points to the
855 first character of <Number>.
856 @param ValueData The output value. Caller takes the responsibility
858 @param ValueLength Length of the <Number>, in characters.
860 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
862 @retval EFI_SUCCESS Value of <Number> is outputted in Number
868 InternalHiiGetValueOfNumber (
869 IN EFI_STRING ValueString
,
870 OUT UINT8
**ValueData
,
871 OUT UINTN
*ValueLength
874 EFI_STRING StringPtr
;
881 ASSERT (ValueString
!= NULL
&& ValueData
!= NULL
&& ValueLength
!= NULL
);
882 ASSERT (*ValueString
!= L
'\0');
885 // Get the length of value string
887 StringPtr
= ValueString
;
888 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
891 Length
= StringPtr
- ValueString
;
894 // Allocate buffer to store the value
896 Buf
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
898 return EFI_OUT_OF_RESOURCES
;
902 // Convert character one by one to the value buffer
904 ZeroMem (TemStr
, sizeof (TemStr
));
905 for (Index
= 0; Index
< Length
; Index
++) {
906 TemStr
[0] = ValueString
[Length
- Index
- 1];
907 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
908 if ((Index
& 1) == 0) {
909 Buf
[Index
/2] = DigitUint8
;
911 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
916 // Set the converted value and string length.
919 *ValueLength
= Length
;
924 This function shares the same logic to parse ConfigAltResp string
925 for setting default value and validating current setting.
928 @param HiiPackageList
929 @param PackageListLength
937 InternalHiiValidateCurrentSetting (
938 IN EFI_STRING ConfigResp
,
939 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
940 IN UINTN PackageListLength
,
941 IN EFI_GUID
*VarGuid
,
945 IFR_BLOCK_DATA
*CurrentBlockArray
;
946 IFR_BLOCK_DATA
*BlockData
;
947 IFR_BLOCK_DATA
*NewBlockData
;
948 IFR_BLOCK_DATA VarBlockData
;
949 EFI_STRING StringPtr
;
959 EFI_HII_PACKAGE_HEADER PacakgeHeader
;
960 UINT32 PackageOffset
;
963 EFI_IFR_OP_HEADER
*IfrOpHdr
;
964 EFI_IFR_VARSTORE
*IfrVarStore
;
965 EFI_IFR_ONE_OF
*IfrOneOf
;
966 EFI_IFR_NUMERIC
*IfrNumeric
;
967 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
968 EFI_IFR_CHECKBOX
*IfrCheckBox
;
969 EFI_IFR_STRING
*IfrString
;
974 // 1. Get the current setting to current block data array and Convert them into VarBuffer
978 // Skip ConfigHdr string
980 StringPtr
= ConfigResp
;
981 StringPtr
= StrStr (ConfigResp
, L
"&OFFSET");
982 if (StringPtr
== NULL
) {
984 // No ConfigBlock value is requied to be validated.
985 // EFI_SUCCESS directly return.
991 // Initialize the local variables.
995 Status
= EFI_SUCCESS
;
999 MaxBufferSize
= HII_LIB_DEFAULT_VARSTORE_SIZE
;
1000 VarBuffer
= AllocateZeroPool (MaxBufferSize
);
1001 if (VarBuffer
== NULL
) {
1002 return EFI_OUT_OF_RESOURCES
;
1006 // Init CurrentBlockArray
1008 CurrentBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1009 if (CurrentBlockArray
== NULL
) {
1010 Status
= EFI_OUT_OF_RESOURCES
;
1013 InitializeListHead (&CurrentBlockArray
->Entry
);
1016 // Parse each <RequestElement> if exists
1017 // Only <BlockName> format is supported by this help function.
1018 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1020 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1022 // Skip the &OFFSET= string
1024 StringPtr
+= StrLen (L
"&OFFSET=");
1029 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1030 if (EFI_ERROR (Status
)) {
1037 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1039 FreePool (TmpBuffer
);
1042 StringPtr
+= Length
;
1043 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1044 Status
= EFI_INVALID_PARAMETER
;
1047 StringPtr
+= StrLen (L
"&WIDTH=");
1052 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1053 if (EFI_ERROR (Status
)) {
1060 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1062 FreePool (TmpBuffer
);
1065 StringPtr
+= Length
;
1066 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1067 Status
= EFI_INVALID_PARAMETER
;
1071 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1072 Status
= EFI_INVALID_PARAMETER
;
1075 StringPtr
+= StrLen (L
"&VALUE=");
1080 Status
= InternalHiiGetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1081 if (EFI_ERROR (Status
)) {
1085 StringPtr
+= Length
;
1086 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1087 Status
= EFI_INVALID_PARAMETER
;
1092 // Check whether VarBuffer is enough
1094 if ((UINTN
) (Offset
+ Width
) > MaxBufferSize
) {
1095 VarBuffer
= ReallocatePool (
1097 Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
,
1100 if (VarBuffer
== NULL
) {
1101 Status
= EFI_OUT_OF_RESOURCES
;
1104 MaxBufferSize
= Offset
+ Width
+ HII_LIB_DEFAULT_VARSTORE_SIZE
;
1108 // Update the Block with configuration info
1110 CopyMem (VarBuffer
+ Offset
, TmpBuffer
, Width
);
1111 FreePool (TmpBuffer
);
1115 // Set new Block Data
1117 NewBlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1118 if (NewBlockData
== NULL
) {
1119 Status
= EFI_OUT_OF_RESOURCES
;
1122 NewBlockData
->Offset
= Offset
;
1123 NewBlockData
->Width
= Width
;
1126 // Insert the new block data into the block data array.
1128 for (Link
= CurrentBlockArray
->Entry
.ForwardLink
; Link
!= &CurrentBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1129 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1130 if (NewBlockData
->Offset
== BlockData
->Offset
) {
1131 if (NewBlockData
->Width
> BlockData
->Width
) {
1132 BlockData
->Width
= NewBlockData
->Width
;
1134 FreePool (NewBlockData
);
1136 } else if (NewBlockData
->Offset
< BlockData
->Offset
) {
1138 // Insert new block data as the previous one of this link.
1140 InsertTailList (Link
, &NewBlockData
->Entry
);
1146 // Insert new block data into the array tail.
1148 if (Link
== &CurrentBlockArray
->Entry
) {
1149 InsertTailList (Link
, &NewBlockData
->Entry
);
1153 // If '\0', parsing is finished.
1155 if (*StringPtr
== 0) {
1159 // Go to next ConfigBlock
1164 // Merge the aligned block data into the single block data.
1166 Link
= CurrentBlockArray
->Entry
.ForwardLink
;
1167 while ((Link
!= &CurrentBlockArray
->Entry
) && (Link
->ForwardLink
!= &CurrentBlockArray
->Entry
)) {
1168 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1169 NewBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1170 if ((NewBlockData
->Offset
>= BlockData
->Offset
) && (NewBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1171 if ((NewBlockData
->Offset
+ NewBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1172 BlockData
->Width
= (UINT16
) (NewBlockData
->Offset
+ NewBlockData
->Width
- BlockData
->Offset
);
1174 RemoveEntryList (Link
->ForwardLink
);
1175 FreePool (NewBlockData
);
1178 Link
= Link
->ForwardLink
;
1182 // 2. Check IFR value is in block data, then Validate Vaule
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
:
1233 // Check the matched VarStoreId is found.
1235 if (IfrVarStore
== NULL
) {
1236 Status
= EFI_NOT_FOUND
;
1240 case EFI_IFR_ONE_OF_OP
:
1242 // Check whether current value is the one of option.
1246 // Check whether this question is for the requested varstore.
1248 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1249 if (IfrOneOf
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1254 // Get Offset by Question header and Width by DataType Flags
1256 Offset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1257 Width
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1259 // Check whether this question is in current block array.
1261 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1263 // This question is not in the current configuration string. Skip it.
1268 // Check this var question is in the var storage
1270 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1272 // This question exceeds the var store size.
1274 Status
= EFI_INVALID_PARAMETER
;
1279 // Get the current value for oneof opcode
1282 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1284 // Set Block Data, to be checked in the following Oneof option opcode.
1286 VarBlockData
.Offset
= Offset
;
1287 VarBlockData
.Width
= Width
;
1288 VarBlockData
.OpCode
= IfrOpHdr
->OpCode
;
1289 VarBlockData
.Scope
= IfrOpHdr
->Scope
;
1291 case EFI_IFR_NUMERIC_OP
:
1293 // Check the current value is in the numeric range.
1297 // Check whether this question is for the requested varstore.
1299 IfrNumeric
= (EFI_IFR_NUMERIC
*) IfrOpHdr
;
1300 if (IfrNumeric
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1305 // Get Offset by Question header and Width by DataType Flags
1307 Offset
= IfrNumeric
->Question
.VarStoreInfo
.VarOffset
;
1308 Width
= (UINT16
) (1 << (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1310 // Check whether this question is in current block array.
1312 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1314 // This question is not in the current configuration string. Skip it.
1319 // Check this var question is in the var storage
1321 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1323 // This question exceeds the var store size.
1325 Status
= EFI_INVALID_PARAMETER
;
1330 // Check the current value is in the numeric range.
1333 CopyMem (&VarValue
, VarBuffer
+ Offset
, Width
);
1334 switch (IfrNumeric
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1335 case EFI_IFR_NUMERIC_SIZE_1
:
1336 if ((UINT8
) VarValue
< IfrNumeric
->data
.u8
.MinValue
|| (UINT8
) VarValue
> IfrNumeric
->data
.u8
.MaxValue
) {
1338 // Not in the valid range.
1340 Status
= EFI_INVALID_PARAMETER
;
1344 case EFI_IFR_NUMERIC_SIZE_2
:
1345 if ((UINT16
) VarValue
< IfrNumeric
->data
.u16
.MinValue
|| (UINT16
) VarValue
> IfrNumeric
->data
.u16
.MaxValue
) {
1347 // Not in the valid range.
1349 Status
= EFI_INVALID_PARAMETER
;
1353 case EFI_IFR_NUMERIC_SIZE_4
:
1354 if ((UINT32
) VarValue
< IfrNumeric
->data
.u32
.MinValue
|| (UINT32
) VarValue
> IfrNumeric
->data
.u32
.MaxValue
) {
1356 // Not in the valid range.
1358 Status
= EFI_INVALID_PARAMETER
;
1362 case EFI_IFR_NUMERIC_SIZE_8
:
1363 if ((UINT64
) VarValue
< IfrNumeric
->data
.u64
.MinValue
|| (UINT64
) VarValue
> IfrNumeric
->data
.u64
.MaxValue
) {
1365 // Not in the valid range.
1367 Status
= EFI_INVALID_PARAMETER
;
1374 case EFI_IFR_CHECKBOX_OP
:
1376 // Check value is BOOLEAN type, only 0 and 1 is valid.
1380 // Check whether this question is for the requested varstore.
1382 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1383 if (IfrCheckBox
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1388 // Get Offset by Question header
1390 Offset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1391 Width
= sizeof (BOOLEAN
);
1393 // Check whether this question is in current block array.
1395 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1397 // This question is not in the current configuration string. Skip it.
1402 // Check this var question is in the var storage
1404 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1406 // This question exceeds the var store size.
1408 Status
= EFI_INVALID_PARAMETER
;
1413 // Boolean type, only 1 and 0 is valid.
1415 if (*(VarBuffer
+ Offset
) > 1) {
1416 Status
= EFI_INVALID_PARAMETER
;
1421 case EFI_IFR_STRING_OP
:
1423 // Check current string length is less than maxsize
1427 // Check whether this question is for the requested varstore.
1429 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1430 if (IfrString
->Question
.VarStoreId
!= IfrVarStore
->VarStoreId
) {
1435 // Get Offset/Width by Question header and OneOf Flags
1437 Offset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1438 Width
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1440 // Check whether this question is in current block array.
1442 if (!BlockArrayCheck (CurrentBlockArray
, Offset
, Width
)) {
1444 // This question is not in the current configuration string. Skip it.
1449 // Check this var question is in the var storage
1451 if ((Offset
+ Width
) > IfrVarStore
->Size
) {
1453 // This question exceeds the var store size.
1455 Status
= EFI_INVALID_PARAMETER
;
1460 // Check current string length is less than maxsize
1462 if (StrSize ((CHAR16
*) (VarBuffer
+ Offset
)) > Width
) {
1463 Status
= EFI_INVALID_PARAMETER
;
1467 case EFI_IFR_ONE_OF_OPTION_OP
:
1469 // Opcode Scope is zero. This one of option is not to be checked.
1471 if (VarBlockData
.Scope
== 0) {
1476 // Only check for OneOf and OrderList opcode
1478 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1479 if (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
) {
1481 // Check current value is the value of one of option.
1483 if (VarValue
== IfrOneOfOption
->Value
.u64
) {
1485 // The value is one of option value.
1486 // Set OpCode to Zero, don't need check again.
1488 VarBlockData
.OpCode
= 0;
1493 case EFI_IFR_END_OP
:
1495 // Decrease opcode scope for the validated opcode
1497 if (VarBlockData
.Scope
> 0) {
1498 VarBlockData
.Scope
--;
1502 // OneOf value doesn't belong to one of option value.
1504 if (VarBlockData
.OpCode
== EFI_IFR_ONE_OF_OP
) {
1505 Status
= EFI_INVALID_PARAMETER
;
1511 // Increase Scope for the validated opcode
1513 if (VarBlockData
.Scope
> 0) {
1514 VarBlockData
.Scope
= (UINT8
) (VarBlockData
.Scope
+ IfrOpHdr
->Scope
);
1519 // Go to the next opcode
1521 IfrOffset
+= IfrOpHdr
->Length
;
1524 // Only one form is in a package list.
1530 // Go to next package.
1532 PackageOffset
+= PacakgeHeader
.Length
;
1536 if (VarBuffer
!= NULL
) {
1537 FreePool (VarBuffer
);
1540 if (CurrentBlockArray
!= NULL
) {
1542 // Free Link Array CurrentBlockArray
1544 while (!IsListEmpty (&CurrentBlockArray
->Entry
)) {
1545 BlockData
= BASE_CR (CurrentBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1546 RemoveEntryList (&BlockData
->Entry
);
1547 FreePool (BlockData
);
1549 FreePool (CurrentBlockArray
);
1556 This function shares the same logic to parse ConfigAltResp string
1557 for setting default value and validating current setting.
1559 1. For setting default action, Reset the default value specified by DefaultId
1560 to the driver configuration got by Request string.
1561 2. For validating current setting, Validate the current configuration
1562 by parsing HII form IFR opcode.
1564 NULL request string support depends on the ExportConfig interface of
1565 HiiConfigRouting protocol in UEFI specification.
1567 @param Request A null-terminated Unicode string in
1568 <MultiConfigRequest> format. It can be NULL.
1569 If it is NULL, all current configuration for the
1570 entirety of the current HII database will be validated.
1571 If it is NULL, all configuration for the
1572 entirety of the current HII database will be reset.
1573 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.
1574 @param ActionType Action supports setting defaults and validate current setting.
1576 @retval TURE Action runs successfully.
1577 @retval FALSE Action is not valid or Action can't be executed successfully..
1581 InternalHiiIfrValueAction (
1582 IN CONST EFI_STRING Request
, OPTIONAL
1583 IN UINT16 DefaultId
,
1587 EFI_STRING ConfigAltResp
;
1588 EFI_STRING ConfigAltHdr
;
1589 EFI_STRING ConfigResp
;
1590 EFI_STRING Progress
;
1591 EFI_STRING StringPtr
;
1592 EFI_STRING StringHdr
;
1594 EFI_HANDLE DriverHandle
;
1595 EFI_HANDLE TempDriverHandle
;
1596 EFI_HII_HANDLE
*HiiHandleBuffer
;
1597 EFI_HII_HANDLE HiiHandle
;
1601 EFI_STRING_ID DefaultName
;
1605 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1606 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1607 UINT32 PackageOffset
;
1608 UINTN PackageListLength
;
1609 EFI_HII_PACKAGE_HEADER PacakgeHeader
;
1610 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1611 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1613 ConfigAltResp
= NULL
;
1618 ConfigAltHdr
= NULL
;
1619 HiiHandleBuffer
= NULL
;
1621 TempDriverHandle
= NULL
;
1624 HiiPackageList
= NULL
;
1627 // Only support set default and validate setting action.
1629 if ((ActionType
!= ACTION_SET_DEFAUTL_VALUE
) && (ActionType
!= ACTION_VALIDATE_SETTING
)) {
1634 // Get the full requested value and deault value string.
1636 if (Request
!= NULL
) {
1637 Status
= gHiiConfigRouting
->ExtractConfig (
1644 Status
= gHiiConfigRouting
->ExportConfig (
1650 if (EFI_ERROR (Status
)) {
1654 StringPtr
= ConfigAltResp
;
1656 while (StringPtr
!= L
'\0') {
1658 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1660 StringHdr
= StringPtr
;
1665 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1666 Status
= EFI_INVALID_PARAMETER
;
1669 StringPtr
+= StrLen (L
"GUID=");
1670 Status
= InternalHiiGetBufferFromString (StringPtr
, GUID_CONFIG_STRING_TYPE
, (UINT8
**) &VarGuid
);
1671 if (EFI_ERROR (Status
)) {
1676 // Get Name value VarName
1678 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1681 if (*StringPtr
== L
'\0') {
1682 Status
= EFI_INVALID_PARAMETER
;
1685 StringPtr
+= StrLen (L
"&NAME=");
1686 Status
= InternalHiiGetBufferFromString (StringPtr
, NAME_CONFIG_STRING_TYPE
, (UINT8
**) &VarName
);
1687 if (EFI_ERROR (Status
)) {
1692 // Get Path value DevicePath
1694 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1697 if (*StringPtr
== L
'\0') {
1698 Status
= EFI_INVALID_PARAMETER
;
1701 StringPtr
+= StrLen (L
"&PATH=");
1702 Status
= InternalHiiGetBufferFromString (StringPtr
, PATH_CONFIG_STRING_TYPE
, (UINT8
**) &DevicePath
);
1703 if (EFI_ERROR (Status
)) {
1708 // Get the Driver handle by the got device path.
1710 TempDevicePath
= DevicePath
;
1711 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDevicePath
, &DriverHandle
);
1712 if (EFI_ERROR (Status
)) {
1717 // Find the matched Hii Handle for the found Driver handle
1719 HiiHandleBuffer
= HiiGetHiiHandles (NULL
);
1720 if (HiiHandleBuffer
== NULL
) {
1721 Status
= EFI_NOT_FOUND
;
1725 for (Index
= 0; HiiHandleBuffer
[Index
] != NULL
; Index
++) {
1726 gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, HiiHandleBuffer
[Index
], &TempDriverHandle
);
1727 if (TempDriverHandle
== DriverHandle
) {
1732 HiiHandle
= HiiHandleBuffer
[Index
];
1733 FreePool (HiiHandleBuffer
);
1735 if (HiiHandle
== NULL
) {
1737 // This request string has no its Hii package.
1738 // Its default value and validating can't execute by parsing IFR data.
1739 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
1741 goto NextConfigAltResp
;
1745 // 2. Get DefaultName string ID by parsing the PacakgeList
1749 // Get HiiPackage by HiiHandle
1751 PackageListLength
= 0;
1752 HiiPackageList
= NULL
;
1753 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
1756 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
1758 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1759 Status
= EFI_INVALID_PARAMETER
;
1763 HiiPackageList
= AllocatePool (PackageListLength
);
1764 if (HiiPackageList
== NULL
) {
1765 Status
= EFI_OUT_OF_RESOURCES
;
1770 // Get PackageList on HiiHandle
1772 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &PackageListLength
, HiiPackageList
);
1773 if (EFI_ERROR (Status
)) {
1778 // Parse the form package and get the default name string ID.
1780 if (ActionType
== ACTION_SET_DEFAUTL_VALUE
) {
1781 PackageOffset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1782 Status
= EFI_NOT_FOUND
;
1783 while (PackageOffset
< PackageListLength
) {
1784 CopyMem (&PacakgeHeader
, (UINT8
*) HiiPackageList
+ PackageOffset
, sizeof (PacakgeHeader
));
1787 // Parse IFR opcode to get default store opcode
1789 if (PacakgeHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1790 IfrOffset
= sizeof (PacakgeHeader
);
1791 PackageData
= (UINT8
*) HiiPackageList
+ PackageOffset
;
1792 while (IfrOffset
< PacakgeHeader
.Length
) {
1793 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (PackageData
+ IfrOffset
);
1795 // Match DefaultId to find its DefaultName
1797 if (IfrOpHdr
->OpCode
== EFI_IFR_DEFAULTSTORE_OP
) {
1798 if (((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
== DefaultId
) {
1799 DefaultName
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultName
;
1800 Status
= EFI_SUCCESS
;
1804 IfrOffset
+= IfrOpHdr
->Length
;
1807 // Only one form is in a package list.
1813 // Go to next package.
1815 PackageOffset
+= PacakgeHeader
.Length
;
1819 // Not found the matched default string ID
1821 if (EFI_ERROR (Status
)) {
1827 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
1828 // Get the default configuration string according to the found defaultname string ID.
1830 Status
= gHiiConfigRouting
->GetAltConfig (
1836 (ActionType
== ACTION_SET_DEFAUTL_VALUE
) ? &DefaultName
:NULL
, // it can be NULL to get the current setting.
1840 if (EFI_ERROR (Status
)) {
1845 // 4. Set the default configuration information or Validate current setting by parse IFR code.
1846 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
1848 if (ActionType
== ACTION_SET_DEFAUTL_VALUE
) {
1850 // Set the default configuration information.
1852 Status
= gHiiConfigRouting
->RouteConfig (gHiiConfigRouting
, ConfigResp
, &Progress
);
1855 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
1857 Status
= InternalHiiValidateCurrentSetting (ConfigResp
, HiiPackageList
, PackageListLength
, VarGuid
, VarName
);
1860 if (EFI_ERROR (Status
)) {
1865 // Free the allocated pacakge buffer and the got ConfigResp string.
1867 if (HiiPackageList
!= NULL
) {
1868 FreePool (HiiPackageList
);
1869 HiiPackageList
= NULL
;
1872 FreePool (ConfigResp
);
1877 // Free the allocated buffer.
1885 FreePool (DevicePath
);
1889 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
1893 // Get and Skip ConfigHdr
1895 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1898 if (*StringPtr
== L
'\0') {
1903 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"
1904 // | 1 | StrLen (ConfigHdr) | 8 | 1 |
1906 ConfigAltHdr
= AllocateZeroPool ((1 + StringPtr
- StringHdr
+ 8 + 1) * sizeof (CHAR16
));
1907 if (ConfigAltHdr
== NULL
) {
1908 Status
= EFI_OUT_OF_RESOURCES
;
1911 StrCpy (ConfigAltHdr
, L
"&");
1912 StrnCat (ConfigAltHdr
, StringHdr
, StringPtr
- StringHdr
);
1913 StrCat (ConfigAltHdr
, L
"&ALTCFG=");
1916 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
1918 while ((StringHdr
= StrStr (StringPtr
, ConfigAltHdr
)) != NULL
) {
1919 StringPtr
= StringHdr
+ StrLen (ConfigAltHdr
);
1920 if (*StringPtr
== L
'\0') {
1926 // Free the allocated ConfigAltHdr string
1928 FreePool (ConfigAltHdr
);
1929 if (*StringPtr
== L
'\0') {
1934 // Find &GUID as the next ConfigHdr
1936 StringPtr
= StrStr (StringPtr
, L
"&GUID");
1937 if (StringPtr
== NULL
) {
1948 if (VarGuid
!= NULL
) {
1952 if (VarName
!= NULL
) {
1956 if (DevicePath
!= NULL
) {
1957 FreePool (DevicePath
);
1960 if (ConfigResp
!= NULL
) {
1961 FreePool (ConfigResp
);
1964 if (ConfigAltResp
!= NULL
) {
1965 FreePool (ConfigAltResp
);
1968 if (HiiPackageList
!= NULL
) {
1969 FreePool (HiiPackageList
);
1972 if (EFI_ERROR (Status
)) {
1980 Validate the current configuration by parsing HII form IFR opcode.
1982 NULL request string support depends on the ExtractConfig interface of
1983 HiiConfigRouting protocol in UEFI specification.
1985 @param Request A null-terminated Unicode string in
1986 <MultiConfigRequest> format. It can be NULL.
1987 If it is NULL, all current configuration for the
1988 entirety of the current HII database will be validated.
1990 @retval TURE Current configuration is valid.
1991 @retval FALSE Current configuration is invalid.
1995 HiiValidateSettings (
1996 IN CONST EFI_STRING Request OPTIONAL
1999 return InternalHiiIfrValueAction (Request
, 0, ACTION_VALIDATE_SETTING
);
2003 Reset the default value specified by DefaultId to the driver
2004 configuration got by Request string.
2006 NULL request string support depends on the ExportConfig interface of
2007 HiiConfigRouting protocol in UEFI specification.
2009 @param Request A null-terminated Unicode string in
2010 <MultiConfigRequest> format. It can be NULL.
2011 If it is NULL, all configuration for the
2012 entirety of the current HII database will be reset.
2013 @param DefaultId Specifies the type of defaults to retrieve.
2015 @retval TURE The default value is set successfully.
2016 @retval FALSE The default value can't be found and set.
2021 IN CONST EFI_STRING Request
, OPTIONAL
2025 return InternalHiiIfrValueAction (Request
, DefaultId
, ACTION_SET_DEFAUTL_VALUE
);
2029 Allocates and returns a Null-terminated Unicode <ConfigAltResp> string.
2031 If Guid is NULL, then ASSERT().
2032 If Name is NULL, then ASSERT().
2033 If BlockNameArray is NULL, then ASSERT().
2035 @param[in] Guid GUID of the buffer storage.
2036 @param[in] Name Name of the buffer storage.
2037 @param[in] DriverHandle The DriverHandle that support a Device Path
2039 @param[in] BufferStorage Content of the buffer storage.
2040 @param[in] BufferStorageSize Length in bytes of the buffer storage.
2041 @param[in] BlockNameArray Array generated by VFR compiler. This array
2042 contains a UINT32 value that is the length
2043 of BlockNameArray in bytes, followed by pairs
2044 of 16-bit values that are the offset and length
2045 values used to contruct a <ConfigRequest> string.
2046 @param[in] ... A variable argument list that contains pairs of 16-bit
2047 ALTCFG identifiers and pointers to DefaultValueArrays.
2048 The variable argument list is terminated by a NULL
2049 DefaultValueArray pointer. A DefaultValueArray
2050 contains a UINT32 value that is the length, in bytes,
2051 of the DefaultValueArray. The UINT32 length value
2052 is followed by a series of records that contain
2053 a 16-bit WIDTH value followed by a byte array with
2054 WIDTH entries. The records must be parsed from
2055 beginning to end until the UINT32 length limit
2058 @retval NULL There are not enough resources to process the request.
2059 @retval NULL A <ConfigResp> could not be retrieved from the Config
2061 @retval Other A pointer to the Null-terminate Unicode <ConfigAltResp>
2067 HiiConstructConfigAltResp (
2068 IN CONST EFI_GUID
*Guid
,
2069 IN CONST CHAR16
*Name
,
2070 IN EFI_HANDLE DriverHandle
,
2071 IN CONST VOID
*BufferStorage
,
2072 IN UINTN BufferStorageSize
,
2073 IN CONST VOID
*BlockNameArray
,
2082 CHAR16
*ConfigRequest
;
2083 EFI_STRING ConfigResp
;
2084 EFI_STRING ConfigAltResp
;
2091 ASSERT (Guid
!= NULL
);
2092 ASSERT (Name
!= NULL
);
2093 ASSERT (BlockNameArray
!= NULL
);
2096 // Initialize local variables
2099 ConfigRequest
= NULL
;
2103 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
2105 ConfigHdr
= HiiConstructConfigHdr (Guid
, Name
, DriverHandle
);
2106 if (ConfigHdr
== NULL
) {
2111 // Compute the length of the entire request starting with <ConfigHdr> and a
2114 Length
= StrLen (ConfigHdr
) + 1;
2117 // Determine the size <BlockName> Offset/Width pairs
2119 Buffer
= (UINT8
*)BlockNameArray
;
2120 BufferEnd
= Buffer
+ ReadUnaligned32 ((UINT32
*)Buffer
);
2121 Buffer
+= sizeof (UINT32
);
2124 // Add <BlockName> length that is composed of one or more Offset/Width pairs
2126 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2127 // | 8 | 4 | 7 | 4 |
2129 Length
+= (((BufferEnd
- Buffer
) / (sizeof (UINT16
) + sizeof (UINT16
))) * (8 + 4 + 7 + 4));
2132 // Allocate buffer for the entire <ConfigRequest>
2134 ConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2135 if (ConfigRequest
== NULL
) {
2138 String
= ConfigRequest
;
2141 // Start with <ConfigHdr>
2143 StrCpy (String
, ConfigHdr
);
2144 String
+= StrLen (String
);
2147 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2149 while (Buffer
< BufferEnd
) {
2151 // Append &OFFSET=XXXX&WIDTH=YYYY
2153 OffsetValue
= ReadUnaligned16 ((UINT16
*)Buffer
);
2154 WidthValue
= ReadUnaligned16 ((UINT16
*)(Buffer
+ sizeof (UINT16
)));
2157 (8 + 4 + 7 + 4) * sizeof (CHAR16
),
2158 L
"&OFFSET=%04X&WIDTH=%04X",
2163 String
+= StrLen (String
);
2164 Buffer
+= (sizeof (UINT16
) + sizeof (UINT16
));
2168 // Get the <ConfigResp>
2170 ConfigResp
= InternalHiiBlockToConfig (ConfigRequest
, BufferStorage
, BufferStorageSize
);
2171 if (ConfigResp
== NULL
) {
2176 // Compute the length of the entire response starting with <ConfigResp> and a
2179 Length
= StrLen (ConfigResp
) + 1;
2182 // Add the length associated with each pair of variable argument parameters
2184 VA_START (Args
, BlockNameArray
);
2186 AltCfgId
= VA_ARG (Args
, UINTN
);
2187 Buffer
= VA_ARG (Args
, UINT8
*);
2188 if (Buffer
== NULL
) {
2193 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2194 // |1| StrLen (ConfigHdr) | 8 | 4 |
2196 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2198 BufferEnd
= Buffer
+ ReadUnaligned32 ((UINT32
*)Buffer
);
2199 Buffer
+= sizeof (UINT32
);
2200 while (Buffer
< BufferEnd
) {
2202 // Extract Width field
2204 Width
= ReadUnaligned16 ((UINT16
*)(Buffer
+ sizeof (UINT16
)));
2207 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2208 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2210 Length
+= (8 + 4 + 7 + 4 + 7 + Width
* 2);
2213 // Update Buffer to the next record
2215 Buffer
+= (sizeof (UINT16
) + sizeof (UINT16
) + Width
);
2221 // Allocate a buffer for the entire response
2223 ConfigAltResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2224 if (ConfigAltResp
== NULL
) {
2227 String
= ConfigAltResp
;
2232 StrCpy (String
, ConfigResp
);
2233 String
+= StrLen (String
);
2236 // Add <AltResp> for each pair of variable argument parameters
2238 VA_START (Args
, BlockNameArray
);
2240 AltCfgId
= VA_ARG (Args
, UINTN
);
2241 Buffer
= VA_ARG (Args
, UINT8
*);
2242 if (Buffer
== NULL
) {
2247 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX"
2248 // |1| StrLen (ConfigHdr) | 8 | 4 |
2252 (1 + StrLen (ConfigHdr
) + 8 + 4) * sizeof (CHAR16
),
2257 String
+= StrLen (String
);
2260 // Add <ConfigBody> ::= <ConfigElement>*
2262 BufferEnd
= Buffer
+ ReadUnaligned32 ((UINT32
*)Buffer
);
2263 Buffer
+= sizeof (UINT32
);
2264 while (Buffer
< BufferEnd
) {
2266 // Extract Width field
2268 Width
= ReadUnaligned16 ((UINT16
*)(Buffer
+ sizeof (UINT16
)));
2271 // Add <BlockConfig>
2275 (8 + 4 + 7 + 4 + 7 + Width
* 2) * sizeof (CHAR16
),
2276 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2277 ReadUnaligned16 ((UINT16
*)Buffer
),
2280 String
+= StrLen (String
);
2283 // Update Buffer to point to the value in the current record
2285 Buffer
+= (sizeof (UINT16
) + sizeof (UINT16
));
2288 // Convert Value to a hex string in "%x" format
2289 // NOTE: This is in the opposite byte that GUID and PATH use
2291 for (; Width
> 0; Width
--) {
2292 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, Buffer
[Width
- 1], 2);
2295 // Update Buffer to the next record
2303 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
2305 return InternalHiiLowerConfigString (ConfigAltResp
);
2308 if (ConfigHdr
!= NULL
) {
2309 FreePool (ConfigHdr
);
2311 if (ConfigRequest
!= NULL
) {
2312 FreePool (ConfigRequest
);
2314 if (ConfigResp
!= NULL
) {
2315 FreePool (ConfigResp
);
2322 Determines if two values in config strings match.
2324 Compares the substring between StartSearchString and StopSearchString in
2325 FirstString to the substring between StartSearchString and StopSearchString
2326 in SecondString. If the two substrings match, then TRUE is returned. If the
2327 two substrings do not match, then FALSE is returned.
2329 If FirstString is NULL, then ASSERT().
2330 If SecondString is NULL, then ASSERT().
2331 If StartSearchString is NULL, then ASSERT().
2332 If StopSearchString is NULL, then ASSERT().
2334 @param FirstString Pointer to the first Null-terminated Unicode string.
2335 @param SecondString Pointer to the second Null-terminated Unicode string.
2336 @param StartSearchString Pointer to the Null-terminated Unicode string that
2337 marks the start of the value string to compare.
2338 @param StopSearchString Pointer to the Null-terminated Unicode string that
2339 marks the end of the vakue string to compare.
2341 @retval FALSE StartSearchString is not present in FirstString.
2342 @retval FALSE StartSearchString is not present in SecondString.
2343 @retval FALSE StopSearchString is not present in FirstString.
2344 @retval FALSE StopSearchString is not present in SecondString.
2345 @retval FALSE The length of the substring in FirstString is not the
2346 same length as the substring in SecondString.
2347 @retval FALSE The value string in FirstString does not matche the
2348 value string in SecondString.
2349 @retval TRUE The value string in FirstString matches the value
2350 string in SecondString.
2355 InternalHiiCompareSubString (
2356 IN CHAR16
*FirstString
,
2357 IN CHAR16
*SecondString
,
2358 IN CHAR16
*StartSearchString
,
2359 IN CHAR16
*StopSearchString
2362 CHAR16
*EndFirstString
;
2363 CHAR16
*EndSecondString
;
2365 ASSERT (FirstString
!= NULL
);
2366 ASSERT (SecondString
!= NULL
);
2367 ASSERT (StartSearchString
!= NULL
);
2368 ASSERT (StopSearchString
!= NULL
);
2370 FirstString
= StrStr (FirstString
, StartSearchString
);
2371 if (FirstString
== NULL
) {
2375 SecondString
= StrStr (SecondString
, StartSearchString
);
2376 if (SecondString
== NULL
) {
2380 EndFirstString
= StrStr (FirstString
, StopSearchString
);
2381 if (EndFirstString
== NULL
) {
2385 EndSecondString
= StrStr (SecondString
, StopSearchString
);
2386 if (EndSecondString
== NULL
) {
2390 if ((EndFirstString
- FirstString
) != (EndSecondString
- SecondString
)) {
2394 return (BOOLEAN
)(StrnCmp (FirstString
, SecondString
, EndFirstString
- FirstString
) == 0);
2398 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
2400 If ConfigHdr is NULL, then ASSERT().
2402 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
2403 @param[in] Guid GUID of the storage.
2404 @param[in] Name NAME of the storage.
2406 @retval TRUE Routing information matches <ConfigHdr>.
2407 @retval FALSE Routing information does not match <ConfigHdr>.
2412 HiiIsConfigHdrMatch (
2413 IN CONST EFI_STRING ConfigHdr
,
2414 IN CONST EFI_GUID
*Guid
, OPTIONAL
2415 IN CONST CHAR16
*Name OPTIONAL
2418 EFI_STRING CompareConfigHdr
;
2421 ASSERT (ConfigHdr
!= NULL
);
2424 // Use Guid and Name to generate a <ConfigHdr> string
2426 CompareConfigHdr
= HiiConstructConfigHdr (Guid
, Name
, NULL
);
2427 if (CompareConfigHdr
== NULL
) {
2434 // Compare GUID value strings
2436 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"GUID=", L
"&NAME=");
2439 if (Result
&& Name
!= NULL
) {
2441 // Compare NAME value strings
2443 Result
= InternalHiiCompareSubString (ConfigHdr
, CompareConfigHdr
, L
"&NAME=", L
"&PATH=");
2447 // Free the <ConfigHdr> string
2449 FreePool (CompareConfigHdr
);
2455 Retrieves uncommited data from the Form Browser and converts it to a binary
2458 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2459 is an optional parameter that may be NULL.
2460 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2461 parameter that may be NULL.
2462 @param[in] BufferSize Length in bytes of buffer to hold retrived data.
2463 @param[out] Block Buffer of data to be updated.
2465 @retval FALSE The uncommitted data could not be retrieved.
2466 @retval TRUE The uncommitted data was retrieved.
2472 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2473 IN CONST CHAR16
*VariableName
, OPTIONAL
2478 EFI_STRING ResultsData
;
2480 EFI_STRING ConfigResp
;
2485 // Retrieve the results data from the Browser Callback
2487 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, NULL
);
2488 if (ResultsData
== NULL
) {
2493 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
2495 Size
= (StrLen (mConfigHdrTemplate
) + 1) * sizeof (CHAR16
);
2496 Size
= Size
+ (StrLen (ResultsData
) + 1) * sizeof (CHAR16
);
2497 ConfigResp
= AllocateZeroPool (Size
);
2498 UnicodeSPrint (ConfigResp
, Size
, L
"%s&%s", mConfigHdrTemplate
, ResultsData
);
2501 // Free the allocated buffer
2503 FreePool (ResultsData
);
2504 if (ConfigResp
== NULL
) {
2509 // Convert <ConfigResp> to a buffer
2511 Status
= gHiiConfigRouting
->ConfigToBlock (
2519 // Free the allocated buffer
2521 FreePool (ConfigResp
);
2523 if (EFI_ERROR (Status
)) {
2531 Updates uncommitted data in the Form Browser.
2533 If Buffer is NULL, then ASSERT().
2535 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2536 is an optional parameter that may be NULL.
2537 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2538 parameter that may be NULL.
2539 @param[in] BufferSize Length, in bytes, of Buffer.
2540 @param[in] Buffer Buffer of data to commit.
2541 @param[in] RequestElement An optional field to specify which part of the
2542 buffer data will be send back to Browser. If NULL,
2543 the whole buffer of data will be committed to
2545 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
2547 @retval FALSE The uncommitted data could not be updated.
2548 @retval TRUE The uncommitted data was updated.
2554 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
2555 IN CONST CHAR16
*VariableName
, OPTIONAL
2556 IN UINTN BufferSize
,
2557 IN CONST UINT8
*Buffer
,
2558 IN CONST CHAR16
*RequestElement OPTIONAL
2562 EFI_STRING ConfigRequest
;
2563 EFI_STRING ConfigResp
;
2564 EFI_STRING ResultsData
;
2566 ASSERT (Buffer
!= NULL
);
2569 // Construct <ConfigRequest>
2571 if (RequestElement
== NULL
) {
2573 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2574 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2576 Size
= (StrLen (mConfigHdrTemplate
) + 32 + 1) * sizeof (CHAR16
);
2577 ConfigRequest
= AllocateZeroPool (Size
);
2578 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate
, (UINT64
)BufferSize
);
2581 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2582 // followed by <RequestElement> followed by a Null-terminator
2584 Size
= StrLen (mConfigHdrTemplate
) * sizeof (CHAR16
);
2585 Size
= Size
+ (StrLen (RequestElement
) + 1) * sizeof (CHAR16
);
2586 ConfigRequest
= AllocateZeroPool (Size
);
2587 UnicodeSPrint (ConfigRequest
, Size
, L
"%s%s", mConfigHdrTemplate
, RequestElement
);
2589 if (ConfigRequest
== NULL
) {
2594 // Convert <ConfigRequest> to <ConfigResp>
2596 ConfigResp
= InternalHiiBlockToConfig (ConfigRequest
, Buffer
, BufferSize
);
2597 FreePool (ConfigRequest
);
2598 if (ConfigResp
== NULL
) {
2603 // Set data in the uncommitted browser state information
2605 ResultsData
= InternalHiiBrowserCallback (VariableGuid
, VariableName
, ConfigResp
+ StrLen(mConfigHdrTemplate
) + 1);
2606 FreePool (ConfigResp
);
2608 return (BOOLEAN
)(ResultsData
!= NULL
);
2611 /////////////////////////////////////////
2612 /////////////////////////////////////////
2614 /////////////////////////////////////////
2615 /////////////////////////////////////////
2617 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
2623 } HII_LIB_OPCODE_BUFFER
;
2626 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
2628 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth
[] = {
2629 1, // EFI_IFR_TYPE_NUM_SIZE_8
2630 2, // EFI_IFR_TYPE_NUM_SIZE_16
2631 4, // EFI_IFR_TYPE_NUM_SIZE_32
2632 8, // EFI_IFR_TYPE_NUM_SIZE_64
2633 1, // EFI_IFR_TYPE_BOOLEAN
2634 3, // EFI_IFR_TYPE_TIME
2635 4, // EFI_IFR_TYPE_DATE
2636 2 // EFI_IFR_TYPE_STRING
2640 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
2641 HiiFreeOpCodeHandle().
2643 @retval NULL There are not enough resources to allocate a new OpCode Handle.
2644 @retval Other A new OpCode handle.
2649 HiiAllocateOpCodeHandle (
2653 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2655 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER
));
2656 if (OpCodeBuffer
== NULL
) {
2659 OpCodeBuffer
->Buffer
= (UINT8
*)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE
);
2660 if (OpCodeBuffer
->Buffer
== NULL
) {
2661 FreePool (OpCodeBuffer
);
2664 OpCodeBuffer
->BufferSize
= HII_LIB_OPCODE_ALLOCATION_SIZE
;
2665 OpCodeBuffer
->Position
= 0;
2666 return (VOID
*)OpCodeBuffer
;
2670 Frees an OpCode Handle that was peviously allocated with HiiAllocateOpCodeHandle().
2671 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
2672 Handle are also freed.
2674 If OpCodeHandle is NULL, then ASSERT().
2679 HiiFreeOpCodeHandle (
2683 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2685 ASSERT (OpCodeHandle
!= NULL
);
2687 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2688 if (OpCodeBuffer
->Buffer
!= NULL
) {
2689 FreePool (OpCodeBuffer
->Buffer
);
2691 FreePool (OpCodeBuffer
);
2696 InternalHiiOpCodeHandlePosition (
2697 IN VOID
*OpCodeHandle
2700 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Position
;
2705 InternalHiiOpCodeHandleBuffer (
2706 IN VOID
*OpCodeHandle
2709 return ((HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
)->Buffer
;
2714 InternalHiiGrowOpCodeHandle (
2719 HII_LIB_OPCODE_BUFFER
*OpCodeBuffer
;
2722 ASSERT (OpCodeHandle
!= NULL
);
2724 OpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)OpCodeHandle
;
2725 if (OpCodeBuffer
->Position
+ Size
> OpCodeBuffer
->BufferSize
) {
2726 Buffer
= ReallocatePool (
2727 OpCodeBuffer
->BufferSize
,
2728 OpCodeBuffer
->BufferSize
+ (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
),
2729 OpCodeBuffer
->Buffer
2731 if (Buffer
== NULL
) {
2734 OpCodeBuffer
->Buffer
= Buffer
;
2735 OpCodeBuffer
->BufferSize
+= (Size
+ HII_LIB_OPCODE_ALLOCATION_SIZE
);
2737 Buffer
= OpCodeBuffer
->Buffer
+ OpCodeBuffer
->Position
;
2738 OpCodeBuffer
->Position
+= Size
;
2744 InternalHiiCreateOpCodeExtended (
2745 IN VOID
*OpCodeHandle
,
2746 IN VOID
*OpCodeTemplate
,
2748 IN UINTN OpCodeSize
,
2749 IN UINTN ExtensionSize
,
2753 EFI_IFR_OP_HEADER
*Header
;
2756 ASSERT (OpCodeTemplate
!= NULL
);
2757 ASSERT ((OpCodeSize
+ ExtensionSize
) <= 0x7F);
2759 Header
= (EFI_IFR_OP_HEADER
*)OpCodeTemplate
;
2760 Header
->OpCode
= OpCode
;
2761 Header
->Scope
= Scope
;
2762 Header
->Length
= (UINT8
)(OpCodeSize
+ ExtensionSize
);
2763 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, Header
->Length
);
2764 return (UINT8
*)CopyMem (Buffer
, Header
, OpCodeSize
);
2769 InternalHiiCreateOpCode (
2770 IN VOID
*OpCodeHandle
,
2771 IN VOID
*OpCodeTemplate
,
2776 return InternalHiiCreateOpCodeExtended (OpCodeHandle
, OpCodeTemplate
, OpCode
, OpCodeSize
, 0, 0);
2780 Append raw opcodes to an OpCodeHandle.
2782 If OpCodeHandle is NULL, then ASSERT().
2783 If RawBuffer is NULL, then ASSERT();
2785 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2786 @param[in] RawBuffer Buffer of opcodes to append.
2787 @param[in] RawBufferSize The size, in bytes, of Buffer.
2789 @retval NULL There is not enough space left in Buffer to add the opcode.
2790 @retval Other A pointer to the appended opcodes.
2795 HiiCreateRawOpCodes (
2796 IN VOID
*OpCodeHandle
,
2797 IN UINT8
*RawBuffer
,
2798 IN UINTN RawBufferSize
2803 ASSERT (RawBuffer
!= NULL
);
2805 Buffer
= InternalHiiGrowOpCodeHandle (OpCodeHandle
, RawBufferSize
);
2806 return (UINT8
*)CopyMem (Buffer
, RawBuffer
, RawBufferSize
);
2810 Append opcodes from one OpCode Handle to another OpCode handle.
2812 If OpCodeHandle is NULL, then ASSERT().
2813 If RawOpCodeHandle is NULL, then ASSERT();
2815 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2816 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
2818 @retval NULL There is not enough space left in Buffer to add the opcode.
2819 @retval Other A pointer to the appended opcodes.
2824 InternalHiiAppendOpCodes (
2825 IN VOID
*OpCodeHandle
,
2826 IN VOID
*RawOpCodeHandle
2829 HII_LIB_OPCODE_BUFFER
*RawOpCodeBuffer
;
2831 ASSERT (RawOpCodeHandle
!= NULL
);
2833 RawOpCodeBuffer
= (HII_LIB_OPCODE_BUFFER
*)RawOpCodeHandle
;
2834 return HiiCreateRawOpCodes (OpCodeHandle
, RawOpCodeBuffer
->Buffer
, RawOpCodeBuffer
->Position
);
2838 Create EFI_IFR_END_OP opcode.
2840 If OpCodeHandle is NULL, then ASSERT().
2842 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2844 @retval NULL There is not enough space left in Buffer to add the opcode.
2845 @retval Other A pointer to the created opcode.
2850 HiiCreateEndOpCode (
2851 IN VOID
*OpCodeHandle
2856 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_END_OP
, sizeof (OpCode
));
2860 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
2862 If OpCodeHandle is NULL, then ASSERT().
2863 If Type is invalid, then ASSERT().
2864 If Flags is invalid, then ASSERT().
2866 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2867 @param[in] StringId StringId for the option
2868 @param[in] Flags Flags for the option
2869 @param[in] Type Type for the option
2870 @param[in] Value Value for the option
2872 @retval NULL There is not enough space left in Buffer to add the opcode.
2873 @retval Other A pointer to the created opcode.
2878 HiiCreateOneOfOptionOpCode (
2879 IN VOID
*OpCodeHandle
,
2886 EFI_IFR_ONE_OF_OPTION OpCode
;
2888 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
2890 ZeroMem (&OpCode
, sizeof (OpCode
));
2891 OpCode
.Option
= StringId
;
2892 OpCode
.Flags
= (UINT8
) (Flags
& (EFI_IFR_OPTION_DEFAULT
| EFI_IFR_OPTION_DEFAULT_MFG
));
2894 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
2896 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OPTION_OP
, sizeof (OpCode
));
2900 Create EFI_IFR_DEFAULT_OP opcode.
2902 If OpCodeHandle is NULL, then ASSERT().
2903 If Type is invalid, then ASSERT().
2905 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2906 @param[in] DefaultId DefaultId for the default
2907 @param[in] Type Type for the default
2908 @param[in] Value Value for the default
2910 @retval NULL There is not enough space left in Buffer to add the opcode.
2911 @retval Other A pointer to the created opcode.
2916 HiiCreateDefaultOpCode (
2917 IN VOID
*OpCodeHandle
,
2918 IN UINT16 DefaultId
,
2923 EFI_IFR_DEFAULT OpCode
;
2925 ASSERT (Type
< EFI_IFR_TYPE_OTHER
);
2927 ZeroMem (&OpCode
, sizeof (OpCode
));
2929 OpCode
.DefaultId
= DefaultId
;
2930 CopyMem (&OpCode
.Value
, &Value
, mHiiDefaultTypeToWidth
[Type
]);
2932 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_DEFAULT_OP
, sizeof (OpCode
));
2936 Create EFI_IFR_GUID opcode.
2938 If OpCodeHandle is NULL, then ASSERT().
2939 If Guid is NULL, then ASSERT().
2940 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
2942 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2943 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
2944 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
2945 optional parameter that may be NULL. If this
2946 parameter is NULL, then the GUID extension
2947 region of the created opcode is filled with zeros.
2948 If this parameter is not NULL, then the GUID
2949 extension region of GuidData will be copied to
2950 the GUID extension region of the created opcode.
2951 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
2952 must be >= sizeof(EFI_IFR_GUID).
2954 @retval NULL There is not enough space left in Buffer to add the opcode.
2955 @retval Other A pointer to the created opcode.
2960 HiiCreateGuidOpCode (
2961 IN VOID
*OpCodeHandle
,
2962 IN CONST EFI_GUID
*Guid
,
2963 IN CONST VOID
*GuidOpCode
, OPTIONAL
2967 EFI_IFR_GUID OpCode
;
2968 EFI_IFR_GUID
*OpCodePointer
;
2970 ASSERT (Guid
!= NULL
);
2971 ASSERT (OpCodeSize
>= sizeof (OpCode
));
2973 ZeroMem (&OpCode
, sizeof (OpCode
));
2974 CopyGuid ((EFI_GUID
*)(VOID
*)&OpCode
.Guid
, Guid
);
2976 OpCodePointer
= (EFI_IFR_GUID
*)InternalHiiCreateOpCodeExtended (
2981 OpCodeSize
- sizeof (OpCode
),
2984 if (OpCodePointer
!= NULL
&& GuidOpCode
!= NULL
) {
2985 CopyMem (OpCodePointer
+ 1, (EFI_IFR_GUID
*)GuidOpCode
+ 1, OpCodeSize
- sizeof (OpCode
));
2987 return (UINT8
*)OpCodePointer
;
2991 Create EFI_IFR_ACTION_OP opcode.
2993 If OpCodeHandle is NULL, then ASSERT().
2994 If any reserved bits are set in QuestionFlags, then ASSERT().
2996 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2997 @param[in] QuestionId Question ID
2998 @param[in] Prompt String ID for Prompt
2999 @param[in] Help String ID for Help
3000 @param[in] QuestionFlags Flags in Question Header
3001 @param[in] QuestionConfig String ID for configuration
3003 @retval NULL There is not enough space left in Buffer to add the opcode.
3004 @retval Other A pointer to the created opcode.
3009 HiiCreateActionOpCode (
3010 IN VOID
*OpCodeHandle
,
3011 IN EFI_QUESTION_ID QuestionId
,
3012 IN EFI_STRING_ID Prompt
,
3013 IN EFI_STRING_ID Help
,
3014 IN UINT8 QuestionFlags
,
3015 IN EFI_STRING_ID QuestionConfig
3018 EFI_IFR_ACTION OpCode
;
3020 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3022 ZeroMem (&OpCode
, sizeof (OpCode
));
3023 OpCode
.Question
.QuestionId
= QuestionId
;
3024 OpCode
.Question
.Header
.Prompt
= Prompt
;
3025 OpCode
.Question
.Header
.Help
= Help
;
3026 OpCode
.Question
.Flags
= QuestionFlags
;
3027 OpCode
.QuestionConfig
= QuestionConfig
;
3029 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_ACTION_OP
, sizeof (OpCode
));
3033 Create EFI_IFR_SUBTITLE_OP opcode.
3035 If OpCodeHandle is NULL, then ASSERT().
3036 If any reserved bits are set in Flags, then ASSERT().
3037 If Scope > 1, then ASSERT().
3039 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3040 @param[in] Prompt String ID for Prompt
3041 @param[in] Help String ID for Help
3042 @param[in] Flags Subtitle opcode flags
3043 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
3044 0 if this opcode is within the current scope.
3046 @retval NULL There is not enough space left in Buffer to add the opcode.
3047 @retval Other A pointer to the created opcode.
3052 HiiCreateSubTitleOpCode (
3053 IN VOID
*OpCodeHandle
,
3054 IN EFI_STRING_ID Prompt
,
3055 IN EFI_STRING_ID Help
,
3060 EFI_IFR_SUBTITLE OpCode
;
3062 ASSERT (Scope
<= 1);
3063 ASSERT ((Flags
& (~(EFI_IFR_FLAGS_HORIZONTAL
))) == 0);
3065 ZeroMem (&OpCode
, sizeof (OpCode
));
3066 OpCode
.Statement
.Prompt
= Prompt
;
3067 OpCode
.Statement
.Help
= Help
;
3068 OpCode
.Flags
= Flags
;
3070 return InternalHiiCreateOpCodeExtended (
3073 EFI_IFR_SUBTITLE_OP
,
3081 Create EFI_IFR_REF_OP opcode.
3083 If OpCodeHandle is NULL, then ASSERT().
3084 If any reserved bits are set in QuestionFlags, then ASSERT().
3086 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3087 @param[in] FormId Destination Form ID
3088 @param[in] Prompt String ID for Prompt
3089 @param[in] Help String ID for Help
3090 @param[in] QuestionFlags Flags in Question Header
3091 @param[in] QuestionId Question ID
3093 @retval NULL There is not enough space left in Buffer to add the opcode.
3094 @retval Other A pointer to the created opcode.
3099 HiiCreateGotoOpCode (
3100 IN VOID
*OpCodeHandle
,
3101 IN EFI_FORM_ID FormId
,
3102 IN EFI_STRING_ID Prompt
,
3103 IN EFI_STRING_ID Help
,
3104 IN UINT8 QuestionFlags
,
3105 IN EFI_QUESTION_ID QuestionId
3110 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3112 ZeroMem (&OpCode
, sizeof (OpCode
));
3113 OpCode
.Question
.Header
.Prompt
= Prompt
;
3114 OpCode
.Question
.Header
.Help
= Help
;
3115 OpCode
.Question
.QuestionId
= QuestionId
;
3116 OpCode
.Question
.Flags
= QuestionFlags
;
3117 OpCode
.FormId
= FormId
;
3119 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_REF_OP
, sizeof (OpCode
));
3123 Create EFI_IFR_CHECKBOX_OP opcode.
3125 If OpCodeHandle is NULL, then ASSERT().
3126 If any reserved bits are set in QuestionFlags, then ASSERT().
3127 If any reserved bits are set in CheckBoxFlags, then ASSERT().
3129 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3130 @param[in] QuestionId Question ID
3131 @param[in] VarStoreId Storage ID
3132 @param[in] VarOffset Offset in Storage
3133 @param[in] Prompt String ID for Prompt
3134 @param[in] Help String ID for Help
3135 @param[in] QuestionFlags Flags in Question Header
3136 @param[in] CheckBoxFlags Flags for checkbox opcode
3137 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3138 is an optional parameter that may be NULL.
3140 @retval NULL There is not enough space left in Buffer to add the opcode.
3141 @retval Other A pointer to the created opcode.
3146 HiiCreateCheckBoxOpCode (
3147 IN VOID
*OpCodeHandle
,
3148 IN EFI_QUESTION_ID QuestionId
,
3149 IN EFI_VARSTORE_ID VarStoreId
,
3150 IN UINT16 VarOffset
,
3151 IN EFI_STRING_ID Prompt
,
3152 IN EFI_STRING_ID Help
,
3153 IN UINT8 QuestionFlags
,
3154 IN UINT8 CheckBoxFlags
,
3155 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3158 EFI_IFR_CHECKBOX OpCode
;
3161 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3163 ZeroMem (&OpCode
, sizeof (OpCode
));
3164 OpCode
.Question
.QuestionId
= QuestionId
;
3165 OpCode
.Question
.VarStoreId
= VarStoreId
;
3166 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3167 OpCode
.Question
.Header
.Prompt
= Prompt
;
3168 OpCode
.Question
.Header
.Help
= Help
;
3169 OpCode
.Question
.Flags
= QuestionFlags
;
3170 OpCode
.Flags
= CheckBoxFlags
;
3172 if (DefaultsOpCodeHandle
== NULL
) {
3173 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
));
3176 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3177 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_CHECKBOX_OP
, sizeof (OpCode
), 0, 1);
3178 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3179 HiiCreateEndOpCode (OpCodeHandle
);
3180 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3184 Create EFI_IFR_NUMERIC_OP opcode.
3186 If OpCodeHandle is NULL, then ASSERT().
3187 If any reserved bits are set in QuestionFlags, then ASSERT().
3188 If any reserved bits are set in NumericFlags, then ASSERT().
3190 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3191 @param[in] QuestionId Question ID
3192 @param[in] VarStoreId Storage ID
3193 @param[in] VarOffset Offset in Storage
3194 @param[in] Prompt String ID for Prompt
3195 @param[in] Help String ID for Help
3196 @param[in] QuestionFlags Flags in Question Header
3197 @param[in] NumericFlags Flags for numeric opcode
3198 @param[in] Minimum Numeric minimum value
3199 @param[in] Maximum Numeric maximum value
3200 @param[in] Step Numeric step for edit
3201 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3202 is an optional parameter that may be NULL.
3204 @retval NULL There is not enough space left in Buffer to add the opcode.
3205 @retval Other A pointer to the created opcode.
3210 HiiCreateNumericOpCode (
3211 IN VOID
*OpCodeHandle
,
3212 IN EFI_QUESTION_ID QuestionId
,
3213 IN EFI_VARSTORE_ID VarStoreId
,
3214 IN UINT16 VarOffset
,
3215 IN EFI_STRING_ID Prompt
,
3216 IN EFI_STRING_ID Help
,
3217 IN UINT8 QuestionFlags
,
3218 IN UINT8 NumericFlags
,
3222 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3225 EFI_IFR_NUMERIC OpCode
;
3228 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3230 ZeroMem (&OpCode
, sizeof (OpCode
));
3231 OpCode
.Question
.QuestionId
= QuestionId
;
3232 OpCode
.Question
.VarStoreId
= VarStoreId
;
3233 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3234 OpCode
.Question
.Header
.Prompt
= Prompt
;
3235 OpCode
.Question
.Header
.Help
= Help
;
3236 OpCode
.Question
.Flags
= QuestionFlags
;
3237 OpCode
.Flags
= NumericFlags
;
3239 switch (NumericFlags
& EFI_IFR_NUMERIC_SIZE
) {
3240 case EFI_IFR_NUMERIC_SIZE_1
:
3241 OpCode
.data
.u8
.MinValue
= (UINT8
)Minimum
;
3242 OpCode
.data
.u8
.MaxValue
= (UINT8
)Maximum
;
3243 OpCode
.data
.u8
.Step
= (UINT8
)Step
;
3246 case EFI_IFR_NUMERIC_SIZE_2
:
3247 OpCode
.data
.u16
.MinValue
= (UINT16
)Minimum
;
3248 OpCode
.data
.u16
.MaxValue
= (UINT16
)Maximum
;
3249 OpCode
.data
.u16
.Step
= (UINT16
)Step
;
3252 case EFI_IFR_NUMERIC_SIZE_4
:
3253 OpCode
.data
.u32
.MinValue
= (UINT32
)Minimum
;
3254 OpCode
.data
.u32
.MaxValue
= (UINT32
)Maximum
;
3255 OpCode
.data
.u32
.Step
= (UINT32
)Step
;
3258 case EFI_IFR_NUMERIC_SIZE_8
:
3259 OpCode
.data
.u64
.MinValue
= Minimum
;
3260 OpCode
.data
.u64
.MaxValue
= Maximum
;
3261 OpCode
.data
.u64
.Step
= Step
;
3265 if (DefaultsOpCodeHandle
== NULL
) {
3266 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, sizeof (OpCode
));
3269 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3270 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_NUMERIC_OP
, sizeof (OpCode
), 0, 1);
3271 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3272 HiiCreateEndOpCode (OpCodeHandle
);
3273 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3277 Create EFI_IFR_STRING_OP opcode.
3279 If OpCodeHandle is NULL, then ASSERT().
3280 If any reserved bits are set in QuestionFlags, then ASSERT().
3281 If any reserved bits are set in StringFlags, then ASSERT().
3283 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3284 @param[in] QuestionId Question ID
3285 @param[in] VarStoreId Storage ID
3286 @param[in] VarOffset Offset in Storage
3287 @param[in] Prompt String ID for Prompt
3288 @param[in] Help String ID for Help
3289 @param[in] QuestionFlags Flags in Question Header
3290 @param[in] StringFlags Flags for string opcode
3291 @param[in] MinSize String minimum length
3292 @param[in] MaxSize String maximum length
3293 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3294 is an optional parameter that may be NULL.
3296 @retval NULL There is not enough space left in Buffer to add the opcode.
3297 @retval Other A pointer to the created opcode.
3302 HiiCreateStringOpCode (
3303 IN VOID
*OpCodeHandle
,
3304 IN EFI_QUESTION_ID QuestionId
,
3305 IN EFI_VARSTORE_ID VarStoreId
,
3306 IN UINT16 VarOffset
,
3307 IN EFI_STRING_ID Prompt
,
3308 IN EFI_STRING_ID Help
,
3309 IN UINT8 QuestionFlags
,
3310 IN UINT8 StringFlags
,
3313 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3316 EFI_IFR_STRING OpCode
;
3319 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3321 ZeroMem (&OpCode
, sizeof (OpCode
));
3322 OpCode
.Question
.Header
.Prompt
= Prompt
;
3323 OpCode
.Question
.Header
.Help
= Help
;
3324 OpCode
.Question
.QuestionId
= QuestionId
;
3325 OpCode
.Question
.VarStoreId
= VarStoreId
;
3326 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3327 OpCode
.Question
.Flags
= QuestionFlags
;
3328 OpCode
.MinSize
= MinSize
;
3329 OpCode
.MaxSize
= MaxSize
;
3330 OpCode
.Flags
= (UINT8
) (StringFlags
& EFI_IFR_STRING_MULTI_LINE
);
3332 if (DefaultsOpCodeHandle
== NULL
) {
3333 return InternalHiiCreateOpCode (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
));
3336 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3337 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_STRING_OP
, sizeof (OpCode
), 0, 1);
3338 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3339 HiiCreateEndOpCode (OpCodeHandle
);
3340 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3344 Create EFI_IFR_ONE_OF_OP opcode.
3346 If OpCodeHandle is NULL, then ASSERT().
3347 If any reserved bits are set in QuestionFlags, then ASSERT().
3348 If any reserved bits are set in OneOfFlags, then ASSERT().
3350 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3351 @param[in] QuestionId Question ID
3352 @param[in] VarStoreId Storage ID
3353 @param[in] VarOffset Offset in Storage
3354 @param[in] Prompt String ID for Prompt
3355 @param[in] Help String ID for Help
3356 @param[in] QuestionFlags Flags in Question Header
3357 @param[in] OneOfFlags Flags for oneof opcode
3358 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3359 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3360 is an optional parameter that may be NULL.
3362 @retval NULL There is not enough space left in Buffer to add the opcode.
3363 @retval Other A pointer to the created opcode.
3368 HiiCreateOneOfOpCode (
3369 IN VOID
*OpCodeHandle
,
3370 IN EFI_QUESTION_ID QuestionId
,
3371 IN EFI_VARSTORE_ID VarStoreId
,
3372 IN UINT16 VarOffset
,
3373 IN EFI_STRING_ID Prompt
,
3374 IN EFI_STRING_ID Help
,
3375 IN UINT8 QuestionFlags
,
3376 IN UINT8 OneOfFlags
,
3377 IN VOID
*OptionsOpCodeHandle
,
3378 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3381 EFI_IFR_ONE_OF OpCode
;
3384 ASSERT (OptionsOpCodeHandle
!= NULL
);
3385 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3387 ZeroMem (&OpCode
, sizeof (OpCode
));
3388 OpCode
.Question
.Header
.Prompt
= Prompt
;
3389 OpCode
.Question
.Header
.Help
= Help
;
3390 OpCode
.Question
.QuestionId
= QuestionId
;
3391 OpCode
.Question
.VarStoreId
= VarStoreId
;
3392 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3393 OpCode
.Question
.Flags
= QuestionFlags
;
3394 OpCode
.Flags
= OneOfFlags
;
3396 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3397 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ONE_OF_OP
, sizeof (OpCode
), 0, 1);
3398 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3399 if (DefaultsOpCodeHandle
!= NULL
) {
3400 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3402 HiiCreateEndOpCode (OpCodeHandle
);
3403 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3407 Create EFI_IFR_ORDERED_LIST_OP opcode.
3409 If OpCodeHandle is NULL, then ASSERT().
3410 If any reserved bits are set in QuestionFlags, then ASSERT().
3411 If any reserved bits are set in OrderedListFlags, then ASSERT().
3413 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3414 @param[in] QuestionId Question ID
3415 @param[in] VarStoreId Storage ID
3416 @param[in] VarOffset Offset in Storage
3417 @param[in] Prompt String ID for Prompt
3418 @param[in] Help String ID for Help
3419 @param[in] QuestionFlags Flags in Question Header
3420 @param[in] OrderedListFlags Flags for ordered list opcode
3421 @param[in] DataType Type for option value
3422 @param[in] MaxContainers Maximum count for options in this ordered list
3423 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3424 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3425 is an optional parameter that may be NULL.
3427 @retval NULL There is not enough space left in Buffer to add the opcode.
3428 @retval Other A pointer to the created opcode.
3433 HiiCreateOrderedListOpCode (
3434 IN VOID
*OpCodeHandle
,
3435 IN EFI_QUESTION_ID QuestionId
,
3436 IN EFI_VARSTORE_ID VarStoreId
,
3437 IN UINT16 VarOffset
,
3438 IN EFI_STRING_ID Prompt
,
3439 IN EFI_STRING_ID Help
,
3440 IN UINT8 QuestionFlags
,
3441 IN UINT8 OrderedListFlags
,
3443 IN UINT8 MaxContainers
,
3444 IN VOID
*OptionsOpCodeHandle
,
3445 IN VOID
*DefaultsOpCodeHandle OPTIONAL
3448 EFI_IFR_ORDERED_LIST OpCode
;
3451 ASSERT (OptionsOpCodeHandle
!= NULL
);
3452 ASSERT ((QuestionFlags
& (~(EFI_IFR_FLAG_READ_ONLY
| EFI_IFR_FLAG_CALLBACK
| EFI_IFR_FLAG_RESET_REQUIRED
| EFI_IFR_FLAG_OPTIONS_ONLY
))) == 0);
3454 ZeroMem (&OpCode
, sizeof (OpCode
));
3455 OpCode
.Question
.Header
.Prompt
= Prompt
;
3456 OpCode
.Question
.Header
.Help
= Help
;
3457 OpCode
.Question
.QuestionId
= QuestionId
;
3458 OpCode
.Question
.VarStoreId
= VarStoreId
;
3459 OpCode
.Question
.VarStoreInfo
.VarOffset
= VarOffset
;
3460 OpCode
.Question
.Flags
= QuestionFlags
;
3461 OpCode
.MaxContainers
= MaxContainers
;
3462 OpCode
.Flags
= OrderedListFlags
;
3464 Position
= InternalHiiOpCodeHandlePosition (OpCodeHandle
);
3465 InternalHiiCreateOpCodeExtended (OpCodeHandle
, &OpCode
, EFI_IFR_ORDERED_LIST_OP
, sizeof (OpCode
), 0, 1);
3466 InternalHiiAppendOpCodes (OpCodeHandle
, OptionsOpCodeHandle
);
3467 if (DefaultsOpCodeHandle
!= NULL
) {
3468 InternalHiiAppendOpCodes (OpCodeHandle
, DefaultsOpCodeHandle
);
3470 HiiCreateEndOpCode (OpCodeHandle
);
3471 return InternalHiiOpCodeHandleBuffer (OpCodeHandle
) + Position
;
3475 This is the internal worker function to update the data in
3476 a form specified by FormSetGuid, FormId and Label.
3478 @param FormSetGuid The optional Formset GUID.
3479 @param FormId The Form ID.
3480 @param Package The package header.
3482 @param TempPacakge The resultant package.
3484 @retval EFI_SUCCESS The function completes successfully.
3489 InternalHiiUpdateFormPackageData (
3490 IN EFI_GUID
*FormSetGuid
, OPTIONAL
3491 IN EFI_FORM_ID FormId
,
3492 IN EFI_HII_PACKAGE_HEADER
*Package
,
3493 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
,
3494 IN HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
, OPTIONAL
3495 OUT EFI_HII_PACKAGE_HEADER
*TempPackage
3500 EFI_HII_PACKAGE_HEADER PackageHeader
;
3502 EFI_IFR_OP_HEADER
*IfrOpHdr
;
3503 EFI_IFR_OP_HEADER
*UpdateIfrOpHdr
;
3507 UINTN UpdatePackageLength
;
3509 CopyMem (TempPackage
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3510 UpdatePackageLength
= sizeof (EFI_HII_PACKAGE_HEADER
);
3511 BufferPos
= (UINT8
*) (TempPackage
+ 1);
3513 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3514 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
3515 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
3516 GetFormSet
= (BOOLEAN
) ((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
3520 while (Offset
< PackageHeader
.Length
) {
3521 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3522 BufferPos
+= IfrOpHdr
->Length
;
3523 UpdatePackageLength
+= IfrOpHdr
->Length
;
3526 // Find the matched FormSet and Form
3528 if ((IfrOpHdr
->OpCode
== EFI_IFR_FORM_SET_OP
) && (FormSetGuid
!= NULL
)) {
3529 if (CompareGuid((GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
)) {
3534 } else if (IfrOpHdr
->OpCode
== EFI_IFR_FORM_OP
) {
3535 if (CompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
3543 // The matched Form is found, and Update data in this form
3545 if (GetFormSet
&& GetForm
) {
3546 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
;
3547 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3548 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3550 // Remove the original data when End OpCode buffer exist.
3552 if (OpCodeBufferEnd
!= NULL
) {
3553 Offset
+= IfrOpHdr
->Length
;
3554 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3555 UpdateIfrOpHdr
= (EFI_IFR_OP_HEADER
*) OpCodeBufferEnd
->Buffer
;
3556 while (Offset
< PackageHeader
.Length
) {
3558 // Search the matched end opcode
3560 if ((UpdateIfrOpHdr
->Length
== IfrOpHdr
->Length
) && \
3561 (CompareMem (IfrOpHdr
, UpdateIfrOpHdr
, UpdateIfrOpHdr
->Length
) == 0)) {
3565 // Go to the next Op-Code
3567 Offset
+= IfrOpHdr
->Length
;
3568 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3571 if (Offset
>= PackageHeader
.Length
) {
3573 // The end opcode is not found.
3575 return EFI_NOT_FOUND
;
3580 // Insert the updated data
3582 AddSize
= ((EFI_IFR_OP_HEADER
*) OpCodeBufferStart
->Buffer
)->Length
;
3583 CopyMem (BufferPos
, OpCodeBufferStart
->Buffer
+ AddSize
, OpCodeBufferStart
->Position
- AddSize
);
3584 BufferPos
+= OpCodeBufferStart
->Position
- AddSize
;
3585 UpdatePackageLength
+= OpCodeBufferStart
->Position
- AddSize
;
3587 if (OpCodeBufferEnd
!= NULL
) {
3589 // Add the end opcode
3591 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
3592 BufferPos
+= IfrOpHdr
->Length
;
3593 UpdatePackageLength
+= IfrOpHdr
->Length
;
3597 // Copy the left package data.
3599 Offset
+= IfrOpHdr
->Length
;
3600 CopyMem (BufferPos
, (UINT8
*) Package
+ Offset
, PackageHeader
.Length
- Offset
);
3601 UpdatePackageLength
+= PackageHeader
.Length
- Offset
;
3612 // Go to the next Op-Code
3614 Offset
+= IfrOpHdr
->Length
;
3615 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
3620 // The updated opcode buffer is not found.
3622 return EFI_NOT_FOUND
;
3625 // Update the package length.
3627 PackageHeader
.Length
= (UINT32
) UpdatePackageLength
;
3628 CopyMem (TempPackage
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3634 This function updates a form that has previously been registered with the HII
3635 Database. This function will perform at most one update operation.
3637 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
3638 comparisons of IFR opcodes are performed from the beginning of the form being
3639 updated until an IFR opcode is found that exactly matches the first IFR opcode
3640 specifed by StartOpCodeHandle. The following rules are used to determine if
3641 an insert, replace, or delete operation is performed.
3643 1) If no matches are found, then NULL is returned.
3644 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
3645 from StartOpcodeHandle except the first opcode are inserted immediately after
3646 the matching IFR opcode in the form beng updated.
3647 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
3648 from the matching IFR opcode until an IFR opcode exatly matches the first
3649 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
3650 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
3651 is found, then all of the IFR opcodes between the start match and the end
3652 match are deleted from the form being updated and all of the IFR opcodes
3653 from StartOpcodeHandle except the first opcode are inserted immediately after
3654 the matching start IFR opcode. If StartOpCcodeHandle only contains one
3655 IFR instruction, then the result of ths operation will delete all of the IFR
3656 opcodes between the start end matches.
3658 If HiiHandle is NULL, then ASSERT().
3659 If StartOpCodeHandle is NULL, then ASSERT().
3661 @param[in] HiiHandle The HII Handle of the form to update.
3662 @param[in] FormSetGuid The Formset GUID of the form to update. This
3663 is an optional parameter that may be NULL.
3664 If it is NULL, all FormSet will be updated.
3665 @param[in] FormId The ID of the form to update.
3666 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
3667 opcodes to be inserted or replaced in the form.
3668 The first IFR instruction in StartOpCodeHandle
3669 is used to find matching IFR opcode in the
3671 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
3672 that marks the end of a replace operation in
3673 the form. This is an optional parameter that
3674 may be NULL. If it is NULL, then an the IFR
3675 opcodes specified by StartOpCodeHandle are
3676 inserted into the form.
3678 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
3679 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
3680 1) The form specified by HiiHandle, FormSetGuid,
3681 and FormId could not be found in the HII Database.
3682 2) No IFR opcodes in the target form match the first
3683 IFR opcode in StartOpCodeHandle.
3684 3) EndOpCOde is not NULL, and no IFR opcodes in the
3685 target form following a matching start opcode match
3686 the first IFR opcode in EndOpCodeHandle.
3687 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
3693 IN EFI_HII_HANDLE HiiHandle
,
3694 IN EFI_GUID
*FormSetGuid
, OPTIONAL
3695 IN EFI_FORM_ID FormId
,
3696 IN VOID
*StartOpcodeHandle
,
3697 IN VOID
*EndOpcodeHandle OPTIONAL
3701 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3702 UINT32 PackageListLength
;
3704 EFI_HII_PACKAGE_LIST_HEADER
*UpdatePackageList
;
3706 UINT8
*UpdateBufferPos
;
3707 EFI_HII_PACKAGE_HEADER
*Package
;
3708 EFI_HII_PACKAGE_HEADER
*TempPacakge
;
3709 EFI_HII_PACKAGE_HEADER PackageHeader
;
3711 HII_LIB_OPCODE_BUFFER
*OpCodeBufferStart
;
3712 HII_LIB_OPCODE_BUFFER
*OpCodeBufferEnd
;
3715 // Input update data can't be NULL.
3717 ASSERT (HiiHandle
!= NULL
);
3718 ASSERT (StartOpcodeHandle
!= NULL
);
3719 UpdatePackageList
= NULL
;
3721 HiiPackageList
= NULL
;
3724 // Restrive buffer data from Opcode Handle
3726 OpCodeBufferStart
= (HII_LIB_OPCODE_BUFFER
*) StartOpcodeHandle
;
3727 OpCodeBufferEnd
= (HII_LIB_OPCODE_BUFFER
*) EndOpcodeHandle
;
3730 // Get the orginal package list
3733 HiiPackageList
= NULL
;
3734 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
3736 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
3738 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3742 HiiPackageList
= AllocatePool (BufferSize
);
3743 if (HiiPackageList
== NULL
) {
3744 Status
= EFI_OUT_OF_RESOURCES
;
3748 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
3749 if (EFI_ERROR (Status
)) {
3754 // Calculate and allocate space for retrieval of IFR data
3756 BufferSize
+= OpCodeBufferStart
->Position
;
3757 UpdatePackageList
= AllocateZeroPool (BufferSize
);
3758 if (UpdatePackageList
== NULL
) {
3759 Status
= EFI_OUT_OF_RESOURCES
;
3764 // Allocate temp buffer to store the temp updated package buffer
3766 TempPacakge
= AllocateZeroPool (BufferSize
);
3767 if (TempPacakge
== NULL
) {
3768 Status
= EFI_OUT_OF_RESOURCES
;
3772 UpdateBufferPos
= (UINT8
*) UpdatePackageList
;
3775 // Copy the package list header
3777 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
3778 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3781 // Go through each package to find the matched pacakge and update one by one
3784 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3785 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
3786 while (Offset
< PackageListLength
) {
3787 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
3788 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3789 Offset
+= Package
->Length
;
3791 if (Package
->Type
== EFI_HII_PACKAGE_FORMS
) {
3793 // Check this package is the matched package.
3795 Status
= InternalHiiUpdateFormPackageData (FormSetGuid
, FormId
, Package
, OpCodeBufferStart
, OpCodeBufferEnd
, TempPacakge
);
3797 // The matched package is found. Its pacakge buffer will be updated by the input new data.
3799 if (!EFI_ERROR(Status
)) {
3805 // Add updated package buffer
3807 Package
= TempPacakge
;
3812 // Add pacakge buffer
3814 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3815 CopyMem (UpdateBufferPos
, Package
, PackageHeader
.Length
);
3816 UpdateBufferPos
+= PackageHeader
.Length
;
3821 // Update package list length
3823 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdatePackageList
;
3824 WriteUnaligned32 (&UpdatePackageList
->PackageLength
, (UINT32
) BufferSize
);
3827 // Update Pacakge to show form
3829 Status
= gHiiDatabase
->UpdatePackageList (gHiiDatabase
, HiiHandle
, UpdatePackageList
);
3832 // Not matched form is found and updated.
3834 Status
= EFI_NOT_FOUND
;
3838 if (HiiPackageList
!= NULL
) {
3839 FreePool (HiiPackageList
);
3842 if (UpdatePackageList
!= NULL
) {
3843 FreePool (UpdatePackageList
);
3846 if (TempPacakge
!= NULL
) {
3847 FreePool (TempPacakge
);
3854 Configure the buffer accrording to ConfigBody strings in the format of
3855 <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.
3856 This ConfigBody strings is generated by UEFI VfrCompiler for the default
3857 values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000
3858 constructed following this rule:
3859 "Vfr" + varstore.name + "Default" + defaultstore.attributes.
3860 Check the generated C file in Output for details.
3862 @param Buffer The start address of buffer.
3863 @param BufferSize The size of buffer.
3864 @param Number The number of the strings.
3865 @param ... Variable argument list for default value in <AltResp> format
3866 generated by the tool.
3868 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
3869 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
3870 @retval EFI_SUCCESS Operation successful.
3875 HiiIfrLibExtractDefault(
3877 IN UINTN
*BufferSize
,
3891 if ((Buffer
== NULL
) || (BufferSize
== NULL
)) {
3892 return EFI_INVALID_PARAMETER
;
3899 VA_START (Args
, Number
);
3900 for (Index
= 0; Index
< Number
; Index
++) {
3901 BufCfgArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
3902 TotalLen
= ReadUnaligned32 ((UINT32
*)BufCfgArray
);
3903 BufferPos
= BufCfgArray
+ sizeof (UINT32
);
3905 while ((UINT32
)(BufferPos
- BufCfgArray
) < TotalLen
) {
3906 Offset
= ReadUnaligned16 ((UINT16
*)BufferPos
);
3907 BufferPos
+= sizeof (UINT16
);
3908 Width
= ReadUnaligned16 ((UINT16
*)BufferPos
);
3909 BufferPos
+= sizeof (UINT16
);
3913 if ((UINTN
)(Offset
+ Width
) > *BufferSize
) {
3914 return EFI_BUFFER_TOO_SMALL
;
3917 CopyMem ((UINT8
*)Buffer
+ Offset
, Value
, Width
);
3922 *BufferSize
= (UINTN
)Offset
;