2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2008, Intel Corporation
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.
16 #include "HiiDatabase.h"
19 Calculate the number of Unicode characters of the incoming Configuration string,
20 not including NULL terminator.
22 This is a internal function.
24 @param String String in <MultiConfigRequest> or
25 <MultiConfigResp> format.
27 @return The number of Unicode characters.
31 CalculateConfigStringLen (
38 // "GUID=" should be the first element of incoming string.
40 ASSERT (String
!= NULL
);
41 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
43 Length
= StrLen (L
"GUID=");
47 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
48 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
50 while (*String
!= 0 && StrnCmp (String
, L
"&GUID=", StrLen (L
"&GUID=")) != 0) {
60 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
61 from <PathHdr> of <ConfigHdr>.
63 This is a internal function.
65 @param String UEFI configuration string
66 @param DevicePath binary of a UEFI device path.
68 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
69 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
70 @retval EFI_SUCCESS The device path is retrieved and translated to
77 OUT UINT8
**DevicePath
82 EFI_STRING DevicePathString
;
84 if (String
== NULL
|| DevicePath
== NULL
) {
85 return EFI_INVALID_PARAMETER
;
89 // Find the 'PATH=' of <PathHdr> and skip it.
91 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
93 return EFI_INVALID_PARAMETER
;
96 String
+= StrLen (L
"PATH=");
100 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
101 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
102 // of UEFI device path.
104 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
105 DevicePathString
= (EFI_STRING
) AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
106 if (DevicePathString
== NULL
) {
107 return EFI_OUT_OF_RESOURCES
;
109 StrnCpy (DevicePathString
, PathHdr
, Length
);
110 *(DevicePathString
+ Length
) = 0;
113 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
114 // as the device path resides in RAM memory.
115 // Translate the data into binary.
118 *DevicePath
= (UINT8
*) AllocateZeroPool (Length
);
119 if (*DevicePath
== NULL
) {
120 FreePool (DevicePathString
);
121 return EFI_OUT_OF_RESOURCES
;
124 HexStringToBufInReverseOrder (*DevicePath
, &Length
, DevicePathString
);
126 FreePool (DevicePathString
);
134 Generate a sub string then output it.
136 This is a internal function.
138 @param String A constant string which is the prefix of the to be
139 generated string, e.g. GUID=
140 @param BufferLen The length of the Buffer in bytes.
141 @param Buffer Points to a buffer which will be converted to be the
142 content of the generated string.
143 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
144 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
145 if 3, the buffer contains other data.
146 @param SubStr Points to the output string. It's caller's
147 responsibility to free this buffer.
153 IN CONST EFI_STRING String
,
157 OUT EFI_STRING
*SubStr
163 EFI_STRING StringHeader
;
165 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
167 if (Buffer
== NULL
) {
168 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
169 ASSERT (*SubStr
!= NULL
);
173 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
174 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
175 ASSERT (Str
!= NULL
);
177 StrCpy (Str
, String
);
178 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
180 Status
= EFI_SUCCESS
;
181 StringHeader
= Str
+ StrLen (String
);
185 Status
= BufInReverseOrderToHexString (StringHeader
, (UINT8
*) Buffer
, BufferLen
);
188 Status
= UnicodeToConfigString (StringHeader
, &Length
, (CHAR16
*) Buffer
);
191 Status
= BufToHexString (StringHeader
, &Length
, (UINT8
*) Buffer
, BufferLen
);
193 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
195 ToLower (StringHeader
);
201 ASSERT_EFI_ERROR (Status
);
209 Retrieve the <ConfigBody> from String then output it.
211 This is a internal function.
213 @param String A sub string of a configuration string in
214 <MultiConfigAltResp> format.
215 @param ConfigBody Points to the output string. It's caller's
216 responsibility to free this buffer.
218 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
219 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
220 @retval EFI_SUCCESS All existing storage is exported.
225 IN EFI_STRING String
,
226 OUT EFI_STRING
*ConfigBody
233 if (String
== NULL
|| ConfigBody
== NULL
) {
234 return EFI_INVALID_PARAMETER
;
237 TmpPtr
= StrStr (String
, L
"GUID=");
238 if (TmpPtr
== NULL
) {
240 // It is the last <ConfigResp> of the incoming configuration string.
242 Result
= AllocateCopyPool (StrSize (String
), String
);
243 if (Result
== NULL
) {
244 return EFI_OUT_OF_RESOURCES
;
246 *ConfigBody
= Result
;
251 Length
= TmpPtr
- String
;
252 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
253 if (Result
== NULL
) {
254 return EFI_OUT_OF_RESOURCES
;
257 *(Result
+ Length
- 1) = 0;
258 *ConfigBody
= Result
;
264 Append a string to a multi-string format.
266 This is a internal function.
268 @param MultiString String in <MultiConfigRequest>,
269 <MultiConfigAltResp>, or <MultiConfigResp>. On
270 input, the buffer length of this string is
271 MAX_STRING_LENGTH. On output, the buffer length
273 @param AppendString NULL-terminated Unicode string.
275 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
276 @retval EFI_SUCCESS AppendString is append to the end of MultiString
280 AppendToMultiString (
281 IN OUT EFI_STRING
*MultiString
,
282 IN EFI_STRING AppendString
285 UINTN AppendStringSize
;
286 UINTN MultiStringSize
;
288 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
289 return EFI_INVALID_PARAMETER
;
292 AppendStringSize
= StrSize (AppendString
);
293 MultiStringSize
= StrSize (*MultiString
);
296 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
298 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
299 MultiStringSize
> MAX_STRING_LENGTH
) {
300 *MultiString
= (EFI_STRING
) ReallocatePool (
302 MultiStringSize
+ AppendStringSize
,
303 (VOID
*) (*MultiString
)
305 ASSERT (*MultiString
!= NULL
);
308 // Append the incoming string
310 StrCat (*MultiString
, AppendString
);
317 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
319 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
321 This is a internal function.
323 @param StringPtr String in <BlockConfig> format and points to the
324 first character of <Number>.
325 @param Number The output value. Caller takes the responsibility
327 @param Len Length of the <Number>, in characters.
329 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
331 @retval EFI_SUCCESS Value of <Number> is outputted in Number
337 IN EFI_STRING StringPtr
,
348 ASSERT (StringPtr
!= NULL
&& Number
!= NULL
&& Len
!= NULL
);
349 ASSERT (*StringPtr
!= 0);
354 while (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
357 *Len
= StringPtr
- TmpPtr
;
360 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (EFI_STRING
));
362 Status
= EFI_OUT_OF_RESOURCES
;
365 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
368 Length
= (Length
+ 1) / 2;
369 Buf
= (UINT8
*) AllocateZeroPool (Length
);
371 Status
= EFI_OUT_OF_RESOURCES
;
375 Status
= HexStringToBuf (Buf
, &Length
, Str
, NULL
);
376 if (EFI_ERROR (Status
)) {
381 Status
= EFI_SUCCESS
;
392 This function allows a caller to extract the current configuration
393 for one or more named elements from one or more drivers.
395 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
397 @param Request A null-terminated Unicode string in
398 <MultiConfigRequest> format.
399 @param Progress On return, points to a character in the Request
400 string. Points to the string's null terminator if
401 request was successful. Points to the most recent
402 & before the first failing name / value pair (or
403 the beginning of the string if the failure is in
404 the first name / value pair) if the request was
406 @param Results Null-terminated Unicode string in
407 <MultiConfigAltResp> format which has all values
408 filled in for the names in the Request string.
409 String to be allocated by the called function.
411 @retval EFI_SUCCESS The Results string is filled with the values
412 corresponding to all requested names.
413 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
414 results that must be stored awaiting possible
416 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
417 Progress set to the "G" in "GUID" of the routing
418 header that doesn't match. Note: There is no
419 requirement that all routing data be validated
420 before any configuration extraction.
421 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
422 parameter would result in this type of error. The
423 Progress parameter is set to NULL.
424 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
425 before the error or the beginning of the string.
426 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
432 HiiConfigRoutingExtractConfig (
433 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
434 IN CONST EFI_STRING Request
,
435 OUT EFI_STRING
*Progress
,
436 OUT EFI_STRING
*Results
439 HII_DATABASE_PRIVATE_DATA
*Private
;
440 EFI_STRING StringPtr
;
441 EFI_STRING ConfigRequest
;
443 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
446 HII_DATABASE_RECORD
*Database
;
447 UINT8
*DevicePathPkg
;
448 UINT8
*CurrentDevicePath
;
449 EFI_HANDLE DriverHandle
;
450 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
451 EFI_STRING AccessProgress
;
452 EFI_STRING AccessResults
;
453 BOOLEAN FirstElement
;
455 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
456 return EFI_INVALID_PARAMETER
;
459 if (Request
== NULL
) {
461 return EFI_INVALID_PARAMETER
;
464 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
466 *Progress
= StringPtr
;
469 // The first element of <MultiConfigRequest> should be
470 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
472 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
473 return EFI_INVALID_PARAMETER
;
479 // Allocate a fix length of memory to store Results. Reallocate memory for
480 // Results if this fix length is insufficient.
482 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
483 if (*Results
== NULL
) {
484 return EFI_OUT_OF_RESOURCES
;
487 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
489 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
490 // or most recent & before the error.
492 if (StringPtr
== Request
) {
493 *Progress
= StringPtr
;
495 *Progress
= StringPtr
- 1;
499 // Process each <ConfigRequest> of <MultiConfigRequest>
501 Length
= CalculateConfigStringLen (StringPtr
);
502 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
503 if (ConfigRequest
== NULL
) {
504 return EFI_OUT_OF_RESOURCES
;
506 *(ConfigRequest
+ Length
) = 0;
509 // Get the UEFI device path
511 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
512 if (EFI_ERROR (Status
)) {
513 FreePool (ConfigRequest
);
518 // Find driver which matches the routing data.
521 for (Link
= Private
->DatabaseList
.ForwardLink
;
522 Link
!= &Private
->DatabaseList
;
523 Link
= Link
->ForwardLink
525 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
527 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
528 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
532 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
534 DriverHandle
= Database
->DriverHandle
;
540 FreePool (DevicePath
);
542 if (DriverHandle
== NULL
) {
544 // Routing data does not match any known driver.
545 // Set Progress to the 'G' in "GUID" of the routing header.
547 *Progress
= StringPtr
;
548 FreePool (ConfigRequest
);
549 return EFI_NOT_FOUND
;
553 // Call corresponding ConfigAccess protocol to extract settings
555 Status
= gBS
->HandleProtocol (
557 &gEfiHiiConfigAccessProtocolGuid
,
558 (VOID
**) &ConfigAccess
560 ASSERT_EFI_ERROR (Status
);
562 Status
= ConfigAccess
->ExtractConfig (
568 if (EFI_ERROR (Status
)) {
570 // AccessProgress indicates the parsing progress on <ConfigRequest>.
571 // Map it to the progress on <MultiConfigRequest> then return it.
573 *Progress
= StrStr (StringPtr
, AccessProgress
);
574 FreePool (ConfigRequest
);
579 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
580 // which seperates the first <ConfigAltResp> and the following ones.
582 ASSERT (*AccessProgress
== 0);
585 Status
= AppendToMultiString (Results
, L
"&");
586 ASSERT_EFI_ERROR (Status
);
589 Status
= AppendToMultiString (Results
, AccessResults
);
590 ASSERT_EFI_ERROR (Status
);
592 FirstElement
= FALSE
;
594 FreePool (AccessResults
);
595 AccessResults
= NULL
;
596 FreePool (ConfigRequest
);
597 ConfigRequest
= NULL
;
600 // Go to next <ConfigRequest> (skip '&').
603 if (*StringPtr
== 0) {
604 *Progress
= StringPtr
;
618 This function allows the caller to request the current configuration for the
619 entirety of the current HII database and returns the data in a
620 null-terminated Unicode string.
622 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
624 @param Results Null-terminated Unicode string in
625 <MultiConfigAltResp> format which has all values
626 filled in for the names in the Request string.
627 String to be allocated by the called function.
628 De-allocation is up to the caller.
630 @retval EFI_SUCCESS The Results string is filled with the values
631 corresponding to all requested names.
632 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
633 results that must be stored awaiting possible
635 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
636 parameter would result in this type of error.
641 HiiConfigRoutingExportConfig (
642 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
643 OUT EFI_STRING
*Results
647 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
648 EFI_STRING AccessResults
;
650 EFI_HANDLE
*ConfigAccessHandles
;
651 UINTN NumberConfigAccessHandles
;
652 BOOLEAN FirstElement
;
654 if (This
== NULL
|| Results
== NULL
) {
655 return EFI_INVALID_PARAMETER
;
659 // Allocate a fix length of memory to store Results. Reallocate memory for
660 // Results if this fix length is insufficient.
662 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
663 if (*Results
== NULL
) {
664 return EFI_OUT_OF_RESOURCES
;
667 NumberConfigAccessHandles
= 0;
668 Status
= gBS
->LocateHandleBuffer (
670 &gEfiHiiConfigAccessProtocolGuid
,
672 &NumberConfigAccessHandles
,
675 if (EFI_ERROR (Status
)) {
681 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
682 Status
= gBS
->HandleProtocol (
683 ConfigAccessHandles
[Index
],
684 &gEfiHiiConfigAccessProtocolGuid
,
685 (VOID
**) &ConfigAccess
687 if (EFI_ERROR (Status
)) {
691 Status
= ConfigAccess
->ExtractConfig (
697 if (!EFI_ERROR (Status
)) {
699 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
700 // which seperates the first <ConfigAltResp> and the following ones.
703 Status
= AppendToMultiString (Results
, L
"&");
704 ASSERT_EFI_ERROR (Status
);
707 Status
= AppendToMultiString (Results
, AccessResults
);
708 ASSERT_EFI_ERROR (Status
);
710 FirstElement
= FALSE
;
712 FreePool (AccessResults
);
713 AccessResults
= NULL
;
716 FreePool (ConfigAccessHandles
);
723 This function processes the results of processing forms and routes it to the
724 appropriate handlers or storage.
726 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
728 @param Configuration A null-terminated Unicode string in
729 <MulltiConfigResp> format.
730 @param Progress A pointer to a string filled in with the offset of
731 the most recent & before the first failing name /
732 value pair (or the beginning of the string if the
733 failure is in the first name / value pair) or the
734 terminating NULL if all was successful.
736 @retval EFI_SUCCESS The results have been distributed or are awaiting
738 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
739 results that must be stored awaiting possible
741 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
742 would result in this type of error.
743 @retval EFI_NOT_FOUND Target for the specified routing data was not
749 HiiConfigRoutingRouteConfig (
750 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
751 IN CONST EFI_STRING Configuration
,
752 OUT EFI_STRING
*Progress
755 HII_DATABASE_PRIVATE_DATA
*Private
;
756 EFI_STRING StringPtr
;
757 EFI_STRING ConfigResp
;
760 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
762 HII_DATABASE_RECORD
*Database
;
763 UINT8
*DevicePathPkg
;
764 UINT8
*CurrentDevicePath
;
765 EFI_HANDLE DriverHandle
;
766 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
767 EFI_STRING AccessProgress
;
769 if (This
== NULL
|| Progress
== NULL
) {
770 return EFI_INVALID_PARAMETER
;
773 if (Configuration
== NULL
) {
775 return EFI_INVALID_PARAMETER
;
778 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
779 StringPtr
= Configuration
;
780 *Progress
= StringPtr
;
783 // The first element of <MultiConfigResp> should be
784 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
786 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
787 return EFI_INVALID_PARAMETER
;
790 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
792 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
793 // or most recent & before the error.
795 if (StringPtr
== Configuration
) {
796 *Progress
= StringPtr
;
798 *Progress
= StringPtr
- 1;
802 // Process each <ConfigResp> of <MultiConfigResp>
804 Length
= CalculateConfigStringLen (StringPtr
);
805 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
806 if (ConfigResp
== NULL
) {
807 return EFI_OUT_OF_RESOURCES
;
810 // Append '\0' to the end of ConfigRequest
812 *(ConfigResp
+ Length
) = 0;
815 // Get the UEFI device path
817 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
818 if (EFI_ERROR (Status
)) {
819 FreePool (ConfigResp
);
824 // Find driver which matches the routing data.
827 for (Link
= Private
->DatabaseList
.ForwardLink
;
828 Link
!= &Private
->DatabaseList
;
829 Link
= Link
->ForwardLink
831 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
833 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
834 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
838 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
840 DriverHandle
= Database
->DriverHandle
;
846 FreePool (DevicePath
);
848 if (DriverHandle
== NULL
) {
850 // Routing data does not match any known driver.
851 // Set Progress to the 'G' in "GUID" of the routing header.
853 *Progress
= StringPtr
;
854 FreePool (ConfigResp
);
855 return EFI_NOT_FOUND
;
859 // Call corresponding ConfigAccess protocol to route settings
861 Status
= gBS
->HandleProtocol (
863 &gEfiHiiConfigAccessProtocolGuid
,
864 (VOID
**) &ConfigAccess
866 ASSERT_EFI_ERROR (Status
);
868 Status
= ConfigAccess
->RouteConfig (
874 if (EFI_ERROR (Status
)) {
876 // AccessProgress indicates the parsing progress on <ConfigResp>.
877 // Map it to the progress on <MultiConfigResp> then return it.
879 *Progress
= StrStr (StringPtr
, AccessProgress
);
881 FreePool (ConfigResp
);
885 FreePool (ConfigResp
);
889 // Go to next <ConfigResp> (skip '&').
892 if (*StringPtr
== 0) {
893 *Progress
= StringPtr
;
906 This helper function is to be called by drivers to map configuration data
907 stored in byte array ("block") formats such as UEFI Variables into current
908 configuration strings.
910 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
912 @param ConfigRequest A null-terminated Unicode string in
913 <ConfigRequest> format.
914 @param Block Array of bytes defining the block's configuration.
915 @param BlockSize Length in bytes of Block.
916 @param Config Filled-in configuration string. String allocated
917 by the function. Returned only if call is
919 @param Progress A pointer to a string filled in with the offset of
920 the most recent & before the first failing
921 name/value pair (or the beginning of the string if
922 the failure is in the first name / value pair) or
923 the terminating NULL if all was successful.
925 @retval EFI_SUCCESS The request succeeded. Progress points to the null
926 terminator at the end of the ConfigRequest
928 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
929 points to the first character of ConfigRequest.
930 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
931 Block parameter would result in this type of
932 error. Progress points to the first character of
934 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
935 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
936 Block is left updated and Progress points at
937 the "&" preceding the first non-<BlockName>.
943 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
944 IN CONST EFI_STRING ConfigRequest
,
945 IN CONST UINT8
*Block
,
946 IN CONST UINTN BlockSize
,
947 OUT EFI_STRING
*Config
,
948 OUT EFI_STRING
*Progress
951 HII_DATABASE_PRIVATE_DATA
*Private
;
952 EFI_STRING StringPtr
;
961 EFI_STRING ConfigElement
;
963 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
964 return EFI_INVALID_PARAMETER
;
967 if (Block
== NULL
|| ConfigRequest
== NULL
) {
968 *Progress
= ConfigRequest
;
969 return EFI_INVALID_PARAMETER
;
973 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
974 ASSERT (Private
!= NULL
);
976 StringPtr
= ConfigRequest
;
979 ConfigElement
= NULL
;
982 // Allocate a fix length of memory to store Results. Reallocate memory for
983 // Results if this fix length is insufficient.
985 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
986 if (*Config
== NULL
) {
987 return EFI_OUT_OF_RESOURCES
;
993 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
994 *Progress
= StringPtr
;
995 Status
= EFI_INVALID_PARAMETER
;
998 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1001 if (*StringPtr
== 0) {
1002 *Progress
= StringPtr
;
1003 Status
= EFI_INVALID_PARAMETER
;
1007 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
1010 if (*StringPtr
== 0) {
1011 *Progress
= StringPtr
;
1012 Status
= EFI_INVALID_PARAMETER
;
1021 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
1023 Length
= StringPtr
- ConfigRequest
;
1024 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
1027 // Parse each <RequestElement> if exists
1028 // Only <BlockName> format is supported by this help function.
1029 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
1031 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1033 // Back up the header of one <BlockName>
1037 StringPtr
+= StrLen (L
"OFFSET=");
1041 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1042 if (Status
== EFI_OUT_OF_RESOURCES
) {
1043 *Progress
= ConfigRequest
;
1050 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1052 FreePool (TmpBuffer
);
1054 StringPtr
+= Length
;
1055 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1056 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1057 Status
= EFI_INVALID_PARAMETER
;
1060 StringPtr
+= StrLen (L
"&WIDTH=");
1065 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1066 if (Status
== EFI_OUT_OF_RESOURCES
) {
1067 *Progress
= ConfigRequest
;
1074 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1076 FreePool (TmpBuffer
);
1078 StringPtr
+= Length
;
1079 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1080 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1081 Status
= EFI_INVALID_PARAMETER
;
1086 // Calculate Value and convert it to hex string.
1088 if (Offset
+ Width
> BlockSize
) {
1089 *Progress
= StringPtr
;
1090 Status
= EFI_DEVICE_ERROR
;
1094 Value
= (UINT8
*) AllocateZeroPool (Width
);
1095 if (Value
== NULL
) {
1096 *Progress
= ConfigRequest
;
1097 Status
= EFI_OUT_OF_RESOURCES
;
1101 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
1103 Length
= Width
* 2 + 1;
1104 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1105 if (ValueStr
== NULL
) {
1106 *Progress
= ConfigRequest
;
1107 Status
= EFI_OUT_OF_RESOURCES
;
1111 Status
= BufToHexString (ValueStr
, &Length
, Value
, Width
);
1112 ASSERT_EFI_ERROR (Status
);
1119 // Build a ConfigElement
1121 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
1122 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1123 if (ConfigElement
== NULL
) {
1124 Status
= EFI_OUT_OF_RESOURCES
;
1127 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
1128 if (*StringPtr
== 0) {
1129 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
1131 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
1132 StrCat (ConfigElement
, L
"VALUE=");
1133 StrCat (ConfigElement
, ValueStr
);
1135 AppendToMultiString (Config
, ConfigElement
);
1137 FreePool (ConfigElement
);
1138 FreePool (ValueStr
);
1139 ConfigElement
= NULL
;
1143 // If '\0', parsing is finished. Otherwise skip '&' to continue
1145 if (*StringPtr
== 0) {
1148 AppendToMultiString (Config
, L
"&");
1153 if (*StringPtr
!= 0) {
1154 *Progress
= StringPtr
- 1;
1155 Status
= EFI_INVALID_PARAMETER
;
1159 *Progress
= StringPtr
;
1164 if (ValueStr
!= NULL
) {
1165 FreePool (ValueStr
);
1167 if (Value
!= NULL
) {
1170 if (ConfigElement
!= NULL
) {
1171 FreePool (ConfigElement
);
1180 This helper function is to be called by drivers to map configuration strings
1181 to configurations stored in byte array ("block") formats such as UEFI Variables.
1183 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1185 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
1187 @param Block A possibly null array of bytes representing the
1188 current block. Only bytes referenced in the
1189 ConfigResp string in the block are modified. If
1190 this parameter is null or if the *BlockSize
1191 parameter is (on input) shorter than required by
1192 the Configuration string, only the BlockSize
1193 parameter is updated and an appropriate status
1194 (see below) is returned.
1195 @param BlockSize The length of the Block in units of UINT8. On
1196 input, this is the size of the Block. On output,
1197 if successful, contains the index of the last
1198 modified byte in the Block.
1199 @param Progress On return, points to an element of the ConfigResp
1200 string filled in with the offset of the most
1201 recent '&' before the first failing name / value
1202 pair (or the beginning of the string if the
1203 failure is in the first name / value pair) or the
1204 terminating NULL if all was successful.
1206 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1207 terminator at the end of the ConfigResp string.
1208 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1209 points to the first character of ConfigResp.
1210 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
1211 Block parameter would result in this type of
1212 error. Progress points to the first character of
1214 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
1215 value pair. Block is left updated and
1216 Progress points at the '&' preceding the first
1223 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1224 IN CONST EFI_STRING ConfigResp
,
1225 IN OUT UINT8
*Block
,
1226 IN OUT UINTN
*BlockSize
,
1227 OUT EFI_STRING
*Progress
1230 HII_DATABASE_PRIVATE_DATA
*Private
;
1231 EFI_STRING StringPtr
;
1240 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
1241 return EFI_INVALID_PARAMETER
;
1244 if (ConfigResp
== NULL
|| Block
== NULL
) {
1245 *Progress
= ConfigResp
;
1246 return EFI_INVALID_PARAMETER
;
1249 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1250 ASSERT (Private
!= NULL
);
1252 StringPtr
= ConfigResp
;
1253 BufferSize
= *BlockSize
;
1259 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1260 *Progress
= StringPtr
;
1261 Status
= EFI_INVALID_PARAMETER
;
1264 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1267 if (*StringPtr
== 0) {
1268 *Progress
= StringPtr
;
1269 Status
= EFI_INVALID_PARAMETER
;
1273 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
1276 if (*StringPtr
== 0) {
1277 *Progress
= StringPtr
;
1278 Status
= EFI_INVALID_PARAMETER
;
1287 // Parse each <ConfigElement> if exists
1288 // Only <BlockConfig> format is supported by this help function.
1289 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
1291 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1292 StringPtr
+= StrLen (L
"OFFSET=");
1296 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1297 if (EFI_ERROR (Status
)) {
1298 *Progress
= ConfigResp
;
1305 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1307 FreePool (TmpBuffer
);
1309 StringPtr
+= Length
;
1310 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1311 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1312 Status
= EFI_INVALID_PARAMETER
;
1315 StringPtr
+= StrLen (L
"&WIDTH=");
1320 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1321 if (Status
== EFI_OUT_OF_RESOURCES
) {
1322 *Progress
= ConfigResp
;
1329 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1331 FreePool (TmpBuffer
);
1333 StringPtr
+= Length
;
1334 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1335 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1336 Status
= EFI_INVALID_PARAMETER
;
1339 StringPtr
+= StrLen (L
"&VALUE=");
1344 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
1345 if (EFI_ERROR (Status
)) {
1346 *Progress
= ConfigResp
;
1350 StringPtr
+= Length
;
1351 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1352 *Progress
= StringPtr
- Length
- 7;
1353 Status
= EFI_INVALID_PARAMETER
;
1358 // Update the Block with configuration info
1361 if (Offset
+ Width
> BufferSize
) {
1362 return EFI_DEVICE_ERROR
;
1365 CopyMem (Block
+ Offset
, Value
, Width
);
1366 *BlockSize
= Offset
+ Width
- 1;
1372 // If '\0', parsing is finished. Otherwise skip '&' to continue
1374 if (*StringPtr
== 0) {
1381 if (*StringPtr
!= 0) {
1382 *Progress
= StringPtr
- 1;
1383 Status
= EFI_INVALID_PARAMETER
;
1387 *Progress
= StringPtr
;
1392 if (Value
!= NULL
) {
1400 This helper function is to be called by drivers to extract portions of
1401 a larger configuration string.
1403 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1405 @param Configuration A null-terminated Unicode string in
1406 <MultiConfigAltResp> format.
1407 @param Guid A pointer to the GUID value to search for in the
1408 routing portion of the ConfigResp string when
1409 retrieving the requested data. If Guid is NULL,
1410 then all GUID values will be searched for.
1411 @param Name A pointer to the NAME value to search for in the
1412 routing portion of the ConfigResp string when
1413 retrieving the requested data. If Name is NULL,
1414 then all Name values will be searched for.
1415 @param DevicePath A pointer to the PATH value to search for in the
1416 routing portion of the ConfigResp string when
1417 retrieving the requested data. If DevicePath is
1418 NULL, then all DevicePath values will be searched
1420 @param AltCfgId A pointer to the ALTCFG value to search for in the
1421 routing portion of the ConfigResp string when
1422 retrieving the requested data. If this parameter
1423 is NULL, then the current setting will be
1425 @param AltCfgResp A pointer to a buffer which will be allocated by
1426 the function which contains the retrieved string
1427 as requested. This buffer is only allocated if
1428 the call was successful.
1430 @retval EFI_SUCCESS The request succeeded. The requested data was
1431 extracted and placed in the newly allocated
1433 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
1434 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1435 @retval EFI_NOT_FOUND Target for the specified routing data was not
1442 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1443 IN CONST EFI_STRING Configuration
,
1444 IN CONST EFI_GUID
*Guid
,
1445 IN CONST EFI_STRING Name
,
1446 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1447 IN CONST UINT16
*AltCfgId
,
1448 OUT EFI_STRING
*AltCfgResp
1452 EFI_STRING StringPtr
;
1453 EFI_STRING HdrStart
;
1460 EFI_STRING AltIdStr
;
1477 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
1478 return EFI_INVALID_PARAMETER
;
1481 StringPtr
= Configuration
;
1482 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1483 return EFI_INVALID_PARAMETER
;
1487 // Generate the sub string for later matching.
1489 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
1492 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1493 (VOID
*) DevicePath
,
1497 if (AltCfgId
!= NULL
) {
1498 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
1501 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1503 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1506 while (*StringPtr
!= 0) {
1508 // Try to match the GUID
1511 TmpPtr
= StrStr (StringPtr
, GuidStr
);
1512 if (TmpPtr
== NULL
) {
1513 Status
= EFI_NOT_FOUND
;
1519 // Jump to <NameHdr>
1522 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
1524 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
1525 if (StringPtr
== NULL
) {
1526 Status
= EFI_NOT_FOUND
;
1534 // Try to match the NAME
1536 if (GuidFlag
&& !NameFlag
) {
1537 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
1541 // Jump to <PathHdr>
1544 StringPtr
+= StrLen (NameStr
);
1546 StringPtr
= StrStr (StringPtr
, L
"PATH=");
1547 if (StringPtr
== NULL
) {
1548 Status
= EFI_NOT_FOUND
;
1557 // Try to match the DevicePath
1559 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
1560 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
1565 // Jump to '&' before <DescHdr> or <ConfigBody>
1567 if (DevicePath
!= NULL
) {
1568 StringPtr
+= StrLen (PathStr
);
1570 StringPtr
= StrStr (StringPtr
, L
"&");
1571 if (StringPtr
== NULL
) {
1572 Status
= EFI_NOT_FOUND
;
1577 HdrEnd
= ++StringPtr
;
1582 // Try to match the AltCfgId
1584 if (GuidFlag
&& NameFlag
&& PathFlag
) {
1585 if (AltCfgId
== NULL
) {
1587 // Return Current Setting when AltCfgId is NULL.
1589 Status
= OutputConfigBody (StringPtr
, &Result
);
1593 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
1595 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
1600 Status
= OutputConfigBody (StringPtr
, &Result
);
1606 Status
= EFI_NOT_FOUND
;
1610 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
1612 // Copy the <ConfigHdr> and <ConfigBody>
1614 Length
= HdrEnd
- HdrStart
+ StrLen (Result
);
1615 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1616 if (*AltCfgResp
== NULL
) {
1617 Status
= EFI_OUT_OF_RESOURCES
;
1619 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
1620 StrCat (*AltCfgResp
, Result
);
1621 Status
= EFI_SUCCESS
;
1625 if (GuidStr
!= NULL
) {
1628 if (NameStr
!= NULL
) {
1631 if (PathStr
!= NULL
) {
1634 if (AltIdStr
!= NULL
) {
1635 FreePool (AltIdStr
);
1637 if (Result
!= NULL
) {