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
31 Calculate the number of Unicode characters of the incoming Configuration string,
32 not including NULL terminator.
34 @param String String in <MultiConfigRequest> or
35 <MultiConfigResp> format.
37 @return The number of Unicode characters.
42 CalculateConfigStringLen (
49 // "GUID=" should be the first element of incoming string.
51 ASSERT (String
!= NULL
);
52 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
54 Length
= StrLen (L
"GUID=");
58 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
59 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
61 while (*String
!= 0 && StrnCmp (String
, L
"&GUID=", StrLen (L
"&GUID=")) != 0) {
71 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
72 from <PathHdr> of <ConfigHdr>.
74 @param String UEFI configuration string
75 @param DevicePath binary of a UEFI device path.
77 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
78 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
79 @retval EFI_SUCCESS The device path is retrieved and translated to
87 OUT UINT8
**DevicePath
92 EFI_STRING DevicePathString
;
94 if (String
== NULL
|| DevicePath
== NULL
) {
95 return EFI_INVALID_PARAMETER
;
99 // Find the 'PATH=' of <PathHdr> and skip it.
101 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
103 return EFI_INVALID_PARAMETER
;
106 String
+= StrLen (L
"PATH=");
110 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
111 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
112 // of UEFI device path.
114 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 DevicePathString
= (EFI_STRING
) AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
116 if (DevicePathString
== NULL
) {
117 return EFI_OUT_OF_RESOURCES
;
119 StrnCpy (DevicePathString
, PathHdr
, Length
);
120 *(DevicePathString
+ Length
) = 0;
123 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
124 // as the device path resides in RAM memory.
125 // Translate the data into binary.
128 *DevicePath
= (UINT8
*) AllocateZeroPool (Length
);
129 if (*DevicePath
== NULL
) {
130 SafeFreePool (DevicePathString
);
131 return EFI_OUT_OF_RESOURCES
;
134 HexStringToBuffer (*DevicePath
, &Length
, DevicePathString
);
136 SafeFreePool (DevicePathString
);
144 Extract Storage from all Form Packages in current hii database.
146 @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.
147 @param StorageListHead Storage link List head.
149 @retval EFI_NOT_FOUND There is no form package in current hii database.
150 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
151 @retval EFI_SUCCESS All existing storage is exported.
157 IN EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
,
158 IN OUT LIST_ENTRY
*StorageListHead
164 EFI_HII_HANDLE
*HandleBuffer
;
167 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
168 EFI_HII_PACKAGE_HEADER
*Package
;
172 HII_FORMSET_STORAGE
*Storage
;
173 EFI_HII_HANDLE HiiHandle
;
174 EFI_HANDLE DriverHandle
;
176 UINT32 PackageListLength
;
177 EFI_HII_PACKAGE_HEADER PackageHeader
;
180 // Find the package list which contains Form package.
184 Status
= HiiListPackageLists (
186 EFI_HII_PACKAGE_FORM
,
191 if (Status
== EFI_BUFFER_TOO_SMALL
) {
192 HandleBuffer
= AllocateZeroPool (BufferSize
);
193 ASSERT (HandleBuffer
!= NULL
);
195 Status
= HiiListPackageLists (
197 EFI_HII_PACKAGE_FORM
,
203 if (EFI_ERROR (Status
)) {
204 SafeFreePool (HandleBuffer
);
208 HandleCount
= BufferSize
/ sizeof (EFI_HII_HANDLE
);
209 for (Index
= 0; Index
< HandleCount
; Index
++) {
210 HiiHandle
= HandleBuffer
[Index
];
213 HiiPackageList
= NULL
;
214 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
215 if (Status
== EFI_BUFFER_TOO_SMALL
) {
216 HiiPackageList
= AllocateZeroPool (BufferSize
);
217 ASSERT (HiiPackageList
!= NULL
);
218 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
220 if (EFI_ERROR (Status
)) {
221 SafeFreePool (HandleBuffer
);
222 SafeFreePool (HiiPackageList
);
227 // Get Form package from this HII package List
229 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
230 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
232 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
234 while (Offset
< PackageListLength
) {
235 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
236 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
237 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
240 Offset
+= PackageHeader
.Length
;
242 if (Offset
>= PackageListLength
) {
244 // Error here: No Form package found in this Package List
250 // Search Storage definition in this Form package
252 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
253 while (Offset
< PackageHeader
.Length
) {
254 OpCodeData
= ((UINT8
*) Package
) + Offset
;
255 Offset
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
257 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
259 if ((Operand
== EFI_IFR_VARSTORE_OP
) ||
260 (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) ||
261 (Operand
== EFI_IFR_VARSTORE_EFI_OP
)) {
263 Storage
= AllocateZeroPool (sizeof (HII_FORMSET_STORAGE
));
264 ASSERT (Storage
!= NULL
);
265 InsertTailList (StorageListHead
, &Storage
->Entry
);
267 Storage
->Signature
= HII_FORMSET_STORAGE_SIGNATURE
;
268 Storage
->HiiHandle
= HiiHandle
;
270 Status
= HiiGetPackageListHandle (HiiDatabase
, HiiHandle
, &DriverHandle
);
271 if (EFI_ERROR (Status
)) {
272 SafeFreePool (HandleBuffer
);
273 SafeFreePool (HiiPackageList
);
274 SafeFreePool (Storage
);
277 Storage
->DriverHandle
= DriverHandle
;
279 if (Operand
== EFI_IFR_VARSTORE_OP
) {
280 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
282 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
283 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
285 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
286 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
287 ASSERT (Storage
->Name
!= NULL
);
288 for (Index2
= 0; AsciiString
[Index2
] != 0; Index2
++) {
289 Storage
->Name
[Index2
] = (CHAR16
) AsciiString
[Index2
];
292 // Append '\0' to the end of the unicode string.
294 Storage
->Name
[Index2
] = 0;
295 } else if (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
296 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
298 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
299 } else if (Operand
== EFI_IFR_VARSTORE_EFI_OP
) {
300 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
302 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
307 SafeFreePool (HiiPackageList
);
310 SafeFreePool (HandleBuffer
);
317 Generate a sub string then output it.
319 @param String A constant string which is the prefix of the to be
320 generated string, e.g. GUID=
321 @param BufferLen The length of the Buffer in bytes.
322 @param Buffer Points to a buffer which will be converted to be the
323 content of the generated string.
324 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
325 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
326 if 3, the buffer contains other data.
327 @param SubStr Points to the output string. It's caller's
328 responsibility to free this buffer.
335 IN CONST EFI_STRING String
,
339 OUT EFI_STRING
*SubStr
345 EFI_STRING StringHeader
;
347 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
349 if (Buffer
== NULL
) {
350 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
351 ASSERT (*SubStr
!= NULL
);
355 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
356 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
357 ASSERT (Str
!= NULL
);
359 StrCpy (Str
, String
);
360 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
362 Status
= EFI_SUCCESS
;
363 StringHeader
= Str
+ StrLen (String
);
367 Status
= BufferToHexString (StringHeader
, (UINT8
*) Buffer
, BufferLen
);
370 Status
= UnicodeToConfigString (StringHeader
, &Length
, (CHAR16
*) Buffer
);
373 Status
= BufToHexString (StringHeader
, &Length
, (UINT8
*) Buffer
, BufferLen
);
375 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
377 ToLower (StringHeader
);
383 ASSERT_EFI_ERROR (Status
);
391 Retrieve the <ConfigBody> from String then output it.
393 @param String A sub string of a configuration string in
394 <MultiConfigAltResp> format.
395 @param ConfigBody Points to the output string. It's caller's
396 responsibility to free this buffer.
398 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
399 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
400 @retval EFI_SUCCESS All existing storage is exported.
406 IN EFI_STRING String
,
407 OUT EFI_STRING
*ConfigBody
414 if (String
== NULL
|| ConfigBody
== NULL
) {
415 return EFI_INVALID_PARAMETER
;
418 TmpPtr
= StrStr (String
, L
"GUID=");
419 if (TmpPtr
== NULL
) {
421 // It is the last <ConfigResp> of the incoming configuration string.
423 Result
= AllocateCopyPool (StrSize (String
), String
);
424 if (Result
== NULL
) {
425 return EFI_OUT_OF_RESOURCES
;
427 *ConfigBody
= Result
;
432 Length
= TmpPtr
- String
;
433 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
434 if (Result
== NULL
) {
435 return EFI_OUT_OF_RESOURCES
;
438 *(Result
+ Length
- 1) = 0;
439 *ConfigBody
= Result
;
456 Adjusts the size of a previously allocated buffer.
459 OldPool - A pointer to the buffer whose size is being adjusted.
460 OldSize - The size of the current buffer.
461 NewSize - The size of the new buffer.
464 Points to the new buffer
472 NewPool
= AllocateZeroPool (NewSize
);
477 CopyMem (NewPool
, OldPool
, OldSize
< NewSize
? OldSize
: NewSize
);
480 gBS
->FreePool (OldPool
);
488 Append a string to a multi-string format.
490 @param MultiString String in <MultiConfigRequest>,
491 <MultiConfigAltResp>, or <MultiConfigResp>. On
492 input, the buffer length of this string is
493 MAX_STRING_LENGTH. On output, the buffer length
495 @param AppendString NULL-terminated Unicode string.
497 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
498 @retval EFI_SUCCESS AppendString is append to the end of MultiString
503 AppendToMultiString (
504 IN OUT EFI_STRING
*MultiString
,
505 IN EFI_STRING AppendString
508 UINTN AppendStringSize
;
509 UINTN MultiStringSize
;
511 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
512 return EFI_INVALID_PARAMETER
;
515 AppendStringSize
= StrSize (AppendString
);
516 MultiStringSize
= StrSize (*MultiString
);
519 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
521 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
522 MultiStringSize
> MAX_STRING_LENGTH
) {
523 *MultiString
= (EFI_STRING
) ReallocatePool (
524 (VOID
*) (*MultiString
),
526 MultiStringSize
+ AppendStringSize
531 // Append the incoming string
533 StrCat (*MultiString
, AppendString
);
540 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
542 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
544 @param StringPtr String in <BlockConfig> format and points to the
545 first character of <Number>.
546 @param Number The output value. Caller takes the responsibility
548 @param Len Length of the <Number>, in characters.
550 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
552 @retval EFI_SUCCESS Value of <Number> is outputted in Number
559 IN EFI_STRING StringPtr
,
570 ASSERT (StringPtr
!= NULL
&& Number
!= NULL
&& Len
!= NULL
);
571 ASSERT (*StringPtr
!= 0);
576 while (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
579 *Len
= StringPtr
- TmpPtr
;
582 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (EFI_STRING
));
584 Status
= EFI_OUT_OF_RESOURCES
;
587 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
590 Length
= (Length
+ 1) / 2;
591 Buf
= (UINT8
*) AllocateZeroPool (Length
);
593 Status
= EFI_OUT_OF_RESOURCES
;
597 Status
= HexStringToBuf (Buf
, &Length
, Str
, NULL
);
598 if (EFI_ERROR (Status
)) {
603 Status
= EFI_SUCCESS
;
612 This function allows a caller to extract the current configuration
613 for one or more named elements from one or more drivers.
615 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
617 @param Request A null-terminated Unicode string in
618 <MultiConfigRequest> format.
619 @param Progress On return, points to a character in the Request
620 string. Points to the string's null terminator if
621 request was successful. Points to the most recent
622 & before the first failing name / value pair (or
623 the beginning of the string if the failure is in
624 the first name / value pair) if the request was
626 @param Results Null-terminated Unicode string in
627 <MultiConfigAltResp> format which has all values
628 filled in for the names in the Request string.
629 String to be allocated by the called function.
631 @retval EFI_SUCCESS The Results string is filled with the values
632 corresponding to all requested names.
633 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
634 results that must be stored awaiting possible
636 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
637 Progress set to the "G" in "GUID" of the routing
638 header that doesn't match. Note: There is no
639 requirement that all routing data be validated
640 before any configuration extraction.
641 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
642 parameter would result in this type of error. The
643 Progress parameter is set to NULL.
644 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
645 before the error or the beginning of the string.
646 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
652 HiiConfigRoutingExtractConfig (
653 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
654 IN CONST EFI_STRING Request
,
655 OUT EFI_STRING
*Progress
,
656 OUT EFI_STRING
*Results
659 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
661 HII_DATABASE_PRIVATE_DATA
*Private
;
662 EFI_STRING StringPtr
;
663 EFI_STRING ConfigRequest
;
665 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
668 HII_DATABASE_RECORD
*Database
;
669 UINT8
*CurrentDevicePath
;
670 EFI_HANDLE DriverHandle
;
671 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
672 EFI_STRING AccessProgress
;
673 EFI_STRING AccessResults
;
677 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
678 return EFI_INVALID_PARAMETER
;
681 if (Request
== NULL
) {
683 return EFI_INVALID_PARAMETER
;
686 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
688 *Progress
= StringPtr
;
691 // The first element of <MultiConfigRequest> should be
692 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
694 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
695 return EFI_INVALID_PARAMETER
;
699 // Allocate a fix length of memory to store Results. Reallocate memory for
700 // Results if this fix length is insufficient.
702 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
703 if (*Results
== NULL
) {
704 return EFI_OUT_OF_RESOURCES
;
707 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
709 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
710 // or most recent & before the error.
712 if (StringPtr
== Request
) {
713 *Progress
= StringPtr
;
715 *Progress
= StringPtr
- 1;
719 // Process each <ConfigRequest> of <MultiConfigRequest>
721 Length
= CalculateConfigStringLen (StringPtr
);
722 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
723 if (ConfigRequest
== NULL
) {
724 return EFI_OUT_OF_RESOURCES
;
726 *(ConfigRequest
+ Length
) = 0;
729 // Get the UEFI device path
731 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
732 if (EFI_ERROR (Status
)) {
733 SafeFreePool (ConfigRequest
);
738 // Find driver which matches the routing data.
741 for (Link
= Private
->DatabaseList
.ForwardLink
;
742 Link
!= &Private
->DatabaseList
;
743 Link
= Link
->ForwardLink
745 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
746 CurrentDevicePath
= Database
->PackageList
->DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
747 if (CurrentDevicePath
!= NULL
) {
751 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
753 DriverHandle
= Database
->DriverHandle
;
759 SafeFreePool (DevicePath
);
761 if (DriverHandle
== NULL
) {
763 // Routing data does not match any known driver.
764 // Set Progress to the 'G' in "GUID" of the routing header.
766 *Progress
= StringPtr
;
767 SafeFreePool (ConfigRequest
);
768 return EFI_NOT_FOUND
;
772 // Call corresponding ConfigAccess protocol to extract settings
774 Status
= gBS
->HandleProtocol (
776 &gEfiHiiConfigAccessProtocolGuid
,
777 (VOID
**) &ConfigAccess
779 ASSERT_EFI_ERROR (Status
);
781 Status
= ConfigAccess
->ExtractConfig (
787 if (EFI_ERROR (Status
)) {
789 // AccessProgress indicates the parsing progress on <ConfigRequest>.
790 // Map it to the progress on <MultiConfigRequest> then return it.
792 RemainSize
= StrSize (AccessProgress
);
793 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
796 SafeFreePool (ConfigRequest
);
801 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
803 ASSERT (*AccessProgress
== 0);
804 Status
= AppendToMultiString (Results
, AccessResults
);
805 ASSERT_EFI_ERROR (Status
);
806 SafeFreePool (AccessResults
);
807 AccessResults
= NULL
;
808 SafeFreePool (ConfigRequest
);
809 ConfigRequest
= NULL
;
812 // Go to next <ConfigRequest> (skip '&').
815 if (*StringPtr
== 0) {
816 *Progress
= StringPtr
;
826 return EFI_UNSUPPORTED
;
833 This function allows the caller to request the current configuration for the
834 entirety of the current HII database and returns the data in a
835 null-terminated Unicode string.
837 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
839 @param Results Null-terminated Unicode string in
840 <MultiConfigAltResp> format which has all values
841 filled in for the names in the Request string.
842 String to be allocated by the called function.
843 De-allocation is up to the caller.
845 @retval EFI_SUCCESS The Results string is filled with the values
846 corresponding to all requested names.
847 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
848 results that must be stored awaiting possible
850 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
851 parameter would result in this type of error.
856 HiiConfigRoutingExportConfig (
857 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
858 OUT EFI_STRING
*Results
861 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
864 HII_DATABASE_PRIVATE_DATA
*Private
;
865 LIST_ENTRY StorageListHdr
;
866 HII_FORMSET_STORAGE
*Storage
;
868 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
872 EFI_STRING ConfigRequest
;
874 EFI_STRING StringPtr
;
875 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
876 EFI_STRING AccessProgress
;
877 EFI_STRING AccessResults
;
880 if (This
== NULL
|| Results
== NULL
) {
881 return EFI_INVALID_PARAMETER
;
884 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
886 InitializeListHead (&StorageListHdr
);
888 Status
= ExportAllStorage (&Private
->HiiDatabase
, &StorageListHdr
);
889 if (EFI_ERROR (Status
)) {
894 // Allocate a fix length of memory to store Results. Reallocate memory for
895 // Results if this fix length is insufficient.
897 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
898 if (*Results
== NULL
) {
899 return EFI_OUT_OF_RESOURCES
;
903 // Parsing all formset storages.
905 for (Link
= StorageListHdr
.ForwardLink
; Link
!= &StorageListHdr
; Link
= Link
->ForwardLink
) {
906 Storage
= CR (Link
, HII_FORMSET_STORAGE
, Entry
, HII_FORMSET_STORAGE_SIGNATURE
);
908 // Find the corresponding device path instance
910 Status
= gBS
->HandleProtocol (
911 Storage
->DriverHandle
,
912 &gEfiDevicePathProtocolGuid
,
913 (VOID
**) &DevicePath
915 if (EFI_ERROR (Status
)) {
919 // Convert the device path binary to hex UNICODE %02x bytes in the same order
920 // as the device path resides in RAM memory.
922 Length
= GetDevicePathSize (DevicePath
);
923 PathHdrSize
= (Length
* 2 + 1) * sizeof (CHAR16
);
924 PathHdr
= (EFI_STRING
) AllocateZeroPool (PathHdrSize
);
925 if (PathHdr
== NULL
) {
926 return EFI_OUT_OF_RESOURCES
;
928 Status
= BufferToHexString (PathHdr
, (UINT8
*) DevicePath
, Length
);
929 ASSERT_EFI_ERROR (Status
);
932 // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.
933 // It means extract all possible configurations from this specific driver.
935 TmpSize
= StrLen (L
"GUID=&NAME=&PATH=");
936 RequestSize
= (TmpSize
+ 32 + StrLen (Storage
->Name
) * 4)
937 * sizeof (CHAR16
) + PathHdrSize
;
938 ConfigRequest
= (EFI_STRING
) AllocateZeroPool (RequestSize
);
939 if (ConfigRequest
== NULL
) {
940 SafeFreePool (PathHdr
);
941 return EFI_OUT_OF_RESOURCES
;
946 // <GuidHdr> ::= 'GUID='<Guid>
947 // Convert <Guid> in the same order as it resides in RAM memory.
949 StringPtr
= ConfigRequest
;
950 StrnCpy (StringPtr
, L
"GUID=", StrLen (L
"GUID="));
951 StringPtr
+= StrLen (L
"GUID=");
953 Status
= BufferToHexString (StringPtr
, (UINT8
*) (&Storage
->Guid
), sizeof (EFI_GUID
));
954 ASSERT_EFI_ERROR (Status
);
957 ASSERT (*StringPtr
== 0);
963 // <NameHdr> ::= 'NAME='<String>
965 StrnCpy (StringPtr
, L
"NAME=", StrLen (L
"NAME="));
966 StringPtr
+= StrLen (L
"NAME=");
968 Length
= (StrLen (Storage
->Name
) * 4 + 1) * sizeof (CHAR16
);
969 Status
= UnicodeToConfigString (StringPtr
, &Length
, Storage
->Name
);
970 ASSERT_EFI_ERROR (Status
);
971 StringPtr
+= StrLen (Storage
->Name
) * 4;
978 // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>
980 StrnCpy (StringPtr
, L
"PATH=", StrLen (L
"PATH="));
981 StringPtr
+= StrLen (L
"PATH=");
982 StrCpy (StringPtr
, PathHdr
);
984 SafeFreePool (PathHdr
);
988 // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the
989 // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>
990 // is required to call ConfigAccess.ExtractConfig().
992 // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess
993 // to handle such kind of "ConfigRequest". It is not supported till now.
995 // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()
996 // will be updated as soon as the decision is made.
999 // Route the request to corresponding ConfigAccess protocol to extract settings.
1001 Status
= gBS
->HandleProtocol (
1002 Storage
->DriverHandle
,
1003 &gEfiHiiConfigAccessProtocolGuid
,
1004 (VOID
**) &ConfigAccess
1006 ASSERT_EFI_ERROR (Status
);
1008 Status
= ConfigAccess
->ExtractConfig (
1014 if (EFI_ERROR (Status
)) {
1015 SafeFreePool (ConfigRequest
);
1016 SafeFreePool (AccessResults
);
1017 return EFI_INVALID_PARAMETER
;
1021 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
1023 ASSERT (*AccessProgress
== 0);
1024 Status
= AppendToMultiString (Results
, AccessResults
);
1025 ASSERT_EFI_ERROR (Status
);
1026 SafeFreePool (AccessResults
);
1027 AccessResults
= NULL
;
1028 SafeFreePool (ConfigRequest
);
1029 ConfigRequest
= NULL
;
1034 // Free the exported storage resource
1036 while (!IsListEmpty (&StorageListHdr
)) {
1038 StorageListHdr
.ForwardLink
,
1039 HII_FORMSET_STORAGE
,
1041 HII_FORMSET_STORAGE_SIGNATURE
1043 RemoveEntryList (&Storage
->Entry
);
1044 SafeFreePool (Storage
->Name
);
1045 SafeFreePool (Storage
);
1050 return EFI_UNSUPPORTED
;
1056 This function processes the results of processing forms and routes it to the
1057 appropriate handlers or storage.
1059 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1061 @param Configuration A null-terminated Unicode string in
1062 <MulltiConfigResp> format.
1063 @param Progress A pointer to a string filled in with the offset of
1064 the most recent & before the first failing name /
1065 value pair (or the beginning of the string if the
1066 failure is in the first name / value pair) or the
1067 terminating NULL if all was successful.
1069 @retval EFI_SUCCESS The results have been distributed or are awaiting
1071 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
1072 results that must be stored awaiting possible
1074 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
1075 would result in this type of error.
1076 @retval EFI_NOT_FOUND Target for the specified routing data was not
1082 HiiConfigRoutingRouteConfig (
1083 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1084 IN CONST EFI_STRING Configuration
,
1085 OUT EFI_STRING
*Progress
1088 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
1090 HII_DATABASE_PRIVATE_DATA
*Private
;
1091 EFI_STRING StringPtr
;
1092 EFI_STRING ConfigResp
;
1095 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1097 HII_DATABASE_RECORD
*Database
;
1098 UINT8
*CurrentDevicePath
;
1099 EFI_HANDLE DriverHandle
;
1100 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1101 EFI_STRING AccessProgress
;
1105 if (This
== NULL
|| Progress
== NULL
) {
1106 return EFI_INVALID_PARAMETER
;
1109 if (Configuration
== NULL
) {
1111 return EFI_INVALID_PARAMETER
;
1114 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1115 StringPtr
= Configuration
;
1116 *Progress
= StringPtr
;
1119 // The first element of <MultiConfigResp> should be
1120 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
1122 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1123 return EFI_INVALID_PARAMETER
;
1126 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
1128 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
1129 // or most recent & before the error.
1131 if (StringPtr
== Configuration
) {
1132 *Progress
= StringPtr
;
1134 *Progress
= StringPtr
- 1;
1138 // Process each <ConfigResp> of <MultiConfigResp>
1140 Length
= CalculateConfigStringLen (StringPtr
);
1141 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
1142 if (ConfigResp
== NULL
) {
1143 return EFI_OUT_OF_RESOURCES
;
1146 // Append '\0' to the end of ConfigRequest
1148 *(ConfigResp
+ Length
) = 0;
1151 // Get the UEFI device path
1153 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
1154 if (EFI_ERROR (Status
)) {
1155 SafeFreePool (ConfigResp
);
1160 // Find driver which matches the routing data.
1162 DriverHandle
= NULL
;
1163 for (Link
= Private
->DatabaseList
.ForwardLink
;
1164 Link
!= &Private
->DatabaseList
;
1165 Link
= Link
->ForwardLink
1167 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
1168 CurrentDevicePath
= Database
->PackageList
->DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
1169 if (CurrentDevicePath
!= NULL
) {
1173 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
1175 DriverHandle
= Database
->DriverHandle
;
1181 SafeFreePool (DevicePath
);
1183 if (DriverHandle
== NULL
) {
1185 // Routing data does not match any known driver.
1186 // Set Progress to the 'G' in "GUID" of the routing header.
1188 *Progress
= StringPtr
;
1189 SafeFreePool (ConfigResp
);
1190 return EFI_NOT_FOUND
;
1194 // Call corresponding ConfigAccess protocol to route settings
1196 Status
= gBS
->HandleProtocol (
1198 &gEfiHiiConfigAccessProtocolGuid
,
1199 (VOID
**) &ConfigAccess
1201 ASSERT_EFI_ERROR (Status
);
1203 Status
= ConfigAccess
->RouteConfig (
1209 if (EFI_ERROR (Status
)) {
1211 // AccessProgress indicates the parsing progress on <ConfigResp>.
1212 // Map it to the progress on <MultiConfigResp> then return it.
1214 RemainSize
= StrSize (AccessProgress
);
1215 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
1218 SafeFreePool (ConfigResp
);
1222 SafeFreePool (ConfigResp
);
1226 // Go to next <ConfigResp> (skip '&').
1228 StringPtr
+= Length
;
1229 if (*StringPtr
== 0) {
1230 *Progress
= StringPtr
;
1240 return EFI_UNSUPPORTED
;
1246 This helper function is to be called by drivers to map configuration data
1247 stored in byte array ("block") formats such as UEFI Variables into current
1248 configuration strings.
1250 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1252 @param ConfigRequest A null-terminated Unicode string in
1253 <ConfigRequest> format.
1254 @param Block Array of bytes defining the block's configuration.
1255 @param BlockSize Length in bytes of Block.
1256 @param Config Filled-in configuration string. String allocated
1257 by the function. Returned only if call is
1259 @param Progress A pointer to a string filled in with the offset of
1260 the most recent & before the first failing
1261 name/value pair (or the beginning of the string if
1262 the failure is in the first name / value pair) or
1263 the terminating NULL if all was successful.
1265 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1266 terminator at the end of the ConfigRequest
1268 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1269 points to the first character of ConfigRequest.
1270 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
1271 Block parameter would result in this type of
1272 error. Progress points to the first character of
1274 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
1275 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
1276 Block is left updated and Progress points at
1277 the "&" preceding the first non-<BlockName>.
1283 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1284 IN CONST EFI_STRING ConfigRequest
,
1285 IN CONST UINT8
*Block
,
1286 IN CONST UINTN BlockSize
,
1287 OUT EFI_STRING
*Config
,
1288 OUT EFI_STRING
*Progress
1291 HII_DATABASE_PRIVATE_DATA
*Private
;
1292 EFI_STRING StringPtr
;
1300 EFI_STRING ValueStr
;
1301 EFI_STRING ConfigElement
;
1303 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
1304 return EFI_INVALID_PARAMETER
;
1307 if (Block
== NULL
|| ConfigRequest
== NULL
) {
1308 *Progress
= ConfigRequest
;
1309 return EFI_INVALID_PARAMETER
;
1313 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1314 ASSERT (Private
!= NULL
);
1316 StringPtr
= ConfigRequest
;
1319 ConfigElement
= NULL
;
1322 // Allocate a fix length of memory to store Results. Reallocate memory for
1323 // Results if this fix length is insufficient.
1325 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
1326 if (*Config
== NULL
) {
1327 return EFI_OUT_OF_RESOURCES
;
1333 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1334 *Progress
= StringPtr
;
1335 Status
= EFI_INVALID_PARAMETER
;
1338 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1341 if (*StringPtr
== 0) {
1342 *Progress
= StringPtr
;
1343 Status
= EFI_INVALID_PARAMETER
;
1346 while (*StringPtr
++ != L
'&');
1349 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
1351 Length
= StringPtr
- ConfigRequest
;
1352 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
1355 // Parse each <RequestElement> if exists
1356 // Only <BlockName> format is supported by this help function.
1357 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
1359 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1361 // Back up the header of one <BlockName>
1365 StringPtr
+= StrLen (L
"OFFSET=");
1369 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1370 if (Status
== EFI_OUT_OF_RESOURCES
) {
1371 *Progress
= ConfigRequest
;
1378 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1380 SafeFreePool (TmpBuffer
);
1382 StringPtr
+= Length
;
1383 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1384 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1385 Status
= EFI_INVALID_PARAMETER
;
1388 StringPtr
+= StrLen (L
"&WIDTH=");
1393 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1394 if (Status
== EFI_OUT_OF_RESOURCES
) {
1395 *Progress
= ConfigRequest
;
1402 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1404 SafeFreePool (TmpBuffer
);
1406 StringPtr
+= Length
;
1407 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1408 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1409 Status
= EFI_INVALID_PARAMETER
;
1414 // Calculate Value and convert it to hex string.
1416 if (Offset
+ Width
> BlockSize
) {
1417 *Progress
= StringPtr
;
1418 Status
= EFI_DEVICE_ERROR
;
1422 Value
= (UINT8
*) AllocateZeroPool (Width
);
1423 if (Value
== NULL
) {
1424 *Progress
= ConfigRequest
;
1425 Status
= EFI_OUT_OF_RESOURCES
;
1429 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
1431 Length
= Width
* 2 + 1;
1432 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1433 if (ValueStr
== NULL
) {
1434 *Progress
= ConfigRequest
;
1435 Status
= EFI_OUT_OF_RESOURCES
;
1439 Status
= BufToHexString (ValueStr
, &Length
, Value
, Width
);
1440 ASSERT_EFI_ERROR (Status
);
1443 SafeFreePool (Value
);
1447 // Build a ConfigElement
1449 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
1450 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1451 if (ConfigElement
== NULL
) {
1452 Status
= EFI_OUT_OF_RESOURCES
;
1455 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
1456 if (*StringPtr
== 0) {
1457 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
1459 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
1460 StrCat (ConfigElement
, L
"VALUE=");
1461 StrCat (ConfigElement
, ValueStr
);
1463 AppendToMultiString (Config
, ConfigElement
);
1465 SafeFreePool (ConfigElement
);
1466 SafeFreePool (ValueStr
);
1467 ConfigElement
= NULL
;
1471 // If '\0', parsing is finished. Otherwise skip '&' to continue
1473 if (*StringPtr
== 0) {
1476 AppendToMultiString (Config
, L
"&");
1481 if (*StringPtr
!= 0) {
1482 *Progress
= StringPtr
- 1;
1483 Status
= EFI_INVALID_PARAMETER
;
1487 *Progress
= StringPtr
;
1492 SafeFreePool (*Config
);
1493 SafeFreePool (ValueStr
);
1494 SafeFreePool (Value
);
1495 SafeFreePool (ConfigElement
);
1503 This helper function is to be called by drivers to map configuration strings
1504 to configurations stored in byte array ("block") formats such as UEFI Variables.
1506 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1508 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
1510 @param Block A possibly null array of bytes representing the
1511 current block. Only bytes referenced in the
1512 ConfigResp string in the block are modified. If
1513 this parameter is null or if the *BlockSize
1514 parameter is (on input) shorter than required by
1515 the Configuration string, only the BlockSize
1516 parameter is updated and an appropriate status
1517 (see below) is returned.
1518 @param BlockSize The length of the Block in units of UINT8. On
1519 input, this is the size of the Block. On output,
1520 if successful, contains the index of the last
1521 modified byte in the Block.
1522 @param Progress On return, points to an element of the ConfigResp
1523 string filled in with the offset of the most
1524 recent '&' before the first failing name / value
1525 pair (or the beginning of the string if the
1526 failure is in the first name / value pair) or the
1527 terminating NULL if all was successful.
1529 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1530 terminator at the end of the ConfigResp string.
1531 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1532 points to the first character of ConfigResp.
1533 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
1534 Block parameter would result in this type of
1535 error. Progress points to the first character of
1537 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
1538 value pair. Block is left updated and
1539 Progress points at the '&' preceding the first
1546 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1547 IN CONST EFI_STRING ConfigResp
,
1548 IN OUT UINT8
*Block
,
1549 IN OUT UINTN
*BlockSize
,
1550 OUT EFI_STRING
*Progress
1553 HII_DATABASE_PRIVATE_DATA
*Private
;
1554 EFI_STRING StringPtr
;
1563 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
1564 return EFI_INVALID_PARAMETER
;
1567 if (ConfigResp
== NULL
|| Block
== NULL
) {
1568 *Progress
= ConfigResp
;
1569 return EFI_INVALID_PARAMETER
;
1572 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1573 ASSERT (Private
!= NULL
);
1575 StringPtr
= ConfigResp
;
1576 BufferSize
= *BlockSize
;
1582 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1583 *Progress
= StringPtr
;
1584 Status
= EFI_INVALID_PARAMETER
;
1587 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1590 if (*StringPtr
== 0) {
1591 *Progress
= StringPtr
;
1592 Status
= EFI_INVALID_PARAMETER
;
1595 while (*StringPtr
++ != L
'&');
1598 // Parse each <ConfigElement> if exists
1599 // Only <BlockConfig> format is supported by this help function.
1600 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
1602 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1603 StringPtr
+= StrLen (L
"OFFSET=");
1607 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1608 if (Status
== EFI_OUT_OF_RESOURCES
) {
1609 *Progress
= ConfigResp
;
1616 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1618 SafeFreePool (TmpBuffer
);
1620 StringPtr
+= Length
;
1621 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1622 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1623 Status
= EFI_INVALID_PARAMETER
;
1626 StringPtr
+= StrLen (L
"&WIDTH=");
1631 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1632 if (Status
== EFI_OUT_OF_RESOURCES
) {
1633 *Progress
= ConfigResp
;
1640 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1642 SafeFreePool (TmpBuffer
);
1644 StringPtr
+= Length
;
1645 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1646 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1647 Status
= EFI_INVALID_PARAMETER
;
1650 StringPtr
+= StrLen (L
"&VALUE=");
1655 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
1656 if (Status
== EFI_OUT_OF_RESOURCES
) {
1657 *Progress
= ConfigResp
;
1661 StringPtr
+= Length
;
1662 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1663 *Progress
= StringPtr
- Length
- 7;
1664 Status
= EFI_INVALID_PARAMETER
;
1669 // Update the Block with configuration info
1672 if (Offset
+ Width
> BufferSize
) {
1673 return EFI_DEVICE_ERROR
;
1676 CopyMem (Block
+ Offset
, Value
, Width
);
1677 *BlockSize
= Offset
+ Width
- 1;
1679 SafeFreePool (Value
);
1683 // If '\0', parsing is finished. Otherwise skip '&' to continue
1685 if (*StringPtr
== 0) {
1692 if (*StringPtr
!= 0) {
1693 *Progress
= StringPtr
- 1;
1694 Status
= EFI_INVALID_PARAMETER
;
1698 *Progress
= StringPtr
;
1703 SafeFreePool (Value
);
1709 This helper function is to be called by drivers to extract portions of
1710 a larger configuration string.
1712 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1714 @param Configuration A null-terminated Unicode string in
1715 <MultiConfigAltResp> format.
1716 @param Guid A pointer to the GUID value to search for in the
1717 routing portion of the ConfigResp string when
1718 retrieving the requested data. If Guid is NULL,
1719 then all GUID values will be searched for.
1720 @param Name A pointer to the NAME value to search for in the
1721 routing portion of the ConfigResp string when
1722 retrieving the requested data. If Name is NULL,
1723 then all Name values will be searched for.
1724 @param DevicePath A pointer to the PATH value to search for in the
1725 routing portion of the ConfigResp string when
1726 retrieving the requested data. If DevicePath is
1727 NULL, then all DevicePath values will be searched
1729 @param AltCfgId A pointer to the ALTCFG value to search for in the
1730 routing portion of the ConfigResp string when
1731 retrieving the requested data. If this parameter
1732 is NULL, then the current setting will be
1734 @param AltCfgResp A pointer to a buffer which will be allocated by
1735 the function which contains the retrieved string
1736 as requested. This buffer is only allocated if
1737 the call was successful.
1739 @retval EFI_SUCCESS The request succeeded. The requested data was
1740 extracted and placed in the newly allocated
1742 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
1743 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1744 @retval EFI_NOT_FOUND Target for the specified routing data was not
1751 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1752 IN CONST EFI_STRING Configuration
,
1753 IN CONST EFI_GUID
*Guid
,
1754 IN CONST EFI_STRING Name
,
1755 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1756 IN CONST UINT16
*AltCfgId
,
1757 OUT EFI_STRING
*AltCfgResp
1760 #ifndef DISABLE_UNUSED_HII_PROTOCOLS
1763 EFI_STRING StringPtr
;
1764 EFI_STRING HdrStart
= NULL
;
1765 EFI_STRING HdrEnd
= NULL
;
1768 EFI_STRING GuidStr
= NULL
;
1769 EFI_STRING NameStr
= NULL
;
1770 EFI_STRING PathStr
= NULL
;
1771 EFI_STRING AltIdStr
= NULL
;
1772 EFI_STRING Result
= NULL
;
1773 BOOLEAN GuidFlag
= FALSE
;
1774 BOOLEAN NameFlag
= FALSE
;
1775 BOOLEAN PathFlag
= FALSE
;
1777 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
1778 return EFI_INVALID_PARAMETER
;
1781 StringPtr
= Configuration
;
1782 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1783 return EFI_INVALID_PARAMETER
;
1787 // Generate the sub string for later matching.
1789 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
1792 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1793 (VOID
*) DevicePath
,
1797 if (AltCfgId
!= NULL
) {
1798 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
1801 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1803 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1806 while (*StringPtr
!= 0) {
1808 // Try to match the GUID
1811 TmpPtr
= StrStr (StringPtr
, GuidStr
);
1812 if (TmpPtr
== NULL
) {
1813 Status
= EFI_NOT_FOUND
;
1819 // Jump to <NameHdr>
1822 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
1824 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
1825 if (StringPtr
== NULL
) {
1826 Status
= EFI_NOT_FOUND
;
1834 // Try to match the NAME
1836 if (GuidFlag
&& !NameFlag
) {
1837 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
1841 // Jump to <PathHdr>
1844 StringPtr
+= StrLen (NameStr
);
1846 StringPtr
= StrStr (StringPtr
, L
"PATH=");
1847 if (StringPtr
== NULL
) {
1848 Status
= EFI_NOT_FOUND
;
1857 // Try to match the DevicePath
1859 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
1860 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
1865 // Jump to '&' before <DescHdr> or <ConfigBody>
1867 if (DevicePath
!= NULL
) {
1868 StringPtr
+= StrLen (PathStr
);
1870 StringPtr
= StrStr (StringPtr
, L
"&");
1871 if (StringPtr
== NULL
) {
1872 Status
= EFI_NOT_FOUND
;
1877 HdrEnd
= ++StringPtr
;
1882 // Try to match the AltCfgId
1884 if (GuidFlag
&& NameFlag
&& PathFlag
) {
1885 if (AltCfgId
== NULL
) {
1887 // Return Current Setting when AltCfgId is NULL.
1889 Status
= OutputConfigBody (StringPtr
, &Result
);
1893 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
1895 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
1900 Status
= OutputConfigBody (StringPtr
, &Result
);
1906 Status
= EFI_NOT_FOUND
;
1910 if (!EFI_ERROR (Status
)) {
1912 // Copy the <ConfigHdr> and <ConfigBody>
1914 Length
= HdrEnd
- HdrStart
+ StrLen (Result
);
1915 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1916 if (*AltCfgResp
== NULL
) {
1917 Status
= EFI_OUT_OF_RESOURCES
;
1919 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
1920 StrCat (*AltCfgResp
, Result
);
1921 Status
= EFI_SUCCESS
;
1925 SafeFreePool (GuidStr
);
1926 SafeFreePool (NameStr
);
1927 SafeFreePool (PathStr
);
1928 SafeFreePool (AltIdStr
);
1929 SafeFreePool (Result
);
1934 return EFI_UNSUPPORTED
;