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 This is a internal function.
36 @param String String in <MultiConfigRequest> or
37 <MultiConfigResp> format.
39 @return The number of Unicode characters.
43 CalculateConfigStringLen (
50 // "GUID=" should be the first element of incoming string.
52 ASSERT (String
!= NULL
);
53 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
55 Length
= StrLen (L
"GUID=");
59 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
60 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
62 while (*String
!= 0 && StrnCmp (String
, L
"&GUID=", StrLen (L
"&GUID=")) != 0) {
72 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
73 from <PathHdr> of <ConfigHdr>.
75 This is a internal function.
77 @param String UEFI configuration string
78 @param DevicePath binary of a UEFI device path.
80 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
81 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
82 @retval EFI_SUCCESS The device path is retrieved and translated to
89 OUT UINT8
**DevicePath
94 EFI_STRING DevicePathString
;
96 if (String
== NULL
|| DevicePath
== NULL
) {
97 return EFI_INVALID_PARAMETER
;
101 // Find the 'PATH=' of <PathHdr> and skip it.
103 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
105 return EFI_INVALID_PARAMETER
;
108 String
+= StrLen (L
"PATH=");
112 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
113 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
114 // of UEFI device path.
116 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
117 DevicePathString
= (EFI_STRING
) AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
118 if (DevicePathString
== NULL
) {
119 return EFI_OUT_OF_RESOURCES
;
121 StrnCpy (DevicePathString
, PathHdr
, Length
);
122 *(DevicePathString
+ Length
) = 0;
125 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
126 // as the device path resides in RAM memory.
127 // Translate the data into binary.
130 *DevicePath
= (UINT8
*) AllocateZeroPool (Length
);
131 if (*DevicePath
== NULL
) {
132 SafeFreePool (DevicePathString
);
133 return EFI_OUT_OF_RESOURCES
;
136 HexStringToBuffer (*DevicePath
, &Length
, DevicePathString
);
138 SafeFreePool (DevicePathString
);
146 Extract Storage from all Form Packages in current hii database.
148 This is a internal function.
150 @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.
151 @param StorageListHead Storage link List head.
153 @retval EFI_NOT_FOUND There is no form package in current hii database.
154 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
155 @retval EFI_SUCCESS All existing storage is exported.
160 IN EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
,
161 IN OUT LIST_ENTRY
*StorageListHead
167 EFI_HII_HANDLE
*HandleBuffer
;
170 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
171 EFI_HII_PACKAGE_HEADER
*Package
;
175 HII_FORMSET_STORAGE
*Storage
;
176 EFI_HII_HANDLE HiiHandle
;
177 EFI_HANDLE DriverHandle
;
179 UINT32 PackageListLength
;
180 EFI_HII_PACKAGE_HEADER PackageHeader
;
183 // Find the package list which contains Form package.
187 Status
= HiiListPackageLists (
189 EFI_HII_PACKAGE_FORM
,
194 if (Status
== EFI_BUFFER_TOO_SMALL
) {
195 HandleBuffer
= AllocateZeroPool (BufferSize
);
196 ASSERT (HandleBuffer
!= NULL
);
198 Status
= HiiListPackageLists (
200 EFI_HII_PACKAGE_FORM
,
206 if (EFI_ERROR (Status
)) {
207 SafeFreePool (HandleBuffer
);
211 HandleCount
= BufferSize
/ sizeof (EFI_HII_HANDLE
);
212 for (Index
= 0; Index
< HandleCount
; Index
++) {
213 HiiHandle
= HandleBuffer
[Index
];
216 HiiPackageList
= NULL
;
217 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
218 if (Status
== EFI_BUFFER_TOO_SMALL
) {
219 HiiPackageList
= AllocateZeroPool (BufferSize
);
220 ASSERT (HiiPackageList
!= NULL
);
221 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
223 if (EFI_ERROR (Status
)) {
224 SafeFreePool (HandleBuffer
);
225 SafeFreePool (HiiPackageList
);
230 // Get Form package from this HII package List
232 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
233 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
235 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
237 while (Offset
< PackageListLength
) {
238 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
239 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
240 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
243 Offset
+= PackageHeader
.Length
;
245 if (Offset
>= PackageListLength
) {
247 // Error here: No Form package found in this Package List
253 // Search Storage definition in this Form package
255 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
256 while (Offset
< PackageHeader
.Length
) {
257 OpCodeData
= ((UINT8
*) Package
) + Offset
;
258 Offset
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
260 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
262 if ((Operand
== EFI_IFR_VARSTORE_OP
) ||
263 (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) ||
264 (Operand
== EFI_IFR_VARSTORE_EFI_OP
)) {
266 Storage
= AllocateZeroPool (sizeof (HII_FORMSET_STORAGE
));
267 ASSERT (Storage
!= NULL
);
268 InsertTailList (StorageListHead
, &Storage
->Entry
);
270 Storage
->Signature
= HII_FORMSET_STORAGE_SIGNATURE
;
271 Storage
->HiiHandle
= HiiHandle
;
273 Status
= HiiGetPackageListHandle (HiiDatabase
, HiiHandle
, &DriverHandle
);
274 if (EFI_ERROR (Status
)) {
275 SafeFreePool (HandleBuffer
);
276 SafeFreePool (HiiPackageList
);
277 SafeFreePool (Storage
);
280 Storage
->DriverHandle
= DriverHandle
;
282 if (Operand
== EFI_IFR_VARSTORE_OP
) {
283 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
285 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
286 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
288 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
289 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
290 ASSERT (Storage
->Name
!= NULL
);
291 for (Index2
= 0; AsciiString
[Index2
] != 0; Index2
++) {
292 Storage
->Name
[Index2
] = (CHAR16
) AsciiString
[Index2
];
295 // Append '\0' to the end of the unicode string.
297 Storage
->Name
[Index2
] = 0;
298 } else if (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
299 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
301 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
302 } else if (Operand
== EFI_IFR_VARSTORE_EFI_OP
) {
303 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
305 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
310 SafeFreePool (HiiPackageList
);
313 SafeFreePool (HandleBuffer
);
320 Generate a sub string then output it.
322 This is a internal function.
324 @param String A constant string which is the prefix of the to be
325 generated string, e.g. GUID=
326 @param BufferLen The length of the Buffer in bytes.
327 @param Buffer Points to a buffer which will be converted to be the
328 content of the generated string.
329 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
330 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
331 if 3, the buffer contains other data.
332 @param SubStr Points to the output string. It's caller's
333 responsibility to free this buffer.
339 IN CONST EFI_STRING String
,
343 OUT EFI_STRING
*SubStr
349 EFI_STRING StringHeader
;
351 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
353 if (Buffer
== NULL
) {
354 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
355 ASSERT (*SubStr
!= NULL
);
359 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
360 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
361 ASSERT (Str
!= NULL
);
363 StrCpy (Str
, String
);
364 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
366 Status
= EFI_SUCCESS
;
367 StringHeader
= Str
+ StrLen (String
);
371 Status
= BufferToHexString (StringHeader
, (UINT8
*) Buffer
, BufferLen
);
374 Status
= UnicodeToConfigString (StringHeader
, &Length
, (CHAR16
*) Buffer
);
377 Status
= BufToHexString (StringHeader
, &Length
, (UINT8
*) Buffer
, BufferLen
);
379 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
381 ToLower (StringHeader
);
387 ASSERT_EFI_ERROR (Status
);
395 Retrieve the <ConfigBody> from String then output it.
397 This is a internal function.
399 @param String A sub string of a configuration string in
400 <MultiConfigAltResp> format.
401 @param ConfigBody Points to the output string. It's caller's
402 responsibility to free this buffer.
404 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
405 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
406 @retval EFI_SUCCESS All existing storage is exported.
411 IN EFI_STRING String
,
412 OUT EFI_STRING
*ConfigBody
419 if (String
== NULL
|| ConfigBody
== NULL
) {
420 return EFI_INVALID_PARAMETER
;
423 TmpPtr
= StrStr (String
, L
"GUID=");
424 if (TmpPtr
== NULL
) {
426 // It is the last <ConfigResp> of the incoming configuration string.
428 Result
= AllocateCopyPool (StrSize (String
), String
);
429 if (Result
== NULL
) {
430 return EFI_OUT_OF_RESOURCES
;
432 *ConfigBody
= Result
;
437 Length
= TmpPtr
- String
;
438 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
439 if (Result
== NULL
) {
440 return EFI_OUT_OF_RESOURCES
;
443 *(Result
+ Length
- 1) = 0;
444 *ConfigBody
= Result
;
453 Adjusts the size of a previously allocated buffer.
456 @param OldPool A pointer to the buffer whose size is being adjusted.
457 @param OldSize The size of the current buffer.
458 @param NewSize The size of the new buffer.
460 @return The new buffer allocated.
474 NewPool
= AllocateZeroPool (NewSize
);
477 if (OldPool
!= NULL
) {
478 if (NewPool
!= NULL
) {
479 CopyMem (NewPool
, OldPool
, OldSize
< NewSize
? OldSize
: NewSize
);
482 gBS
->FreePool (OldPool
);
490 Append a string to a multi-string format.
492 This is a internal function.
494 @param MultiString String in <MultiConfigRequest>,
495 <MultiConfigAltResp>, or <MultiConfigResp>. On
496 input, the buffer length of this string is
497 MAX_STRING_LENGTH. On output, the buffer length
499 @param AppendString NULL-terminated Unicode string.
501 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
502 @retval EFI_SUCCESS AppendString is append to the end of MultiString
506 AppendToMultiString (
507 IN OUT EFI_STRING
*MultiString
,
508 IN EFI_STRING AppendString
511 UINTN AppendStringSize
;
512 UINTN MultiStringSize
;
514 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
515 return EFI_INVALID_PARAMETER
;
518 AppendStringSize
= StrSize (AppendString
);
519 MultiStringSize
= StrSize (*MultiString
);
522 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
524 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
525 MultiStringSize
> MAX_STRING_LENGTH
) {
526 *MultiString
= (EFI_STRING
) ReallocatePool (
527 (VOID
*) (*MultiString
),
529 MultiStringSize
+ AppendStringSize
534 // Append the incoming string
536 StrCat (*MultiString
, AppendString
);
543 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
545 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
547 This is a internal function.
549 @param StringPtr String in <BlockConfig> format and points to the
550 first character of <Number>.
551 @param Number The output value. Caller takes the responsibility
553 @param Len Length of the <Number>, in characters.
555 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
557 @retval EFI_SUCCESS Value of <Number> is outputted in Number
563 IN EFI_STRING StringPtr
,
574 ASSERT (StringPtr
!= NULL
&& Number
!= NULL
&& Len
!= NULL
);
575 ASSERT (*StringPtr
!= 0);
580 while (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
583 *Len
= StringPtr
- TmpPtr
;
586 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (EFI_STRING
));
588 Status
= EFI_OUT_OF_RESOURCES
;
591 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
594 Length
= (Length
+ 1) / 2;
595 Buf
= (UINT8
*) AllocateZeroPool (Length
);
597 Status
= EFI_OUT_OF_RESOURCES
;
601 Status
= HexStringToBuf (Buf
, &Length
, Str
, NULL
);
602 if (EFI_ERROR (Status
)) {
607 Status
= EFI_SUCCESS
;
616 This function allows a caller to extract the current configuration
617 for one or more named elements from one or more drivers.
619 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
621 @param Request A null-terminated Unicode string in
622 <MultiConfigRequest> format.
623 @param Progress On return, points to a character in the Request
624 string. Points to the string's null terminator if
625 request was successful. Points to the most recent
626 & before the first failing name / value pair (or
627 the beginning of the string if the failure is in
628 the first name / value pair) if the request was
630 @param Results Null-terminated Unicode string in
631 <MultiConfigAltResp> format which has all values
632 filled in for the names in the Request string.
633 String to be allocated by the called function.
635 @retval EFI_SUCCESS The Results string is filled with the values
636 corresponding to all requested names.
637 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
638 results that must be stored awaiting possible
640 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
641 Progress set to the "G" in "GUID" of the routing
642 header that doesn't match. Note: There is no
643 requirement that all routing data be validated
644 before any configuration extraction.
645 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
646 parameter would result in this type of error. The
647 Progress parameter is set to NULL.
648 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
649 before the error or the beginning of the string.
650 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
656 HiiConfigRoutingExtractConfig (
657 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
658 IN CONST EFI_STRING Request
,
659 OUT EFI_STRING
*Progress
,
660 OUT EFI_STRING
*Results
663 #ifndef _DISABLE_UNUSED_HII_PROTOCOLS_
665 HII_DATABASE_PRIVATE_DATA
*Private
;
666 EFI_STRING StringPtr
;
667 EFI_STRING ConfigRequest
;
669 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
672 HII_DATABASE_RECORD
*Database
;
673 UINT8
*CurrentDevicePath
;
674 EFI_HANDLE DriverHandle
;
675 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
676 EFI_STRING AccessProgress
;
677 EFI_STRING AccessResults
;
681 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
682 return EFI_INVALID_PARAMETER
;
685 if (Request
== NULL
) {
687 return EFI_INVALID_PARAMETER
;
690 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
692 *Progress
= StringPtr
;
695 // The first element of <MultiConfigRequest> should be
696 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
698 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
699 return EFI_INVALID_PARAMETER
;
703 // Allocate a fix length of memory to store Results. Reallocate memory for
704 // Results if this fix length is insufficient.
706 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
707 if (*Results
== NULL
) {
708 return EFI_OUT_OF_RESOURCES
;
711 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
713 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
714 // or most recent & before the error.
716 if (StringPtr
== Request
) {
717 *Progress
= StringPtr
;
719 *Progress
= StringPtr
- 1;
723 // Process each <ConfigRequest> of <MultiConfigRequest>
725 Length
= CalculateConfigStringLen (StringPtr
);
726 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
727 if (ConfigRequest
== NULL
) {
728 return EFI_OUT_OF_RESOURCES
;
730 *(ConfigRequest
+ Length
) = 0;
733 // Get the UEFI device path
735 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
736 if (EFI_ERROR (Status
)) {
737 SafeFreePool (ConfigRequest
);
742 // Find driver which matches the routing data.
745 for (Link
= Private
->DatabaseList
.ForwardLink
;
746 Link
!= &Private
->DatabaseList
;
747 Link
= Link
->ForwardLink
749 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
750 CurrentDevicePath
= Database
->PackageList
->DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
751 if (CurrentDevicePath
!= NULL
) {
755 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
757 DriverHandle
= Database
->DriverHandle
;
763 SafeFreePool (DevicePath
);
765 if (DriverHandle
== NULL
) {
767 // Routing data does not match any known driver.
768 // Set Progress to the 'G' in "GUID" of the routing header.
770 *Progress
= StringPtr
;
771 SafeFreePool (ConfigRequest
);
772 return EFI_NOT_FOUND
;
776 // Call corresponding ConfigAccess protocol to extract settings
778 Status
= gBS
->HandleProtocol (
780 &gEfiHiiConfigAccessProtocolGuid
,
781 (VOID
**) &ConfigAccess
783 ASSERT_EFI_ERROR (Status
);
785 Status
= ConfigAccess
->ExtractConfig (
791 if (EFI_ERROR (Status
)) {
793 // AccessProgress indicates the parsing progress on <ConfigRequest>.
794 // Map it to the progress on <MultiConfigRequest> then return it.
796 RemainSize
= StrSize (AccessProgress
);
797 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
800 SafeFreePool (ConfigRequest
);
805 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
807 ASSERT (*AccessProgress
== 0);
808 Status
= AppendToMultiString (Results
, AccessResults
);
809 ASSERT_EFI_ERROR (Status
);
810 SafeFreePool (AccessResults
);
811 AccessResults
= NULL
;
812 SafeFreePool (ConfigRequest
);
813 ConfigRequest
= NULL
;
816 // Go to next <ConfigRequest> (skip '&').
819 if (*StringPtr
== 0) {
820 *Progress
= StringPtr
;
830 return EFI_UNSUPPORTED
;
837 This function allows the caller to request the current configuration for the
838 entirety of the current HII database and returns the data in a
839 null-terminated Unicode string.
841 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
843 @param Results Null-terminated Unicode string in
844 <MultiConfigAltResp> format which has all values
845 filled in for the names in the Request string.
846 String to be allocated by the called function.
847 De-allocation is up to the caller.
849 @retval EFI_SUCCESS The Results string is filled with the values
850 corresponding to all requested names.
851 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
852 results that must be stored awaiting possible
854 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
855 parameter would result in this type of error.
860 HiiConfigRoutingExportConfig (
861 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
862 OUT EFI_STRING
*Results
865 #ifndef _DISABLE_UNUSED_HII_PROTOCOLS_
868 HII_DATABASE_PRIVATE_DATA
*Private
;
869 LIST_ENTRY StorageListHdr
;
870 HII_FORMSET_STORAGE
*Storage
;
872 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
876 EFI_STRING ConfigRequest
;
878 EFI_STRING StringPtr
;
879 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
880 EFI_STRING AccessProgress
;
881 EFI_STRING AccessResults
;
884 if (This
== NULL
|| Results
== NULL
) {
885 return EFI_INVALID_PARAMETER
;
888 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
890 InitializeListHead (&StorageListHdr
);
892 Status
= ExportAllStorage (&Private
->HiiDatabase
, &StorageListHdr
);
893 if (EFI_ERROR (Status
)) {
898 // Allocate a fix length of memory to store Results. Reallocate memory for
899 // Results if this fix length is insufficient.
901 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
902 if (*Results
== NULL
) {
903 return EFI_OUT_OF_RESOURCES
;
907 // Parsing all formset storages.
909 for (Link
= StorageListHdr
.ForwardLink
; Link
!= &StorageListHdr
; Link
= Link
->ForwardLink
) {
910 Storage
= CR (Link
, HII_FORMSET_STORAGE
, Entry
, HII_FORMSET_STORAGE_SIGNATURE
);
912 // Find the corresponding device path instance
914 Status
= gBS
->HandleProtocol (
915 Storage
->DriverHandle
,
916 &gEfiDevicePathProtocolGuid
,
917 (VOID
**) &DevicePath
919 if (EFI_ERROR (Status
)) {
923 // Convert the device path binary to hex UNICODE %02x bytes in the same order
924 // as the device path resides in RAM memory.
926 Length
= GetDevicePathSize (DevicePath
);
927 PathHdrSize
= (Length
* 2 + 1) * sizeof (CHAR16
);
928 PathHdr
= (EFI_STRING
) AllocateZeroPool (PathHdrSize
);
929 if (PathHdr
== NULL
) {
930 return EFI_OUT_OF_RESOURCES
;
932 Status
= BufferToHexString (PathHdr
, (UINT8
*) DevicePath
, Length
);
933 ASSERT_EFI_ERROR (Status
);
936 // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.
937 // It means extract all possible configurations from this specific driver.
939 TmpSize
= StrLen (L
"GUID=&NAME=&PATH=");
940 RequestSize
= (TmpSize
+ 32 + StrLen (Storage
->Name
) * 4)
941 * sizeof (CHAR16
) + PathHdrSize
;
942 ConfigRequest
= (EFI_STRING
) AllocateZeroPool (RequestSize
);
943 if (ConfigRequest
== NULL
) {
944 SafeFreePool (PathHdr
);
945 return EFI_OUT_OF_RESOURCES
;
950 // <GuidHdr> ::= 'GUID='<Guid>
951 // Convert <Guid> in the same order as it resides in RAM memory.
953 StringPtr
= ConfigRequest
;
954 StrnCpy (StringPtr
, L
"GUID=", StrLen (L
"GUID="));
955 StringPtr
+= StrLen (L
"GUID=");
957 Status
= BufferToHexString (StringPtr
, (UINT8
*) (&Storage
->Guid
), sizeof (EFI_GUID
));
958 ASSERT_EFI_ERROR (Status
);
961 ASSERT (*StringPtr
== 0);
967 // <NameHdr> ::= 'NAME='<String>
969 StrnCpy (StringPtr
, L
"NAME=", StrLen (L
"NAME="));
970 StringPtr
+= StrLen (L
"NAME=");
972 Length
= (StrLen (Storage
->Name
) * 4 + 1) * sizeof (CHAR16
);
973 Status
= UnicodeToConfigString (StringPtr
, &Length
, Storage
->Name
);
974 ASSERT_EFI_ERROR (Status
);
975 StringPtr
+= StrLen (Storage
->Name
) * 4;
982 // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>
984 StrnCpy (StringPtr
, L
"PATH=", StrLen (L
"PATH="));
985 StringPtr
+= StrLen (L
"PATH=");
986 StrCpy (StringPtr
, PathHdr
);
988 SafeFreePool (PathHdr
);
992 // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the
993 // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>
994 // is required to call ConfigAccess.ExtractConfig().
996 // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess
997 // to handle such kind of "ConfigRequest". It is not supported till now.
999 // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()
1000 // will be updated as soon as the decision is made.
1003 // Route the request to corresponding ConfigAccess protocol to extract settings.
1005 Status
= gBS
->HandleProtocol (
1006 Storage
->DriverHandle
,
1007 &gEfiHiiConfigAccessProtocolGuid
,
1008 (VOID
**) &ConfigAccess
1010 ASSERT_EFI_ERROR (Status
);
1012 Status
= ConfigAccess
->ExtractConfig (
1018 if (EFI_ERROR (Status
)) {
1019 SafeFreePool (ConfigRequest
);
1020 SafeFreePool (AccessResults
);
1021 return EFI_INVALID_PARAMETER
;
1025 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
1027 ASSERT (*AccessProgress
== 0);
1028 Status
= AppendToMultiString (Results
, AccessResults
);
1029 ASSERT_EFI_ERROR (Status
);
1030 SafeFreePool (AccessResults
);
1031 AccessResults
= NULL
;
1032 SafeFreePool (ConfigRequest
);
1033 ConfigRequest
= NULL
;
1038 // Free the exported storage resource
1040 while (!IsListEmpty (&StorageListHdr
)) {
1042 StorageListHdr
.ForwardLink
,
1043 HII_FORMSET_STORAGE
,
1045 HII_FORMSET_STORAGE_SIGNATURE
1047 RemoveEntryList (&Storage
->Entry
);
1048 SafeFreePool (Storage
->Name
);
1049 SafeFreePool (Storage
);
1054 return EFI_UNSUPPORTED
;
1060 This function processes the results of processing forms and routes it to the
1061 appropriate handlers or storage.
1063 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1065 @param Configuration A null-terminated Unicode string in
1066 <MulltiConfigResp> format.
1067 @param Progress A pointer to a string filled in with the offset of
1068 the most recent & before the first failing name /
1069 value pair (or the beginning of the string if the
1070 failure is in the first name / value pair) or the
1071 terminating NULL if all was successful.
1073 @retval EFI_SUCCESS The results have been distributed or are awaiting
1075 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
1076 results that must be stored awaiting possible
1078 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
1079 would result in this type of error.
1080 @retval EFI_NOT_FOUND Target for the specified routing data was not
1086 HiiConfigRoutingRouteConfig (
1087 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1088 IN CONST EFI_STRING Configuration
,
1089 OUT EFI_STRING
*Progress
1092 #ifndef _DISABLE_UNUSED_HII_PROTOCOLS_
1094 HII_DATABASE_PRIVATE_DATA
*Private
;
1095 EFI_STRING StringPtr
;
1096 EFI_STRING ConfigResp
;
1099 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1101 HII_DATABASE_RECORD
*Database
;
1102 UINT8
*CurrentDevicePath
;
1103 EFI_HANDLE DriverHandle
;
1104 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1105 EFI_STRING AccessProgress
;
1109 if (This
== NULL
|| Progress
== NULL
) {
1110 return EFI_INVALID_PARAMETER
;
1113 if (Configuration
== NULL
) {
1115 return EFI_INVALID_PARAMETER
;
1118 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1119 StringPtr
= Configuration
;
1120 *Progress
= StringPtr
;
1123 // The first element of <MultiConfigResp> should be
1124 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
1126 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1127 return EFI_INVALID_PARAMETER
;
1130 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
1132 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
1133 // or most recent & before the error.
1135 if (StringPtr
== Configuration
) {
1136 *Progress
= StringPtr
;
1138 *Progress
= StringPtr
- 1;
1142 // Process each <ConfigResp> of <MultiConfigResp>
1144 Length
= CalculateConfigStringLen (StringPtr
);
1145 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
1146 if (ConfigResp
== NULL
) {
1147 return EFI_OUT_OF_RESOURCES
;
1150 // Append '\0' to the end of ConfigRequest
1152 *(ConfigResp
+ Length
) = 0;
1155 // Get the UEFI device path
1157 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
1158 if (EFI_ERROR (Status
)) {
1159 SafeFreePool (ConfigResp
);
1164 // Find driver which matches the routing data.
1166 DriverHandle
= NULL
;
1167 for (Link
= Private
->DatabaseList
.ForwardLink
;
1168 Link
!= &Private
->DatabaseList
;
1169 Link
= Link
->ForwardLink
1171 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
1172 CurrentDevicePath
= Database
->PackageList
->DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
1173 if (CurrentDevicePath
!= NULL
) {
1177 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
1179 DriverHandle
= Database
->DriverHandle
;
1185 SafeFreePool (DevicePath
);
1187 if (DriverHandle
== NULL
) {
1189 // Routing data does not match any known driver.
1190 // Set Progress to the 'G' in "GUID" of the routing header.
1192 *Progress
= StringPtr
;
1193 SafeFreePool (ConfigResp
);
1194 return EFI_NOT_FOUND
;
1198 // Call corresponding ConfigAccess protocol to route settings
1200 Status
= gBS
->HandleProtocol (
1202 &gEfiHiiConfigAccessProtocolGuid
,
1203 (VOID
**) &ConfigAccess
1205 ASSERT_EFI_ERROR (Status
);
1207 Status
= ConfigAccess
->RouteConfig (
1213 if (EFI_ERROR (Status
)) {
1215 // AccessProgress indicates the parsing progress on <ConfigResp>.
1216 // Map it to the progress on <MultiConfigResp> then return it.
1218 RemainSize
= StrSize (AccessProgress
);
1219 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
1222 SafeFreePool (ConfigResp
);
1226 SafeFreePool (ConfigResp
);
1230 // Go to next <ConfigResp> (skip '&').
1232 StringPtr
+= Length
;
1233 if (*StringPtr
== 0) {
1234 *Progress
= StringPtr
;
1244 return EFI_UNSUPPORTED
;
1250 This helper function is to be called by drivers to map configuration data
1251 stored in byte array ("block") formats such as UEFI Variables into current
1252 configuration strings.
1254 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1256 @param ConfigRequest A null-terminated Unicode string in
1257 <ConfigRequest> format.
1258 @param Block Array of bytes defining the block's configuration.
1259 @param BlockSize Length in bytes of Block.
1260 @param Config Filled-in configuration string. String allocated
1261 by the function. Returned only if call is
1263 @param Progress A pointer to a string filled in with the offset of
1264 the most recent & before the first failing
1265 name/value pair (or the beginning of the string if
1266 the failure is in the first name / value pair) or
1267 the terminating NULL if all was successful.
1269 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1270 terminator at the end of the ConfigRequest
1272 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1273 points to the first character of ConfigRequest.
1274 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
1275 Block parameter would result in this type of
1276 error. Progress points to the first character of
1278 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
1279 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
1280 Block is left updated and Progress points at
1281 the "&" preceding the first non-<BlockName>.
1287 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1288 IN CONST EFI_STRING ConfigRequest
,
1289 IN CONST UINT8
*Block
,
1290 IN CONST UINTN BlockSize
,
1291 OUT EFI_STRING
*Config
,
1292 OUT EFI_STRING
*Progress
1295 HII_DATABASE_PRIVATE_DATA
*Private
;
1296 EFI_STRING StringPtr
;
1304 EFI_STRING ValueStr
;
1305 EFI_STRING ConfigElement
;
1307 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
1308 return EFI_INVALID_PARAMETER
;
1311 if (Block
== NULL
|| ConfigRequest
== NULL
) {
1312 *Progress
= ConfigRequest
;
1313 return EFI_INVALID_PARAMETER
;
1317 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1318 ASSERT (Private
!= NULL
);
1320 StringPtr
= ConfigRequest
;
1323 ConfigElement
= NULL
;
1326 // Allocate a fix length of memory to store Results. Reallocate memory for
1327 // Results if this fix length is insufficient.
1329 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
1330 if (*Config
== NULL
) {
1331 return EFI_OUT_OF_RESOURCES
;
1337 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1338 *Progress
= StringPtr
;
1339 Status
= EFI_INVALID_PARAMETER
;
1342 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1345 if (*StringPtr
== 0) {
1346 *Progress
= StringPtr
;
1347 Status
= EFI_INVALID_PARAMETER
;
1350 while (*StringPtr
++ != L
'&');
1353 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
1355 Length
= StringPtr
- ConfigRequest
;
1356 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
1359 // Parse each <RequestElement> if exists
1360 // Only <BlockName> format is supported by this help function.
1361 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
1363 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1365 // Back up the header of one <BlockName>
1369 StringPtr
+= StrLen (L
"OFFSET=");
1373 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1374 if (Status
== EFI_OUT_OF_RESOURCES
) {
1375 *Progress
= ConfigRequest
;
1382 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1384 SafeFreePool (TmpBuffer
);
1386 StringPtr
+= Length
;
1387 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1388 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1389 Status
= EFI_INVALID_PARAMETER
;
1392 StringPtr
+= StrLen (L
"&WIDTH=");
1397 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1398 if (Status
== EFI_OUT_OF_RESOURCES
) {
1399 *Progress
= ConfigRequest
;
1406 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1408 SafeFreePool (TmpBuffer
);
1410 StringPtr
+= Length
;
1411 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1412 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1413 Status
= EFI_INVALID_PARAMETER
;
1418 // Calculate Value and convert it to hex string.
1420 if (Offset
+ Width
> BlockSize
) {
1421 *Progress
= StringPtr
;
1422 Status
= EFI_DEVICE_ERROR
;
1426 Value
= (UINT8
*) AllocateZeroPool (Width
);
1427 if (Value
== NULL
) {
1428 *Progress
= ConfigRequest
;
1429 Status
= EFI_OUT_OF_RESOURCES
;
1433 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
1435 Length
= Width
* 2 + 1;
1436 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1437 if (ValueStr
== NULL
) {
1438 *Progress
= ConfigRequest
;
1439 Status
= EFI_OUT_OF_RESOURCES
;
1443 Status
= BufToHexString (ValueStr
, &Length
, Value
, Width
);
1444 ASSERT_EFI_ERROR (Status
);
1447 SafeFreePool (Value
);
1451 // Build a ConfigElement
1453 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
1454 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1455 if (ConfigElement
== NULL
) {
1456 Status
= EFI_OUT_OF_RESOURCES
;
1459 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
1460 if (*StringPtr
== 0) {
1461 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
1463 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
1464 StrCat (ConfigElement
, L
"VALUE=");
1465 StrCat (ConfigElement
, ValueStr
);
1467 AppendToMultiString (Config
, ConfigElement
);
1469 SafeFreePool (ConfigElement
);
1470 SafeFreePool (ValueStr
);
1471 ConfigElement
= NULL
;
1475 // If '\0', parsing is finished. Otherwise skip '&' to continue
1477 if (*StringPtr
== 0) {
1480 AppendToMultiString (Config
, L
"&");
1485 if (*StringPtr
!= 0) {
1486 *Progress
= StringPtr
- 1;
1487 Status
= EFI_INVALID_PARAMETER
;
1491 *Progress
= StringPtr
;
1496 SafeFreePool (*Config
);
1497 SafeFreePool (ValueStr
);
1498 SafeFreePool (Value
);
1499 SafeFreePool (ConfigElement
);
1507 This helper function is to be called by drivers to map configuration strings
1508 to configurations stored in byte array ("block") formats such as UEFI Variables.
1510 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1512 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
1514 @param Block A possibly null array of bytes representing the
1515 current block. Only bytes referenced in the
1516 ConfigResp string in the block are modified. If
1517 this parameter is null or if the *BlockSize
1518 parameter is (on input) shorter than required by
1519 the Configuration string, only the BlockSize
1520 parameter is updated and an appropriate status
1521 (see below) is returned.
1522 @param BlockSize The length of the Block in units of UINT8. On
1523 input, this is the size of the Block. On output,
1524 if successful, contains the index of the last
1525 modified byte in the Block.
1526 @param Progress On return, points to an element of the ConfigResp
1527 string filled in with the offset of the most
1528 recent '&' before the first failing name / value
1529 pair (or the beginning of the string if the
1530 failure is in the first name / value pair) or the
1531 terminating NULL if all was successful.
1533 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1534 terminator at the end of the ConfigResp string.
1535 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1536 points to the first character of ConfigResp.
1537 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
1538 Block parameter would result in this type of
1539 error. Progress points to the first character of
1541 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
1542 value pair. Block is left updated and
1543 Progress points at the '&' preceding the first
1550 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1551 IN CONST EFI_STRING ConfigResp
,
1552 IN OUT UINT8
*Block
,
1553 IN OUT UINTN
*BlockSize
,
1554 OUT EFI_STRING
*Progress
1557 HII_DATABASE_PRIVATE_DATA
*Private
;
1558 EFI_STRING StringPtr
;
1567 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
1568 return EFI_INVALID_PARAMETER
;
1571 if (ConfigResp
== NULL
|| Block
== NULL
) {
1572 *Progress
= ConfigResp
;
1573 return EFI_INVALID_PARAMETER
;
1576 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1577 ASSERT (Private
!= NULL
);
1579 StringPtr
= ConfigResp
;
1580 BufferSize
= *BlockSize
;
1586 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1587 *Progress
= StringPtr
;
1588 Status
= EFI_INVALID_PARAMETER
;
1591 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1594 if (*StringPtr
== 0) {
1595 *Progress
= StringPtr
;
1596 Status
= EFI_INVALID_PARAMETER
;
1599 while (*StringPtr
++ != L
'&');
1602 // Parse each <ConfigElement> if exists
1603 // Only <BlockConfig> format is supported by this help function.
1604 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
1606 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1607 StringPtr
+= StrLen (L
"OFFSET=");
1611 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1612 if (Status
== EFI_OUT_OF_RESOURCES
) {
1613 *Progress
= ConfigResp
;
1620 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1622 SafeFreePool (TmpBuffer
);
1624 StringPtr
+= Length
;
1625 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1626 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1627 Status
= EFI_INVALID_PARAMETER
;
1630 StringPtr
+= StrLen (L
"&WIDTH=");
1635 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1636 if (Status
== EFI_OUT_OF_RESOURCES
) {
1637 *Progress
= ConfigResp
;
1644 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1646 SafeFreePool (TmpBuffer
);
1648 StringPtr
+= Length
;
1649 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1650 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1651 Status
= EFI_INVALID_PARAMETER
;
1654 StringPtr
+= StrLen (L
"&VALUE=");
1659 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
1660 if (Status
== EFI_OUT_OF_RESOURCES
) {
1661 *Progress
= ConfigResp
;
1665 StringPtr
+= Length
;
1666 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1667 *Progress
= StringPtr
- Length
- 7;
1668 Status
= EFI_INVALID_PARAMETER
;
1673 // Update the Block with configuration info
1676 if (Offset
+ Width
> BufferSize
) {
1677 return EFI_DEVICE_ERROR
;
1680 CopyMem (Block
+ Offset
, Value
, Width
);
1681 *BlockSize
= Offset
+ Width
- 1;
1683 SafeFreePool (Value
);
1687 // If '\0', parsing is finished. Otherwise skip '&' to continue
1689 if (*StringPtr
== 0) {
1696 if (*StringPtr
!= 0) {
1697 *Progress
= StringPtr
- 1;
1698 Status
= EFI_INVALID_PARAMETER
;
1702 *Progress
= StringPtr
;
1707 SafeFreePool (Value
);
1713 This helper function is to be called by drivers to extract portions of
1714 a larger configuration string.
1716 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1718 @param Configuration A null-terminated Unicode string in
1719 <MultiConfigAltResp> format.
1720 @param Guid A pointer to the GUID value to search for in the
1721 routing portion of the ConfigResp string when
1722 retrieving the requested data. If Guid is NULL,
1723 then all GUID values will be searched for.
1724 @param Name A pointer to the NAME value to search for in the
1725 routing portion of the ConfigResp string when
1726 retrieving the requested data. If Name is NULL,
1727 then all Name values will be searched for.
1728 @param DevicePath A pointer to the PATH value to search for in the
1729 routing portion of the ConfigResp string when
1730 retrieving the requested data. If DevicePath is
1731 NULL, then all DevicePath values will be searched
1733 @param AltCfgId A pointer to the ALTCFG value to search for in the
1734 routing portion of the ConfigResp string when
1735 retrieving the requested data. If this parameter
1736 is NULL, then the current setting will be
1738 @param AltCfgResp A pointer to a buffer which will be allocated by
1739 the function which contains the retrieved string
1740 as requested. This buffer is only allocated if
1741 the call was successful.
1743 @retval EFI_SUCCESS The request succeeded. The requested data was
1744 extracted and placed in the newly allocated
1746 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
1747 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1748 @retval EFI_NOT_FOUND Target for the specified routing data was not
1755 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1756 IN CONST EFI_STRING Configuration
,
1757 IN CONST EFI_GUID
*Guid
,
1758 IN CONST EFI_STRING Name
,
1759 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1760 IN CONST UINT16
*AltCfgId
,
1761 OUT EFI_STRING
*AltCfgResp
1764 #ifndef _DISABLE_UNUSED_HII_PROTOCOLS_
1767 EFI_STRING StringPtr
;
1768 EFI_STRING HdrStart
;
1775 EFI_STRING AltIdStr
;
1792 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
1793 return EFI_INVALID_PARAMETER
;
1796 StringPtr
= Configuration
;
1797 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1798 return EFI_INVALID_PARAMETER
;
1802 // Generate the sub string for later matching.
1804 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
1807 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1808 (VOID
*) DevicePath
,
1812 if (AltCfgId
!= NULL
) {
1813 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
1816 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1818 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1821 while (*StringPtr
!= 0) {
1823 // Try to match the GUID
1826 TmpPtr
= StrStr (StringPtr
, GuidStr
);
1827 if (TmpPtr
== NULL
) {
1828 Status
= EFI_NOT_FOUND
;
1834 // Jump to <NameHdr>
1837 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
1839 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
1840 if (StringPtr
== NULL
) {
1841 Status
= EFI_NOT_FOUND
;
1849 // Try to match the NAME
1851 if (GuidFlag
&& !NameFlag
) {
1852 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
1856 // Jump to <PathHdr>
1859 StringPtr
+= StrLen (NameStr
);
1861 StringPtr
= StrStr (StringPtr
, L
"PATH=");
1862 if (StringPtr
== NULL
) {
1863 Status
= EFI_NOT_FOUND
;
1872 // Try to match the DevicePath
1874 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
1875 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
1880 // Jump to '&' before <DescHdr> or <ConfigBody>
1882 if (DevicePath
!= NULL
) {
1883 StringPtr
+= StrLen (PathStr
);
1885 StringPtr
= StrStr (StringPtr
, L
"&");
1886 if (StringPtr
== NULL
) {
1887 Status
= EFI_NOT_FOUND
;
1892 HdrEnd
= ++StringPtr
;
1897 // Try to match the AltCfgId
1899 if (GuidFlag
&& NameFlag
&& PathFlag
) {
1900 if (AltCfgId
== NULL
) {
1902 // Return Current Setting when AltCfgId is NULL.
1904 Status
= OutputConfigBody (StringPtr
, &Result
);
1908 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
1910 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
1915 Status
= OutputConfigBody (StringPtr
, &Result
);
1921 Status
= EFI_NOT_FOUND
;
1925 if (!EFI_ERROR (Status
)) {
1927 // Copy the <ConfigHdr> and <ConfigBody>
1929 Length
= HdrEnd
- HdrStart
+ StrLen (Result
);
1930 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1931 if (*AltCfgResp
== NULL
) {
1932 Status
= EFI_OUT_OF_RESOURCES
;
1934 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
1935 StrCat (*AltCfgResp
, Result
);
1936 Status
= EFI_SUCCESS
;
1940 SafeFreePool (GuidStr
);
1941 SafeFreePool (NameStr
);
1942 SafeFreePool (PathStr
);
1943 SafeFreePool (AltIdStr
);
1944 SafeFreePool (Result
);
1949 return EFI_UNSUPPORTED
;