3 Copyright (c) 2007 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL.
26 #include "HiiDatabase.h"
28 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
32 NibbleToHexCharPrivate (
38 Converts the low nibble of a byte to hex unicode character.
41 Nibble - lower nibble of a byte.
44 Hex unicode character between L'0' to L'f'.
51 return (CHAR16
)(Nibble
+ L
'0');
54 return (CHAR16
)(Nibble
- 0xA + L
'a');
59 Converts Unicode string to binary buffer.
60 The conversion may be partial.
61 The first character in the string that is not hex digit stops the conversion.
62 At a minimum, any blob of data could be represented as a hex string.
64 @param Buf Pointer to buffer that receives the data.
65 @param Len Length in bytes of the buffer to hold converted
66 data. If routine return with EFI_SUCCESS,
67 containing length of converted data. If routine
68 return with EFI_BUFFER_TOO_SMALL, containg length
70 @param Str String to be converted from.
71 @param ConvertedStrLen Length of the Hex String consumed.
73 @retval EFI_SUCCESS Routine Success.
74 @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data.
79 HexStringToBufPrivate (
83 OUT UINTN
*ConvertedStrLen OPTIONAL
93 // Find out how many hex characters the string has.
95 for (Idx
= 0, HexCnt
= 0; IsHexDigit (&Digit
, Str
[Idx
]); Idx
++, HexCnt
++);
102 // Two Unicode characters make up 1 buffer byte. Round up.
104 BufferLength
= (HexCnt
+ 1) / 2;
107 // Test if buffer is passed enough.
109 if (BufferLength
> (*Len
)) {
111 return EFI_BUFFER_TOO_SMALL
;
116 for (Idx
= 0; Idx
< HexCnt
; Idx
++) {
118 IsHexDigit (&Digit
, Str
[Idx
]);
121 // For odd charaters, write the lower nibble for each buffer byte,
122 // and for even characters, the upper nibble.
124 if ((Idx
& 1) == 0) {
125 Byte
= (UINT8
) (Digit
<< 4);
129 Byte
= (UINT8
) (Byte
| Digit
);
135 if (ConvertedStrLen
!= NULL
) {
136 *ConvertedStrLen
= HexCnt
;
144 Converts binary buffer to Unicode string.
145 At a minimum, any blob of data could be represented as a hex string.
147 @param Str Pointer to the string.
148 @param HexStringBufferLength Length in bytes of buffer to hold the hex string.
149 Includes tailing '\0' character. If routine return
150 with EFI_SUCCESS, containing length of hex string
151 buffer. If routine return with
152 EFI_BUFFER_TOO_SMALL, containg length of hex
153 string buffer desired.
154 @param Buf Buffer to be converted from.
155 @param Len Length in bytes of the buffer to be converted.
156 @param Flag If TRUE, encode the data in the same order as the
157 it resides in the Buf. Else encode it in the
160 @retval EFI_SUCCESS Routine success.
161 @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small.
166 BufToHexStringPrivate (
168 IN OUT UINTN
*HexStringBufferLength
,
179 // Make sure string is either passed or allocate enough.
180 // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
181 // Plus the Unicode termination character.
184 if ((*HexStringBufferLength
) < (StrLen
+ 1) * sizeof (CHAR16
)) {
185 *HexStringBufferLength
= (StrLen
+ 1) * sizeof (CHAR16
);
186 return EFI_BUFFER_TOO_SMALL
;
189 *HexStringBufferLength
= (StrLen
+ 1) * sizeof (CHAR16
);
196 for (Idx
= 0; Idx
< Len
; Idx
++) {
200 Str
[Idx
* 2] = NibbleToHexCharPrivate ((UINT8
)(Byte
>> 4));
201 Str
[Idx
* 2 + 1] = NibbleToHexCharPrivate (Byte
);
203 Str
[StrLen
- 1 - Idx
* 2] = NibbleToHexCharPrivate (Byte
);
204 Str
[StrLen
- 2 - Idx
* 2] = NibbleToHexCharPrivate ((UINT8
)(Byte
>> 4));
214 Calculate the number of Unicode characters of the incoming Configuration string,
215 not including NULL terminator.
217 @param String String in <MultiConfigRequest> or
218 <MultiConfigResp> format.
220 @return The number of Unicode characters.
225 CalculateConfigStringLen (
232 // "GUID=" should be the first element of incoming string.
234 ASSERT (String
!= NULL
);
235 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
237 Length
= StrLen (L
"GUID=");
241 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
242 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
244 while (*String
!= 0 && StrnCmp (String
, L
"&GUID=", StrLen (L
"&GUID=")) != 0) {
254 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
255 from <PathHdr> of <ConfigHdr>.
257 @param String UEFI configuration string
258 @param DevicePath binary of a UEFI device path.
260 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
261 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
262 @retval EFI_SUCCESS The device path is retrieved and translated to
269 IN EFI_STRING String
,
270 OUT UINT8
**DevicePath
275 EFI_STRING DevicePathString
;
277 if (String
== NULL
|| DevicePath
== NULL
) {
278 return EFI_INVALID_PARAMETER
;
282 // Find the 'PATH=' of <PathHdr> and skip it.
284 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
286 return EFI_INVALID_PARAMETER
;
289 String
+= StrLen (L
"PATH=");
293 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
294 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
295 // of UEFI device path.
297 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
298 DevicePathString
= (EFI_STRING
) AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
299 if (DevicePathString
== NULL
) {
300 return EFI_OUT_OF_RESOURCES
;
302 StrnCpy (DevicePathString
, PathHdr
, Length
);
303 *(DevicePathString
+ Length
) = 0;
306 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
307 // as the device path resides in RAM memory.
308 // Translate the data into binary.
309 // Two Unicode characters make up 1 buffer byte.
312 *DevicePath
= (UINT8
*) AllocateZeroPool (Length
);
313 if (*DevicePath
== NULL
) {
314 SafeFreePool (DevicePathString
);
315 return EFI_OUT_OF_RESOURCES
;
318 HexStringToBufPrivate (*DevicePath
, &Length
, DevicePathString
, NULL
);
320 SafeFreePool (DevicePathString
);
328 Extract Storage from all Form Packages in current hii database.
330 @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.
331 @param StorageListHead Storage link List head.
333 @retval EFI_NOT_FOUND There is no form package in current hii database.
334 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
335 @retval EFI_SUCCESS All existing storage is exported.
341 IN EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
,
342 IN OUT LIST_ENTRY
*StorageListHead
348 EFI_HII_HANDLE
*HandleBuffer
;
351 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
352 EFI_HII_PACKAGE_HEADER
*Package
;
356 HII_FORMSET_STORAGE
*Storage
;
357 EFI_HII_HANDLE HiiHandle
;
358 EFI_HANDLE DriverHandle
;
360 UINT32 PackageListLength
;
361 EFI_HII_PACKAGE_HEADER PackageHeader
;
364 // Find the package list which contains Form package.
368 Status
= HiiListPackageLists (
370 EFI_HII_PACKAGE_FORM
,
375 if (Status
== EFI_BUFFER_TOO_SMALL
) {
376 HandleBuffer
= AllocateZeroPool (BufferSize
);
377 ASSERT (HandleBuffer
!= NULL
);
379 Status
= HiiListPackageLists (
381 EFI_HII_PACKAGE_FORM
,
387 if (EFI_ERROR (Status
)) {
388 SafeFreePool (HandleBuffer
);
392 HandleCount
= BufferSize
/ sizeof (EFI_HII_HANDLE
);
393 for (Index
= 0; Index
< HandleCount
; Index
++) {
394 HiiHandle
= HandleBuffer
[Index
];
397 HiiPackageList
= NULL
;
398 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
399 if (Status
== EFI_BUFFER_TOO_SMALL
) {
400 HiiPackageList
= AllocateZeroPool (BufferSize
);
401 ASSERT (HiiPackageList
!= NULL
);
402 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
404 if (EFI_ERROR (Status
)) {
405 SafeFreePool (HandleBuffer
);
406 SafeFreePool (HiiPackageList
);
411 // Get Form package from this HII package List
413 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
414 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
416 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
418 while (Offset
< PackageListLength
) {
419 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
420 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
421 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
424 Offset
+= PackageHeader
.Length
;
426 if (Offset
>= PackageListLength
) {
428 // Error here: No Form package found in this Package List
434 // Search Storage definition in this Form package
436 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
437 while (Offset
< PackageHeader
.Length
) {
438 OpCodeData
= ((UINT8
*) Package
) + Offset
;
439 Offset
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
441 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
443 if ((Operand
== EFI_IFR_VARSTORE_OP
) ||
444 (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) ||
445 (Operand
== EFI_IFR_VARSTORE_EFI_OP
)) {
447 Storage
= AllocateZeroPool (sizeof (HII_FORMSET_STORAGE
));
448 ASSERT (Storage
!= NULL
);
449 InsertTailList (StorageListHead
, &Storage
->Entry
);
451 Storage
->Signature
= HII_FORMSET_STORAGE_SIGNATURE
;
452 Storage
->HiiHandle
= HiiHandle
;
454 Status
= HiiGetPackageListHandle (HiiDatabase
, HiiHandle
, &DriverHandle
);
455 if (EFI_ERROR (Status
)) {
456 SafeFreePool (HandleBuffer
);
457 SafeFreePool (HiiPackageList
);
458 SafeFreePool (Storage
);
461 Storage
->DriverHandle
= DriverHandle
;
463 if (Operand
== EFI_IFR_VARSTORE_OP
) {
464 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
466 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
467 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
469 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
470 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
471 ASSERT (Storage
->Name
!= NULL
);
472 for (Index2
= 0; AsciiString
[Index2
] != 0; Index2
++) {
473 Storage
->Name
[Index2
] = (CHAR16
) AsciiString
[Index2
];
476 // Append '\0' to the end of the unicode string.
478 Storage
->Name
[Index2
] = 0;
479 } else if (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
480 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
482 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
483 } else if (Operand
== EFI_IFR_VARSTORE_EFI_OP
) {
484 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
486 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
491 SafeFreePool (HiiPackageList
);
494 SafeFreePool (HandleBuffer
);
501 Generate a sub string then output it.
503 @param String A constant string which is the prefix of the to be
504 generated string, e.g. GUID=
505 @param BufferLen The length of the Buffer in bytes.
506 @param Buffer Points to a buffer which will be converted to hex
507 string and to be the content of the generated
509 @param Flag If TRUE, convert the buffer data in the same order
510 as the it resides in the Buffer. Else convert it
511 in the reverse direction.
512 @param SubStr Points to the output string. It's caller's
513 responsibility to free this buffer.
520 IN CONST EFI_STRING String
,
524 OUT EFI_STRING
*SubStr
531 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
533 if (Buffer
== NULL
) {
534 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
535 ASSERT (*SubStr
!= NULL
);
539 Length
= BufferLen
* 2 + 1 + StrLen (String
) + 1;
540 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
541 ASSERT (Str
!= NULL
);
543 StrCpy (Str
, String
);
544 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
546 Status
= BufToHexStringPrivate (
547 Str
+ StrLen (String
),
554 ASSERT_EFI_ERROR (Status
);
562 Retrieve the <ConfigBody> from String then output it.
564 @param String A sub string of a configuration string in
565 <MultiConfigAltResp> format.
566 @param ConfigBody Points to the output string. It's caller's
567 responsibility to free this buffer.
569 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
570 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
571 @retval EFI_SUCCESS All existing storage is exported.
577 IN EFI_STRING String
,
578 OUT EFI_STRING
*ConfigBody
585 if (String
== NULL
|| ConfigBody
== NULL
) {
586 return EFI_INVALID_PARAMETER
;
589 TmpPtr
= StrStr (String
, L
"GUID=");
590 if (TmpPtr
== NULL
) {
592 // It is the last <ConfigResp> of the incoming configuration string.
594 Result
= AllocateCopyPool (StrSize (String
), String
);
595 if (Result
== NULL
) {
596 return EFI_OUT_OF_RESOURCES
;
598 *ConfigBody
= Result
;
603 Length
= TmpPtr
- String
;
604 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
605 if (Result
== NULL
) {
606 return EFI_OUT_OF_RESOURCES
;
609 *(Result
+ Length
- 1) = 0;
610 *ConfigBody
= Result
;
627 Adjusts the size of a previously allocated buffer.
630 OldPool - A pointer to the buffer whose size is being adjusted.
631 OldSize - The size of the current buffer.
632 NewSize - The size of the new buffer.
635 Points to the new buffer
643 NewPool
= AllocateZeroPool (NewSize
);
648 CopyMem (NewPool
, OldPool
, OldSize
< NewSize
? OldSize
: NewSize
);
651 gBS
->FreePool (OldPool
);
659 Append a string to a multi-string format.
661 @param MultiString String in <MultiConfigRequest>,
662 <MultiConfigAltResp>, or <MultiConfigResp>. On
663 input, the buffer length of this string is
664 MAX_STRING_LENGTH. On output, the buffer length
666 @param AppendString NULL-terminated Unicode string.
668 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
669 @retval EFI_SUCCESS AppendString is append to the end of MultiString
674 AppendToMultiString (
675 IN OUT EFI_STRING
*MultiString
,
676 IN EFI_STRING AppendString
679 UINTN AppendStringSize
;
680 UINTN MultiStringSize
;
682 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
683 return EFI_INVALID_PARAMETER
;
686 AppendStringSize
= StrSize (AppendString
);
687 MultiStringSize
= StrSize (*MultiString
);
690 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
692 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
693 MultiStringSize
> MAX_STRING_LENGTH
) {
694 *MultiString
= (EFI_STRING
) ReallocatePool (
695 (VOID
*) (*MultiString
),
697 MultiStringSize
+ AppendStringSize
702 // Append the incoming string
704 StrCat (*MultiString
, AppendString
);
711 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
713 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
715 @param StringPtr String in <BlockConfig> format and points to the
716 first character of <Number>.
717 @param Number The output value. Caller takes the responsibility
719 @param Len Length of the <Number>, in characters.
721 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
723 @retval EFI_SUCCESS Value of <Number> is outputted in Number
730 IN EFI_STRING StringPtr
,
741 ASSERT (StringPtr
!= NULL
&& Number
!= NULL
&& Len
!= NULL
);
742 ASSERT (*StringPtr
!= 0);
747 while (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
750 *Len
= StringPtr
- TmpPtr
;
753 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (EFI_STRING
));
755 Status
= EFI_OUT_OF_RESOURCES
;
758 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
761 Length
= (Length
+ 1) / 2;
762 Buf
= (UINT8
*) AllocateZeroPool (Length
);
764 Status
= EFI_OUT_OF_RESOURCES
;
768 Status
= HexStringToBuf (Buf
, &Length
, Str
, NULL
);
769 if (EFI_ERROR (Status
)) {
774 Status
= EFI_SUCCESS
;
783 This function allows a caller to extract the current configuration
784 for one or more named elements from one or more drivers.
786 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
788 @param Request A null-terminated Unicode string in
789 <MultiConfigRequest> format.
790 @param Progress On return, points to a character in the Request
791 string. Points to the string's null terminator if
792 request was successful. Points to the most recent
793 & before the first failing name / value pair (or
794 the beginning of the string if the failure is in
795 the first name / value pair) if the request was
797 @param Results Null-terminated Unicode string in
798 <MultiConfigAltResp> format which has all values
799 filled in for the names in the Request string.
800 String to be allocated by the called function.
802 @retval EFI_SUCCESS The Results string is filled with the values
803 corresponding to all requested names.
804 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
805 results that must be stored awaiting possible
807 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
808 Progress set to the "G" in "GUID" of the routing
809 header that doesn't match. Note: There is no
810 requirement that all routing data be validated
811 before any configuration extraction.
812 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
813 parameter would result in this type of error. The
814 Progress parameter is set to NULL.
815 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
816 before the error or the beginning of the string.
817 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
823 HiiConfigRoutingExtractConfig (
824 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
825 IN CONST EFI_STRING Request
,
826 OUT EFI_STRING
*Progress
,
827 OUT EFI_STRING
*Results
830 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
832 HII_DATABASE_PRIVATE_DATA
*Private
;
833 EFI_STRING StringPtr
;
834 EFI_STRING ConfigRequest
;
836 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
839 HII_DATABASE_RECORD
*Database
;
840 UINT8
*CurrentDevicePath
;
841 EFI_HANDLE DriverHandle
;
842 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
843 EFI_STRING AccessProgress
;
844 EFI_STRING AccessResults
;
848 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
849 return EFI_INVALID_PARAMETER
;
852 if (Request
== NULL
) {
854 return EFI_INVALID_PARAMETER
;
857 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
859 *Progress
= StringPtr
;
862 // The first element of <MultiConfigRequest> should be
863 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
865 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
866 return EFI_INVALID_PARAMETER
;
870 // Allocate a fix length of memory to store Results. Reallocate memory for
871 // Results if this fix length is insufficient.
873 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
874 if (*Results
== NULL
) {
875 return EFI_OUT_OF_RESOURCES
;
878 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
880 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
881 // or most recent & before the error.
883 if (StringPtr
== Request
) {
884 *Progress
= StringPtr
;
886 *Progress
= StringPtr
- 1;
890 // Process each <ConfigRequest> of <MultiConfigRequest>
892 Length
= CalculateConfigStringLen (StringPtr
);
893 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
894 if (ConfigRequest
== NULL
) {
895 return EFI_OUT_OF_RESOURCES
;
897 *(ConfigRequest
+ Length
) = 0;
900 // Get the UEFI device path
902 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
903 if (EFI_ERROR (Status
)) {
904 SafeFreePool (ConfigRequest
);
909 // Find driver which matches the routing data.
912 for (Link
= Private
->DatabaseList
.ForwardLink
;
913 Link
!= &Private
->DatabaseList
;
914 Link
= Link
->ForwardLink
916 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
917 CurrentDevicePath
= Database
->PackageList
->DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
918 if (CurrentDevicePath
!= NULL
) {
922 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
924 DriverHandle
= Database
->DriverHandle
;
930 SafeFreePool (DevicePath
);
932 if (DriverHandle
== NULL
) {
934 // Routing data does not match any known driver.
935 // Set Progress to the 'G' in "GUID" of the routing header.
937 *Progress
= StringPtr
;
938 SafeFreePool (ConfigRequest
);
939 return EFI_NOT_FOUND
;
943 // Call corresponding ConfigAccess protocol to extract settings
945 Status
= gBS
->HandleProtocol (
947 &gEfiHiiConfigAccessProtocolGuid
,
948 (VOID
**) &ConfigAccess
950 ASSERT_EFI_ERROR (Status
);
952 Status
= ConfigAccess
->ExtractConfig (
958 if (EFI_ERROR (Status
)) {
960 // AccessProgress indicates the parsing progress on <ConfigRequest>.
961 // Map it to the progress on <MultiConfigRequest> then return it.
963 RemainSize
= StrSize (AccessProgress
);
964 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
967 SafeFreePool (ConfigRequest
);
972 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
974 ASSERT (*AccessProgress
== 0);
975 Status
= AppendToMultiString (Results
, AccessResults
);
976 ASSERT_EFI_ERROR (Status
);
977 SafeFreePool (AccessResults
);
978 AccessResults
= NULL
;
979 SafeFreePool (ConfigRequest
);
980 ConfigRequest
= NULL
;
983 // Go to next <ConfigRequest> (skip '&').
986 if (*StringPtr
== 0) {
987 *Progress
= StringPtr
;
997 return EFI_UNSUPPORTED
;
1004 This function allows the caller to request the current configuration for the
1005 entirety of the current HII database and returns the data in a
1006 null-terminated Unicode string.
1008 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1010 @param Results Null-terminated Unicode string in
1011 <MultiConfigAltResp> format which has all values
1012 filled in for the names in the Request string.
1013 String to be allocated by the called function.
1014 De-allocation is up to the caller.
1016 @retval EFI_SUCCESS The Results string is filled with the values
1017 corresponding to all requested names.
1018 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
1019 results that must be stored awaiting possible
1021 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
1022 parameter would result in this type of error.
1027 HiiConfigRoutingExportConfig (
1028 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1029 OUT EFI_STRING
*Results
1032 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
1035 HII_DATABASE_PRIVATE_DATA
*Private
;
1036 LIST_ENTRY StorageListHdr
;
1037 HII_FORMSET_STORAGE
*Storage
;
1039 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1043 EFI_STRING ConfigRequest
;
1045 EFI_STRING StringPtr
;
1046 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1047 EFI_STRING AccessProgress
;
1048 EFI_STRING AccessResults
;
1051 if (This
== NULL
|| Results
== NULL
) {
1052 return EFI_INVALID_PARAMETER
;
1055 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1057 InitializeListHead (&StorageListHdr
);
1059 Status
= ExportAllStorage (&Private
->HiiDatabase
, &StorageListHdr
);
1060 if (EFI_ERROR (Status
)) {
1065 // Allocate a fix length of memory to store Results. Reallocate memory for
1066 // Results if this fix length is insufficient.
1068 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
1069 if (*Results
== NULL
) {
1070 return EFI_OUT_OF_RESOURCES
;
1074 // Parsing all formset storages.
1076 for (Link
= StorageListHdr
.ForwardLink
; Link
!= &StorageListHdr
; Link
= Link
->ForwardLink
) {
1077 Storage
= CR (Link
, HII_FORMSET_STORAGE
, Entry
, HII_FORMSET_STORAGE_SIGNATURE
);
1079 // Find the corresponding device path instance
1081 Status
= gBS
->HandleProtocol (
1082 Storage
->DriverHandle
,
1083 &gEfiDevicePathProtocolGuid
,
1084 (VOID
**) &DevicePath
1086 if (EFI_ERROR (Status
)) {
1090 // Convert the device path binary to hex UNICODE %02x bytes in the same order
1091 // as the device path resides in RAM memory.
1093 Length
= GetDevicePathSize (DevicePath
);
1094 PathHdrSize
= (Length
* 2 + 1) * sizeof (CHAR16
);
1095 PathHdr
= (EFI_STRING
) AllocateZeroPool (PathHdrSize
);
1096 if (PathHdr
== NULL
) {
1097 return EFI_OUT_OF_RESOURCES
;
1099 Status
= BufToHexStringPrivate (PathHdr
, &PathHdrSize
, (UINT8
*) DevicePath
, Length
, TRUE
);
1100 ASSERT_EFI_ERROR (Status
);
1103 // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.
1104 // It means extract all possible configurations from this specific driver.
1106 TmpSize
= StrLen (L
"GUID=&NAME=&PATH=");
1107 RequestSize
= (TmpSize
+ sizeof (EFI_GUID
) * 2 + StrLen (Storage
->Name
))
1108 * sizeof (CHAR16
) + PathHdrSize
;
1109 ConfigRequest
= (EFI_STRING
) AllocateZeroPool (RequestSize
);
1110 if (ConfigRequest
== NULL
) {
1111 SafeFreePool (PathHdr
);
1112 return EFI_OUT_OF_RESOURCES
;
1117 // <GuidHdr> ::= 'GUID='<Guid>
1119 StringPtr
= ConfigRequest
;
1120 StrnCpy (StringPtr
, L
"GUID=", StrLen (L
"GUID="));
1121 StringPtr
+= StrLen (L
"GUID=");
1123 Status
= BufToHexStringPrivate (
1126 (UINT8
*) (&Storage
->Guid
),
1130 ASSERT_EFI_ERROR (Status
);
1131 StringPtr
+= RequestSize
/ 2 - 1;
1132 ASSERT (*StringPtr
== 0);
1138 // <NameHdr> ::= 'NAME='<String>
1140 StrnCpy (StringPtr
, L
"NAME=", StrLen (L
"NAME="));
1141 StringPtr
+= StrLen (L
"NAME=");
1142 StrnCpy (StringPtr
, Storage
->Name
, StrLen (Storage
->Name
));
1143 StringPtr
+= StrLen (Storage
->Name
);
1149 // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>
1151 StrnCpy (StringPtr
, L
"PATH=", StrLen (L
"PATH="));
1152 StringPtr
+= StrLen (L
"PATH=");
1153 StrCpy (StringPtr
, PathHdr
);
1155 SafeFreePool (PathHdr
);
1159 // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the
1160 // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>
1161 // is required to call ConfigAccess.ExtractConfig().
1163 // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess
1164 // to handle such kind of "ConfigRequest". It is not supported till now.
1166 // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()
1167 // will be updated as soon as the decision is made.
1170 // Route the request to corresponding ConfigAccess protocol to extract settings.
1172 Status
= gBS
->HandleProtocol (
1173 Storage
->DriverHandle
,
1174 &gEfiHiiConfigAccessProtocolGuid
,
1175 (VOID
**) &ConfigAccess
1177 ASSERT_EFI_ERROR (Status
);
1179 Status
= ConfigAccess
->ExtractConfig (
1185 if (EFI_ERROR (Status
)) {
1186 SafeFreePool (ConfigRequest
);
1187 SafeFreePool (AccessResults
);
1188 return EFI_INVALID_PARAMETER
;
1192 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
1194 ASSERT (*AccessProgress
== 0);
1195 Status
= AppendToMultiString (Results
, AccessResults
);
1196 ASSERT_EFI_ERROR (Status
);
1197 SafeFreePool (AccessResults
);
1198 AccessResults
= NULL
;
1199 SafeFreePool (ConfigRequest
);
1200 ConfigRequest
= NULL
;
1205 // Free the exported storage resource
1207 while (!IsListEmpty (&StorageListHdr
)) {
1209 StorageListHdr
.ForwardLink
,
1210 HII_FORMSET_STORAGE
,
1212 HII_FORMSET_STORAGE_SIGNATURE
1214 RemoveEntryList (&Storage
->Entry
);
1215 SafeFreePool (Storage
->Name
);
1216 SafeFreePool (Storage
);
1221 return EFI_UNSUPPORTED
;
1227 This function processes the results of processing forms and routes it to the
1228 appropriate handlers or storage.
1230 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1232 @param Configuration A null-terminated Unicode string in
1233 <MulltiConfigResp> format.
1234 @param Progress A pointer to a string filled in with the offset of
1235 the most recent & before the first failing name /
1236 value pair (or the beginning of the string if the
1237 failure is in the first name / value pair) or the
1238 terminating NULL if all was successful.
1240 @retval EFI_SUCCESS The results have been distributed or are awaiting
1242 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
1243 results that must be stored awaiting possible
1245 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
1246 would result in this type of error.
1247 @retval EFI_NOT_FOUND Target for the specified routing data was not
1253 HiiConfigRoutingRoutConfig (
1254 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1255 IN CONST EFI_STRING Configuration
,
1256 OUT EFI_STRING
*Progress
1259 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
1261 HII_DATABASE_PRIVATE_DATA
*Private
;
1262 EFI_STRING StringPtr
;
1263 EFI_STRING ConfigResp
;
1266 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1268 HII_DATABASE_RECORD
*Database
;
1269 UINT8
*CurrentDevicePath
;
1270 EFI_HANDLE DriverHandle
;
1271 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1272 EFI_STRING AccessProgress
;
1276 if (This
== NULL
|| Progress
== NULL
) {
1277 return EFI_INVALID_PARAMETER
;
1280 if (Configuration
== NULL
) {
1282 return EFI_INVALID_PARAMETER
;
1285 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1286 StringPtr
= Configuration
;
1287 *Progress
= StringPtr
;
1290 // The first element of <MultiConfigResp> should be
1291 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
1293 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1294 return EFI_INVALID_PARAMETER
;
1297 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
1299 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
1300 // or most recent & before the error.
1302 if (StringPtr
== Configuration
) {
1303 *Progress
= StringPtr
;
1305 *Progress
= StringPtr
- 1;
1309 // Process each <ConfigResp> of <MultiConfigResp>
1311 Length
= CalculateConfigStringLen (StringPtr
);
1312 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
1313 if (ConfigResp
== NULL
) {
1314 return EFI_OUT_OF_RESOURCES
;
1317 // Append '\0' to the end of ConfigRequest
1319 *(ConfigResp
+ Length
) = 0;
1322 // Get the UEFI device path
1324 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
1325 if (EFI_ERROR (Status
)) {
1326 SafeFreePool (ConfigResp
);
1331 // Find driver which matches the routing data.
1333 DriverHandle
= NULL
;
1334 for (Link
= Private
->DatabaseList
.ForwardLink
;
1335 Link
!= &Private
->DatabaseList
;
1336 Link
= Link
->ForwardLink
1338 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
1339 CurrentDevicePath
= Database
->PackageList
->DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
1340 if (CurrentDevicePath
!= NULL
) {
1344 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
1346 DriverHandle
= Database
->DriverHandle
;
1352 SafeFreePool (DevicePath
);
1354 if (DriverHandle
== NULL
) {
1356 // Routing data does not match any known driver.
1357 // Set Progress to the 'G' in "GUID" of the routing header.
1359 *Progress
= StringPtr
;
1360 SafeFreePool (ConfigResp
);
1361 return EFI_NOT_FOUND
;
1365 // Call corresponding ConfigAccess protocol to route settings
1367 Status
= gBS
->HandleProtocol (
1369 &gEfiHiiConfigAccessProtocolGuid
,
1370 (VOID
**) &ConfigAccess
1372 ASSERT_EFI_ERROR (Status
);
1374 Status
= ConfigAccess
->RouteConfig (
1380 if (EFI_ERROR (Status
)) {
1382 // AccessProgress indicates the parsing progress on <ConfigResp>.
1383 // Map it to the progress on <MultiConfigResp> then return it.
1385 RemainSize
= StrSize (AccessProgress
);
1386 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
1389 SafeFreePool (ConfigResp
);
1393 SafeFreePool (ConfigResp
);
1397 // Go to next <ConfigResp> (skip '&').
1399 StringPtr
+= Length
;
1400 if (*StringPtr
== 0) {
1401 *Progress
= StringPtr
;
1411 return EFI_UNSUPPORTED
;
1417 This helper function is to be called by drivers to map configuration data
1418 stored in byte array ("block") formats such as UEFI Variables into current
1419 configuration strings.
1421 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1423 @param ConfigRequest A null-terminated Unicode string in
1424 <ConfigRequest> format.
1425 @param Block Array of bytes defining the block's configuration.
1426 @param BlockSize Length in bytes of Block.
1427 @param Config Filled-in configuration string. String allocated
1428 by the function. Returned only if call is
1430 @param Progress A pointer to a string filled in with the offset of
1431 the most recent & before the first failing
1432 name/value pair (or the beginning of the string if
1433 the failure is in the first name / value pair) or
1434 the terminating NULL if all was successful.
1436 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1437 terminator at the end of the ConfigRequest
1439 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1440 points to the first character of ConfigRequest.
1441 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
1442 Block parameter would result in this type of
1443 error. Progress points to the first character of
1445 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
1446 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
1447 Block is left updated and Progress points at
1448 the "&" preceding the first non-<BlockName>.
1454 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1455 IN CONST EFI_STRING ConfigRequest
,
1456 IN CONST UINT8
*Block
,
1457 IN CONST UINTN BlockSize
,
1458 OUT EFI_STRING
*Config
,
1459 OUT EFI_STRING
*Progress
1462 HII_DATABASE_PRIVATE_DATA
*Private
;
1463 EFI_STRING StringPtr
;
1471 EFI_STRING ValueStr
;
1472 EFI_STRING ConfigElement
;
1474 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
1475 return EFI_INVALID_PARAMETER
;
1478 if (Block
== NULL
|| ConfigRequest
== NULL
) {
1479 *Progress
= ConfigRequest
;
1480 return EFI_INVALID_PARAMETER
;
1484 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1485 ASSERT (Private
!= NULL
);
1487 StringPtr
= ConfigRequest
;
1490 ConfigElement
= NULL
;
1493 // Allocate a fix length of memory to store Results. Reallocate memory for
1494 // Results if this fix length is insufficient.
1496 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
1497 if (*Config
== NULL
) {
1498 return EFI_OUT_OF_RESOURCES
;
1504 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1505 *Progress
= StringPtr
;
1506 Status
= EFI_INVALID_PARAMETER
;
1509 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1512 if (*StringPtr
== 0) {
1513 *Progress
= StringPtr
;
1514 Status
= EFI_INVALID_PARAMETER
;
1517 while (*StringPtr
++ != L
'&');
1520 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
1522 Length
= StringPtr
- ConfigRequest
;
1523 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
1526 // Parse each <RequestElement> if exists
1527 // Only <BlockName> format is supported by this help function.
1528 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
1530 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1532 // Back up the header of one <BlockName>
1536 StringPtr
+= StrLen (L
"OFFSET=");
1540 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1541 if (Status
== EFI_OUT_OF_RESOURCES
) {
1542 *Progress
= ConfigRequest
;
1549 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1551 SafeFreePool (TmpBuffer
);
1553 StringPtr
+= Length
;
1554 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1555 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1556 Status
= EFI_INVALID_PARAMETER
;
1559 StringPtr
+= StrLen (L
"&WIDTH=");
1564 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1565 if (Status
== EFI_OUT_OF_RESOURCES
) {
1566 *Progress
= ConfigRequest
;
1573 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1575 SafeFreePool (TmpBuffer
);
1577 StringPtr
+= Length
;
1578 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1579 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1580 Status
= EFI_INVALID_PARAMETER
;
1585 // Calculate Value and convert it to hex string.
1587 if (Offset
+ Width
> BlockSize
) {
1588 *Progress
= StringPtr
;
1589 Status
= EFI_DEVICE_ERROR
;
1593 Value
= (UINT8
*) AllocateZeroPool (Width
);
1594 if (Value
== NULL
) {
1595 *Progress
= ConfigRequest
;
1596 Status
= EFI_OUT_OF_RESOURCES
;
1600 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
1602 Length
= Width
* 2 + 1;
1603 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1604 if (ValueStr
== NULL
) {
1605 *Progress
= ConfigRequest
;
1606 Status
= EFI_OUT_OF_RESOURCES
;
1610 Status
= BufToHexString (ValueStr
, &Length
, Value
, Width
);
1611 ASSERT_EFI_ERROR (Status
);
1612 SafeFreePool (Value
);
1616 // Build a ConfigElement
1618 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
1619 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1620 if (ConfigElement
== NULL
) {
1621 Status
= EFI_OUT_OF_RESOURCES
;
1624 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
1625 if (*StringPtr
== 0) {
1626 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
1628 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
1629 StrCat (ConfigElement
, L
"VALUE=");
1630 StrCat (ConfigElement
, ValueStr
);
1632 AppendToMultiString (Config
, ConfigElement
);
1634 SafeFreePool (ConfigElement
);
1635 SafeFreePool (ValueStr
);
1636 ConfigElement
= NULL
;
1640 // If '\0', parsing is finished. Otherwise skip '&' to continue
1642 if (*StringPtr
== 0) {
1645 AppendToMultiString (Config
, L
"&");
1650 if (*StringPtr
!= 0) {
1651 *Progress
= StringPtr
- 1;
1652 Status
= EFI_INVALID_PARAMETER
;
1656 *Progress
= StringPtr
;
1661 SafeFreePool (*Config
);
1662 SafeFreePool (ValueStr
);
1663 SafeFreePool (Value
);
1664 SafeFreePool (ConfigElement
);
1672 This helper function is to be called by drivers to map configuration strings
1673 to configurations stored in byte array ("block") formats such as UEFI Variables.
1675 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1677 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
1679 @param Block A possibly null array of bytes representing the
1680 current block. Only bytes referenced in the
1681 ConfigResp string in the block are modified. If
1682 this parameter is null or if the *BlockSize
1683 parameter is (on input) shorter than required by
1684 the Configuration string, only the BlockSize
1685 parameter is updated and an appropriate status
1686 (see below) is returned.
1687 @param BlockSize The length of the Block in units of UINT8. On
1688 input, this is the size of the Block. On output,
1689 if successful, contains the index of the last
1690 modified byte in the Block.
1691 @param Progress On return, points to an element of the ConfigResp
1692 string filled in with the offset of the most
1693 recent '&' before the first failing name / value
1694 pair (or the beginning of the string if the
1695 failure is in the first name / value pair) or the
1696 terminating NULL if all was successful.
1698 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1699 terminator at the end of the ConfigResp string.
1700 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1701 points to the first character of ConfigResp.
1702 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
1703 Block parameter would result in this type of
1704 error. Progress points to the first character of
1706 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
1707 value pair. Block is left updated and
1708 Progress points at the '&' preceding the first
1715 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1716 IN CONST EFI_STRING ConfigResp
,
1717 IN OUT UINT8
*Block
,
1718 IN OUT UINTN
*BlockSize
,
1719 OUT EFI_STRING
*Progress
1722 HII_DATABASE_PRIVATE_DATA
*Private
;
1723 EFI_STRING StringPtr
;
1732 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
1733 return EFI_INVALID_PARAMETER
;
1736 if (ConfigResp
== NULL
|| Block
== NULL
) {
1737 *Progress
= ConfigResp
;
1738 return EFI_INVALID_PARAMETER
;
1741 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1742 ASSERT (Private
!= NULL
);
1744 StringPtr
= ConfigResp
;
1745 BufferSize
= *BlockSize
;
1751 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1752 *Progress
= StringPtr
;
1753 Status
= EFI_INVALID_PARAMETER
;
1756 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1759 if (*StringPtr
== 0) {
1760 *Progress
= StringPtr
;
1761 Status
= EFI_INVALID_PARAMETER
;
1764 while (*StringPtr
++ != L
'&');
1767 // Parse each <ConfigElement> if exists
1768 // Only <BlockConfig> format is supported by this help function.
1769 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
1771 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1772 StringPtr
+= StrLen (L
"OFFSET=");
1776 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1777 if (Status
== EFI_OUT_OF_RESOURCES
) {
1778 *Progress
= ConfigResp
;
1785 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1787 SafeFreePool (TmpBuffer
);
1789 StringPtr
+= Length
;
1790 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1791 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1792 Status
= EFI_INVALID_PARAMETER
;
1795 StringPtr
+= StrLen (L
"&WIDTH=");
1800 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1801 if (Status
== EFI_OUT_OF_RESOURCES
) {
1802 *Progress
= ConfigResp
;
1809 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1811 SafeFreePool (TmpBuffer
);
1813 StringPtr
+= Length
;
1814 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1815 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1816 Status
= EFI_INVALID_PARAMETER
;
1819 StringPtr
+= StrLen (L
"&VALUE=");
1824 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
1825 if (Status
== EFI_OUT_OF_RESOURCES
) {
1826 *Progress
= ConfigResp
;
1830 StringPtr
+= Length
;
1831 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1832 *Progress
= StringPtr
- Length
- 7;
1833 Status
= EFI_INVALID_PARAMETER
;
1838 // Update the Block with configuration info
1841 if (Offset
+ Width
> BufferSize
) {
1842 return EFI_DEVICE_ERROR
;
1845 CopyMem (Block
+ Offset
, Value
, Width
);
1846 *BlockSize
= Offset
+ Width
- 1;
1848 SafeFreePool (Value
);
1852 // If '\0', parsing is finished. Otherwise skip '&' to continue
1854 if (*StringPtr
== 0) {
1861 if (*StringPtr
!= 0) {
1862 *Progress
= StringPtr
- 1;
1863 Status
= EFI_INVALID_PARAMETER
;
1867 *Progress
= StringPtr
;
1872 SafeFreePool (Value
);
1878 This helper function is to be called by drivers to extract portions of
1879 a larger configuration string.
1881 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1883 @param Configuration A null-terminated Unicode string in
1884 <MultiConfigAltResp> format.
1885 @param Guid A pointer to the GUID value to search for in the
1886 routing portion of the ConfigResp string when
1887 retrieving the requested data. If Guid is NULL,
1888 then all GUID values will be searched for.
1889 @param Name A pointer to the NAME value to search for in the
1890 routing portion of the ConfigResp string when
1891 retrieving the requested data. If Name is NULL,
1892 then all Name values will be searched for.
1893 @param DevicePath A pointer to the PATH value to search for in the
1894 routing portion of the ConfigResp string when
1895 retrieving the requested data. If DevicePath is
1896 NULL, then all DevicePath values will be searched
1898 @param AltCfgId A pointer to the ALTCFG value to search for in the
1899 routing portion of the ConfigResp string when
1900 retrieving the requested data. If this parameter
1901 is NULL, then the current setting will be
1903 @param AltCfgResp A pointer to a buffer which will be allocated by
1904 the function which contains the retrieved string
1905 as requested. This buffer is only allocated if
1906 the call was successful.
1908 @retval EFI_SUCCESS The request succeeded. The requested data was
1909 extracted and placed in the newly allocated
1911 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
1912 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1913 @retval EFI_NOT_FOUND Target for the specified routing data was not
1920 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1921 IN CONST EFI_STRING Configuration
,
1922 IN CONST EFI_GUID
*Guid
,
1923 IN CONST EFI_STRING Name
,
1924 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1925 IN CONST UINT16
*AltCfgId
,
1926 OUT EFI_STRING
*AltCfgResp
1929 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
1932 EFI_STRING StringPtr
;
1933 EFI_STRING HdrStart
= NULL
;
1934 EFI_STRING HdrEnd
= NULL
;
1937 EFI_STRING GuidStr
= NULL
;
1938 EFI_STRING NameStr
= NULL
;
1939 EFI_STRING PathStr
= NULL
;
1940 EFI_STRING AltIdStr
= NULL
;
1941 EFI_STRING Result
= NULL
;
1942 BOOLEAN GuidFlag
= FALSE
;
1943 BOOLEAN NameFlag
= FALSE
;
1944 BOOLEAN PathFlag
= FALSE
;
1946 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
1947 return EFI_INVALID_PARAMETER
;
1950 StringPtr
= Configuration
;
1951 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1952 return EFI_INVALID_PARAMETER
;
1956 // Generate the sub string for later matching.
1958 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (UINT8
*) Guid
, FALSE
, &GuidStr
);
1961 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1962 (UINT8
*) DevicePath
,
1966 if (AltCfgId
!= NULL
) {
1967 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (UINT8
*) AltCfgId
, FALSE
, &AltIdStr
);
1970 Length
= StrLen (Name
);
1971 Length
+= StrLen (L
"NAME=&") + 1;
1972 NameStr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1973 if (NameStr
== NULL
) {
1974 Status
= EFI_OUT_OF_RESOURCES
;
1977 StrCpy (NameStr
, L
"NAME=");
1978 StrCat (NameStr
, Name
);
1979 StrCat (NameStr
, L
"&");
1981 GenerateSubStr (L
"NAME=", 0, NULL
, FALSE
, &NameStr
);
1984 while (*StringPtr
!= 0) {
1986 // Try to match the GUID
1989 TmpPtr
= StrStr (StringPtr
, GuidStr
);
1990 if (TmpPtr
== NULL
) {
1991 Status
= EFI_NOT_FOUND
;
1997 // Jump to <NameHdr>
2000 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
2002 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
2003 if (StringPtr
== NULL
) {
2004 Status
= EFI_NOT_FOUND
;
2012 // Try to match the NAME
2014 if (GuidFlag
&& !NameFlag
) {
2015 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
2019 // Jump to <PathHdr>
2022 StringPtr
+= StrLen (NameStr
);
2024 StringPtr
= StrStr (StringPtr
, L
"PATH=");
2025 if (StringPtr
== NULL
) {
2026 Status
= EFI_NOT_FOUND
;
2035 // Try to match the DevicePath
2037 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
2038 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
2043 // Jump to '&' before <DescHdr> or <ConfigBody>
2045 if (DevicePath
!= NULL
) {
2046 StringPtr
+= StrLen (PathStr
);
2048 StringPtr
= StrStr (StringPtr
, L
"&");
2049 if (StringPtr
== NULL
) {
2050 Status
= EFI_NOT_FOUND
;
2055 HdrEnd
= ++StringPtr
;
2060 // Try to match the AltCfgId
2062 if (GuidFlag
&& NameFlag
&& PathFlag
) {
2063 if (AltCfgId
== NULL
) {
2065 // Return Current Setting when AltCfgId is NULL.
2067 Status
= OutputConfigBody (StringPtr
, &Result
);
2071 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
2073 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
2078 Status
= OutputConfigBody (StringPtr
, &Result
);
2084 Status
= EFI_NOT_FOUND
;
2088 if (!EFI_ERROR (Status
)) {
2090 // Copy the <ConfigHdr> and <ConfigBody>
2092 Length
= HdrEnd
- HdrStart
+ StrLen (Result
);
2093 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2094 if (*AltCfgResp
== NULL
) {
2095 Status
= EFI_OUT_OF_RESOURCES
;
2097 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
2098 StrCat (*AltCfgResp
, Result
);
2099 Status
= EFI_SUCCESS
;
2103 SafeFreePool (GuidStr
);
2104 SafeFreePool (NameStr
);
2105 SafeFreePool (PathStr
);
2106 SafeFreePool (AltIdStr
);
2107 SafeFreePool (Result
);
2112 return EFI_UNSUPPORTED
;