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"
29 Calculate the number of Unicode characters of the incoming Configuration string,
30 not including NULL terminator.
32 This is a internal function.
34 @param String String in <MultiConfigRequest> or
35 <MultiConfigResp> format.
37 @return The number of Unicode characters.
41 CalculateConfigStringLen (
48 // "GUID=" should be the first element of incoming string.
50 ASSERT (String
!= NULL
);
51 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
53 Length
= StrLen (L
"GUID=");
57 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
58 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
60 while (*String
!= 0 && StrnCmp (String
, L
"&GUID=", StrLen (L
"&GUID=")) != 0) {
70 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
71 from <PathHdr> of <ConfigHdr>.
73 This is a internal function.
75 @param String UEFI configuration string
76 @param DevicePath binary of a UEFI device path.
78 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
79 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
80 @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 HexStringToBufInReverseOrder (*DevicePath
, &Length
, DevicePathString
);
136 SafeFreePool (DevicePathString
);
144 Extract Storage from all Form Packages in current hii database.
146 This is a internal function.
148 @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.
149 @param StorageListHead Storage link List head.
151 @retval EFI_NOT_FOUND There is no form package in current hii database.
152 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
153 @retval EFI_SUCCESS All existing storage is exported.
158 IN EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
,
159 IN OUT LIST_ENTRY
*StorageListHead
165 EFI_HII_HANDLE
*HandleBuffer
;
168 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
169 EFI_HII_PACKAGE_HEADER
*Package
;
173 HII_FORMSET_STORAGE
*Storage
;
174 EFI_HII_HANDLE HiiHandle
;
175 EFI_HANDLE DriverHandle
;
177 UINT32 PackageListLength
;
178 EFI_HII_PACKAGE_HEADER PackageHeader
;
181 // Find the package list which contains Form package.
185 Status
= HiiListPackageLists (
187 EFI_HII_PACKAGE_FORM
,
192 if (Status
== EFI_BUFFER_TOO_SMALL
) {
193 HandleBuffer
= AllocateZeroPool (BufferSize
);
194 ASSERT (HandleBuffer
!= NULL
);
196 Status
= HiiListPackageLists (
198 EFI_HII_PACKAGE_FORM
,
204 if (EFI_ERROR (Status
)) {
205 SafeFreePool (HandleBuffer
);
209 HandleCount
= BufferSize
/ sizeof (EFI_HII_HANDLE
);
210 for (Index
= 0; Index
< HandleCount
; Index
++) {
211 HiiHandle
= HandleBuffer
[Index
];
214 HiiPackageList
= NULL
;
215 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
216 if (Status
== EFI_BUFFER_TOO_SMALL
) {
217 HiiPackageList
= AllocateZeroPool (BufferSize
);
218 ASSERT (HiiPackageList
!= NULL
);
219 Status
= HiiExportPackageLists (HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
221 if (EFI_ERROR (Status
)) {
222 SafeFreePool (HandleBuffer
);
223 SafeFreePool (HiiPackageList
);
228 // Get Form package from this HII package List
230 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
231 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
233 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
235 while (Offset
< PackageListLength
) {
236 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
237 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
238 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
241 Offset
+= PackageHeader
.Length
;
243 if (Offset
>= PackageListLength
) {
245 // Error here: No Form package found in this Package List
251 // Search Storage definition in this Form package
253 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
254 while (Offset
< PackageHeader
.Length
) {
255 OpCodeData
= ((UINT8
*) Package
) + Offset
;
256 Offset
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
258 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
260 if ((Operand
== EFI_IFR_VARSTORE_OP
) ||
261 (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) ||
262 (Operand
== EFI_IFR_VARSTORE_EFI_OP
)) {
264 Storage
= AllocateZeroPool (sizeof (HII_FORMSET_STORAGE
));
265 ASSERT (Storage
!= NULL
);
266 InsertTailList (StorageListHead
, &Storage
->Entry
);
268 Storage
->Signature
= HII_FORMSET_STORAGE_SIGNATURE
;
269 Storage
->HiiHandle
= HiiHandle
;
271 Status
= HiiGetPackageListHandle (HiiDatabase
, HiiHandle
, &DriverHandle
);
272 if (EFI_ERROR (Status
)) {
273 SafeFreePool (HandleBuffer
);
274 SafeFreePool (HiiPackageList
);
275 SafeFreePool (Storage
);
278 Storage
->DriverHandle
= DriverHandle
;
280 if (Operand
== EFI_IFR_VARSTORE_OP
) {
281 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
283 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
284 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
286 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
287 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
288 ASSERT (Storage
->Name
!= NULL
);
289 for (Index2
= 0; AsciiString
[Index2
] != 0; Index2
++) {
290 Storage
->Name
[Index2
] = (CHAR16
) AsciiString
[Index2
];
293 // Append '\0' to the end of the unicode string.
295 Storage
->Name
[Index2
] = 0;
296 } else if (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
297 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
299 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
300 } else if (Operand
== EFI_IFR_VARSTORE_EFI_OP
) {
301 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
303 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
308 SafeFreePool (HiiPackageList
);
311 SafeFreePool (HandleBuffer
);
318 Generate a sub string then output it.
320 This is a internal function.
322 @param String A constant string which is the prefix of the to be
323 generated string, e.g. GUID=
324 @param BufferLen The length of the Buffer in bytes.
325 @param Buffer Points to a buffer which will be converted to be the
326 content of the generated string.
327 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
328 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
329 if 3, the buffer contains other data.
330 @param SubStr Points to the output string. It's caller's
331 responsibility to free this buffer.
337 IN CONST EFI_STRING String
,
341 OUT EFI_STRING
*SubStr
347 EFI_STRING StringHeader
;
349 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
351 if (Buffer
== NULL
) {
352 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
353 ASSERT (*SubStr
!= NULL
);
357 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
358 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
359 ASSERT (Str
!= NULL
);
361 StrCpy (Str
, String
);
362 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
364 Status
= EFI_SUCCESS
;
365 StringHeader
= Str
+ StrLen (String
);
369 Status
= BufInReverseOrderToHexString (StringHeader
, (UINT8
*) Buffer
, BufferLen
);
372 Status
= UnicodeToConfigString (StringHeader
, &Length
, (CHAR16
*) Buffer
);
375 Status
= BufToHexString (StringHeader
, &Length
, (UINT8
*) Buffer
, BufferLen
);
377 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
379 ToLower (StringHeader
);
385 ASSERT_EFI_ERROR (Status
);
393 Retrieve the <ConfigBody> from String then output it.
395 This is a internal function.
397 @param String A sub string of a configuration string in
398 <MultiConfigAltResp> format.
399 @param ConfigBody Points to the output string. It's caller's
400 responsibility to free this buffer.
402 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
403 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
404 @retval EFI_SUCCESS All existing storage is exported.
409 IN EFI_STRING String
,
410 OUT EFI_STRING
*ConfigBody
417 if (String
== NULL
|| ConfigBody
== NULL
) {
418 return EFI_INVALID_PARAMETER
;
421 TmpPtr
= StrStr (String
, L
"GUID=");
422 if (TmpPtr
== NULL
) {
424 // It is the last <ConfigResp> of the incoming configuration string.
426 Result
= AllocateCopyPool (StrSize (String
), String
);
427 if (Result
== NULL
) {
428 return EFI_OUT_OF_RESOURCES
;
430 *ConfigBody
= Result
;
435 Length
= TmpPtr
- String
;
436 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
437 if (Result
== NULL
) {
438 return EFI_OUT_OF_RESOURCES
;
441 *(Result
+ Length
- 1) = 0;
442 *ConfigBody
= Result
;
449 Adjusts the size of a previously allocated buffer.
452 @param OldPool A pointer to the buffer whose size is being adjusted.
453 @param OldSize The size of the current buffer.
454 @param NewSize The size of the new buffer.
456 @return The new buffer allocated.
470 NewPool
= AllocateZeroPool (NewSize
);
473 if (OldPool
!= NULL
) {
474 if (NewPool
!= NULL
) {
475 CopyMem (NewPool
, OldPool
, OldSize
< NewSize
? OldSize
: NewSize
);
478 gBS
->FreePool (OldPool
);
486 Append a string to a multi-string format.
488 This is a internal function.
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
502 AppendToMultiString (
503 IN OUT EFI_STRING
*MultiString
,
504 IN EFI_STRING AppendString
507 UINTN AppendStringSize
;
508 UINTN MultiStringSize
;
510 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
511 return EFI_INVALID_PARAMETER
;
514 AppendStringSize
= StrSize (AppendString
);
515 MultiStringSize
= StrSize (*MultiString
);
518 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
520 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
521 MultiStringSize
> MAX_STRING_LENGTH
) {
522 *MultiString
= (EFI_STRING
) ReallocatePool (
523 (VOID
*) (*MultiString
),
525 MultiStringSize
+ AppendStringSize
530 // Append the incoming string
532 StrCat (*MultiString
, AppendString
);
539 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
541 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
543 This is a internal function.
545 @param StringPtr String in <BlockConfig> format and points to the
546 first character of <Number>.
547 @param Number The output value. Caller takes the responsibility
549 @param Len Length of the <Number>, in characters.
551 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
553 @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 HII_DATABASE_PRIVATE_DATA
*Private
;
660 EFI_STRING StringPtr
;
661 EFI_STRING ConfigRequest
;
663 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
666 HII_DATABASE_RECORD
*Database
;
667 UINT8
*DevicePathPkg
;
668 UINT8
*CurrentDevicePath
;
669 EFI_HANDLE DriverHandle
;
670 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
671 EFI_STRING AccessProgress
;
672 EFI_STRING AccessResults
;
677 // For size reduction, please define PcdSupportFullConfigRoutingProtocol
678 // as FALSE. But this renders the system to not 100% compliant with
679 // UEFI 2.1. Use this with caution.
681 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol
)) {
682 return EFI_UNSUPPORTED
;
685 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
686 return EFI_INVALID_PARAMETER
;
689 if (Request
== NULL
) {
691 return EFI_INVALID_PARAMETER
;
694 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
696 *Progress
= StringPtr
;
699 // The first element of <MultiConfigRequest> should be
700 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
702 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
703 return EFI_INVALID_PARAMETER
;
707 // Allocate a fix length of memory to store Results. Reallocate memory for
708 // Results if this fix length is insufficient.
710 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
711 if (*Results
== NULL
) {
712 return EFI_OUT_OF_RESOURCES
;
715 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
717 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
718 // or most recent & before the error.
720 if (StringPtr
== Request
) {
721 *Progress
= StringPtr
;
723 *Progress
= StringPtr
- 1;
727 // Process each <ConfigRequest> of <MultiConfigRequest>
729 Length
= CalculateConfigStringLen (StringPtr
);
730 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
731 if (ConfigRequest
== NULL
) {
732 return EFI_OUT_OF_RESOURCES
;
734 *(ConfigRequest
+ Length
) = 0;
737 // Get the UEFI device path
739 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
740 if (EFI_ERROR (Status
)) {
741 SafeFreePool (ConfigRequest
);
746 // Find driver which matches the routing data.
749 for (Link
= Private
->DatabaseList
.ForwardLink
;
750 Link
!= &Private
->DatabaseList
;
751 Link
= Link
->ForwardLink
753 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
755 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
756 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
760 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
762 DriverHandle
= Database
->DriverHandle
;
768 SafeFreePool (DevicePath
);
770 if (DriverHandle
== NULL
) {
772 // Routing data does not match any known driver.
773 // Set Progress to the 'G' in "GUID" of the routing header.
775 *Progress
= StringPtr
;
776 SafeFreePool (ConfigRequest
);
777 return EFI_NOT_FOUND
;
781 // Call corresponding ConfigAccess protocol to extract settings
783 Status
= gBS
->HandleProtocol (
785 &gEfiHiiConfigAccessProtocolGuid
,
786 (VOID
**) &ConfigAccess
788 ASSERT_EFI_ERROR (Status
);
790 Status
= ConfigAccess
->ExtractConfig (
796 if (EFI_ERROR (Status
)) {
798 // AccessProgress indicates the parsing progress on <ConfigRequest>.
799 // Map it to the progress on <MultiConfigRequest> then return it.
801 RemainSize
= StrSize (AccessProgress
);
802 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
805 SafeFreePool (ConfigRequest
);
810 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
812 ASSERT (*AccessProgress
== 0);
813 Status
= AppendToMultiString (Results
, AccessResults
);
814 ASSERT_EFI_ERROR (Status
);
815 SafeFreePool (AccessResults
);
816 AccessResults
= NULL
;
817 SafeFreePool (ConfigRequest
);
818 ConfigRequest
= NULL
;
821 // Go to next <ConfigRequest> (skip '&').
824 if (*StringPtr
== 0) {
825 *Progress
= StringPtr
;
839 This function allows the caller to request the current configuration for the
840 entirety of the current HII database and returns the data in a
841 null-terminated Unicode string.
843 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
845 @param Results Null-terminated Unicode string in
846 <MultiConfigAltResp> format which has all values
847 filled in for the names in the Request string.
848 String to be allocated by the called function.
849 De-allocation is up to the caller.
851 @retval EFI_SUCCESS The Results string is filled with the values
852 corresponding to all requested names.
853 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
854 results that must be stored awaiting possible
856 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
857 parameter would result in this type of error.
862 HiiConfigRoutingExportConfig (
863 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
864 OUT EFI_STRING
*Results
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 // For size reduction, please define PcdSupportFullConfigRoutingProtocol
885 // as FALSE. But this renders the system to not 100% compliant with
886 // UEFI 2.1. Use this with caution.
888 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol
)) {
889 return EFI_UNSUPPORTED
;
892 if (This
== NULL
|| Results
== NULL
) {
893 return EFI_INVALID_PARAMETER
;
896 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
898 InitializeListHead (&StorageListHdr
);
900 Status
= ExportAllStorage (&Private
->HiiDatabase
, &StorageListHdr
);
901 if (EFI_ERROR (Status
)) {
906 // Allocate a fix length of memory to store Results. Reallocate memory for
907 // Results if this fix length is insufficient.
909 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
910 if (*Results
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
915 // Parsing all formset storages.
917 for (Link
= StorageListHdr
.ForwardLink
; Link
!= &StorageListHdr
; Link
= Link
->ForwardLink
) {
918 Storage
= CR (Link
, HII_FORMSET_STORAGE
, Entry
, HII_FORMSET_STORAGE_SIGNATURE
);
920 // Find the corresponding device path instance
922 Status
= gBS
->HandleProtocol (
923 Storage
->DriverHandle
,
924 &gEfiDevicePathProtocolGuid
,
925 (VOID
**) &DevicePath
927 if (EFI_ERROR (Status
)) {
931 // Convert the device path binary to hex UNICODE %02x bytes in the same order
932 // as the device path resides in RAM memory.
934 Length
= GetDevicePathSize (DevicePath
);
935 PathHdrSize
= (Length
* 2 + 1) * sizeof (CHAR16
);
936 PathHdr
= (EFI_STRING
) AllocateZeroPool (PathHdrSize
);
937 if (PathHdr
== NULL
) {
938 return EFI_OUT_OF_RESOURCES
;
940 Status
= BufInReverseOrderToHexString (PathHdr
, (UINT8
*) DevicePath
, Length
);
941 ASSERT_EFI_ERROR (Status
);
944 // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.
945 // It means extract all possible configurations from this specific driver.
947 RequestSize
= (StrLen (L
"GUID=&NAME=&PATH=") + 32) * sizeof (CHAR16
) + PathHdrSize
;
948 if (Storage
->Name
!= NULL
) {
949 RequestSize
+= StrLen (Storage
->Name
) * 4 * sizeof (CHAR16
);
952 ConfigRequest
= (EFI_STRING
) AllocateZeroPool (RequestSize
);
953 if (ConfigRequest
== NULL
) {
954 SafeFreePool (PathHdr
);
955 return EFI_OUT_OF_RESOURCES
;
960 // <GuidHdr> ::= 'GUID='<Guid>
961 // Convert <Guid> in the same order as it resides in RAM memory.
963 StringPtr
= ConfigRequest
;
964 StrnCpy (StringPtr
, L
"GUID=", StrLen (L
"GUID="));
965 StringPtr
+= StrLen (L
"GUID=");
967 Status
= BufInReverseOrderToHexString (StringPtr
, (UINT8
*) (&Storage
->Guid
), sizeof (EFI_GUID
));
968 ASSERT_EFI_ERROR (Status
);
971 ASSERT (*StringPtr
== 0);
977 // <NameHdr> ::= 'NAME='<String>
979 StrnCpy (StringPtr
, L
"NAME=", StrLen (L
"NAME="));
980 StringPtr
+= StrLen (L
"NAME=");
982 if (Storage
->Name
!= NULL
) {
983 Length
= (StrLen (Storage
->Name
) * 4 + 1) * sizeof (CHAR16
);
984 Status
= UnicodeToConfigString (StringPtr
, &Length
, Storage
->Name
);
985 ASSERT_EFI_ERROR (Status
);
986 StringPtr
+= StrLen (Storage
->Name
) * 4;
994 // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>
996 StrnCpy (StringPtr
, L
"PATH=", StrLen (L
"PATH="));
997 StringPtr
+= StrLen (L
"PATH=");
998 StrCpy (StringPtr
, PathHdr
);
1000 SafeFreePool (PathHdr
);
1004 // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the
1005 // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>
1006 // is required to call ConfigAccess.ExtractConfig().
1008 // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess
1009 // to handle such kind of "ConfigRequest". It is not supported till now.
1011 // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()
1012 // will be updated as soon as the decision is made.
1015 // Route the request to corresponding ConfigAccess protocol to extract settings.
1017 Status
= gBS
->HandleProtocol (
1018 Storage
->DriverHandle
,
1019 &gEfiHiiConfigAccessProtocolGuid
,
1020 (VOID
**) &ConfigAccess
1022 ASSERT_EFI_ERROR (Status
);
1024 Status
= ConfigAccess
->ExtractConfig (
1030 if (EFI_ERROR (Status
)) {
1031 SafeFreePool (ConfigRequest
);
1032 SafeFreePool (AccessResults
);
1033 return EFI_INVALID_PARAMETER
;
1037 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
1039 ASSERT (*AccessProgress
== 0);
1040 Status
= AppendToMultiString (Results
, AccessResults
);
1041 ASSERT_EFI_ERROR (Status
);
1042 SafeFreePool (AccessResults
);
1043 AccessResults
= NULL
;
1044 SafeFreePool (ConfigRequest
);
1045 ConfigRequest
= NULL
;
1050 // Free the exported storage resource
1052 while (!IsListEmpty (&StorageListHdr
)) {
1054 StorageListHdr
.ForwardLink
,
1055 HII_FORMSET_STORAGE
,
1057 HII_FORMSET_STORAGE_SIGNATURE
1059 RemoveEntryList (&Storage
->Entry
);
1060 SafeFreePool (Storage
->Name
);
1061 SafeFreePool (Storage
);
1069 This function processes the results of processing forms and routes it to the
1070 appropriate handlers or storage.
1072 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1074 @param Configuration A null-terminated Unicode string in
1075 <MulltiConfigResp> format.
1076 @param Progress A pointer to a string filled in with the offset of
1077 the most recent & before the first failing name /
1078 value pair (or the beginning of the string if the
1079 failure is in the first name / value pair) or the
1080 terminating NULL if all was successful.
1082 @retval EFI_SUCCESS The results have been distributed or are awaiting
1084 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
1085 results that must be stored awaiting possible
1087 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
1088 would result in this type of error.
1089 @retval EFI_NOT_FOUND Target for the specified routing data was not
1095 HiiConfigRoutingRouteConfig (
1096 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1097 IN CONST EFI_STRING Configuration
,
1098 OUT EFI_STRING
*Progress
1101 HII_DATABASE_PRIVATE_DATA
*Private
;
1102 EFI_STRING StringPtr
;
1103 EFI_STRING ConfigResp
;
1106 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1108 HII_DATABASE_RECORD
*Database
;
1109 UINT8
*DevicePathPkg
;
1110 UINT8
*CurrentDevicePath
;
1111 EFI_HANDLE DriverHandle
;
1112 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1113 EFI_STRING AccessProgress
;
1118 // For size reduction, please define PcdSupportFullConfigRoutingProtocol
1119 // as FALSE. But this renders the system to not 100% compliant with
1120 // UEFI 2.1. Use this with caution.
1122 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol
)) {
1123 return EFI_UNSUPPORTED
;
1126 if (This
== NULL
|| Progress
== NULL
) {
1127 return EFI_INVALID_PARAMETER
;
1130 if (Configuration
== NULL
) {
1132 return EFI_INVALID_PARAMETER
;
1135 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1136 StringPtr
= Configuration
;
1137 *Progress
= StringPtr
;
1140 // The first element of <MultiConfigResp> should be
1141 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
1143 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1144 return EFI_INVALID_PARAMETER
;
1147 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
1149 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
1150 // or most recent & before the error.
1152 if (StringPtr
== Configuration
) {
1153 *Progress
= StringPtr
;
1155 *Progress
= StringPtr
- 1;
1159 // Process each <ConfigResp> of <MultiConfigResp>
1161 Length
= CalculateConfigStringLen (StringPtr
);
1162 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
1163 if (ConfigResp
== NULL
) {
1164 return EFI_OUT_OF_RESOURCES
;
1167 // Append '\0' to the end of ConfigRequest
1169 *(ConfigResp
+ Length
) = 0;
1172 // Get the UEFI device path
1174 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
1175 if (EFI_ERROR (Status
)) {
1176 SafeFreePool (ConfigResp
);
1181 // Find driver which matches the routing data.
1183 DriverHandle
= NULL
;
1184 for (Link
= Private
->DatabaseList
.ForwardLink
;
1185 Link
!= &Private
->DatabaseList
;
1186 Link
= Link
->ForwardLink
1188 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
1190 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
1191 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
1195 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
1197 DriverHandle
= Database
->DriverHandle
;
1203 SafeFreePool (DevicePath
);
1205 if (DriverHandle
== NULL
) {
1207 // Routing data does not match any known driver.
1208 // Set Progress to the 'G' in "GUID" of the routing header.
1210 *Progress
= StringPtr
;
1211 SafeFreePool (ConfigResp
);
1212 return EFI_NOT_FOUND
;
1216 // Call corresponding ConfigAccess protocol to route settings
1218 Status
= gBS
->HandleProtocol (
1220 &gEfiHiiConfigAccessProtocolGuid
,
1221 (VOID
**) &ConfigAccess
1223 ASSERT_EFI_ERROR (Status
);
1225 Status
= ConfigAccess
->RouteConfig (
1231 if (EFI_ERROR (Status
)) {
1233 // AccessProgress indicates the parsing progress on <ConfigResp>.
1234 // Map it to the progress on <MultiConfigResp> then return it.
1236 RemainSize
= StrSize (AccessProgress
);
1237 for (TmpPtr
= StringPtr
; CompareMem (TmpPtr
, AccessProgress
, RemainSize
) != 0; TmpPtr
++);
1240 SafeFreePool (ConfigResp
);
1244 SafeFreePool (ConfigResp
);
1248 // Go to next <ConfigResp> (skip '&').
1250 StringPtr
+= Length
;
1251 if (*StringPtr
== 0) {
1252 *Progress
= StringPtr
;
1265 This helper function is to be called by drivers to map configuration data
1266 stored in byte array ("block") formats such as UEFI Variables into current
1267 configuration strings.
1269 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1271 @param ConfigRequest A null-terminated Unicode string in
1272 <ConfigRequest> format.
1273 @param Block Array of bytes defining the block's configuration.
1274 @param BlockSize Length in bytes of Block.
1275 @param Config Filled-in configuration string. String allocated
1276 by the function. Returned only if call is
1278 @param Progress A pointer to a string filled in with the offset of
1279 the most recent & before the first failing
1280 name/value pair (or the beginning of the string if
1281 the failure is in the first name / value pair) or
1282 the terminating NULL if all was successful.
1284 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1285 terminator at the end of the ConfigRequest
1287 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1288 points to the first character of ConfigRequest.
1289 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
1290 Block parameter would result in this type of
1291 error. Progress points to the first character of
1293 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
1294 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
1295 Block is left updated and Progress points at
1296 the "&" preceding the first non-<BlockName>.
1302 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1303 IN CONST EFI_STRING ConfigRequest
,
1304 IN CONST UINT8
*Block
,
1305 IN CONST UINTN BlockSize
,
1306 OUT EFI_STRING
*Config
,
1307 OUT EFI_STRING
*Progress
1310 HII_DATABASE_PRIVATE_DATA
*Private
;
1311 EFI_STRING StringPtr
;
1319 EFI_STRING ValueStr
;
1320 EFI_STRING ConfigElement
;
1322 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
1323 return EFI_INVALID_PARAMETER
;
1326 if (Block
== NULL
|| ConfigRequest
== NULL
) {
1327 *Progress
= ConfigRequest
;
1328 return EFI_INVALID_PARAMETER
;
1332 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1333 ASSERT (Private
!= NULL
);
1335 StringPtr
= ConfigRequest
;
1338 ConfigElement
= NULL
;
1341 // Allocate a fix length of memory to store Results. Reallocate memory for
1342 // Results if this fix length is insufficient.
1344 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
1345 if (*Config
== NULL
) {
1346 return EFI_OUT_OF_RESOURCES
;
1352 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1353 *Progress
= StringPtr
;
1354 Status
= EFI_INVALID_PARAMETER
;
1357 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1360 if (*StringPtr
== 0) {
1361 *Progress
= StringPtr
;
1362 Status
= EFI_INVALID_PARAMETER
;
1366 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
1369 if (*StringPtr
== 0) {
1370 *Progress
= StringPtr
;
1371 Status
= EFI_INVALID_PARAMETER
;
1380 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
1382 Length
= StringPtr
- ConfigRequest
;
1383 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
1386 // Parse each <RequestElement> if exists
1387 // Only <BlockName> format is supported by this help function.
1388 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
1390 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1392 // Back up the header of one <BlockName>
1396 StringPtr
+= StrLen (L
"OFFSET=");
1400 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1401 if (Status
== EFI_OUT_OF_RESOURCES
) {
1402 *Progress
= ConfigRequest
;
1409 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1411 SafeFreePool (TmpBuffer
);
1413 StringPtr
+= Length
;
1414 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1415 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1416 Status
= EFI_INVALID_PARAMETER
;
1419 StringPtr
+= StrLen (L
"&WIDTH=");
1424 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1425 if (Status
== EFI_OUT_OF_RESOURCES
) {
1426 *Progress
= ConfigRequest
;
1433 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1435 SafeFreePool (TmpBuffer
);
1437 StringPtr
+= Length
;
1438 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1439 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1440 Status
= EFI_INVALID_PARAMETER
;
1445 // Calculate Value and convert it to hex string.
1447 if (Offset
+ Width
> BlockSize
) {
1448 *Progress
= StringPtr
;
1449 Status
= EFI_DEVICE_ERROR
;
1453 Value
= (UINT8
*) AllocateZeroPool (Width
);
1454 if (Value
== NULL
) {
1455 *Progress
= ConfigRequest
;
1456 Status
= EFI_OUT_OF_RESOURCES
;
1460 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
1462 Length
= Width
* 2 + 1;
1463 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1464 if (ValueStr
== NULL
) {
1465 *Progress
= ConfigRequest
;
1466 Status
= EFI_OUT_OF_RESOURCES
;
1470 Status
= BufToHexString (ValueStr
, &Length
, Value
, Width
);
1471 ASSERT_EFI_ERROR (Status
);
1474 SafeFreePool (Value
);
1478 // Build a ConfigElement
1480 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
1481 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
1482 if (ConfigElement
== NULL
) {
1483 Status
= EFI_OUT_OF_RESOURCES
;
1486 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
1487 if (*StringPtr
== 0) {
1488 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
1490 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
1491 StrCat (ConfigElement
, L
"VALUE=");
1492 StrCat (ConfigElement
, ValueStr
);
1494 AppendToMultiString (Config
, ConfigElement
);
1496 SafeFreePool (ConfigElement
);
1497 SafeFreePool (ValueStr
);
1498 ConfigElement
= NULL
;
1502 // If '\0', parsing is finished. Otherwise skip '&' to continue
1504 if (*StringPtr
== 0) {
1507 AppendToMultiString (Config
, L
"&");
1512 if (*StringPtr
!= 0) {
1513 *Progress
= StringPtr
- 1;
1514 Status
= EFI_INVALID_PARAMETER
;
1518 *Progress
= StringPtr
;
1523 SafeFreePool (*Config
);
1524 SafeFreePool (ValueStr
);
1525 SafeFreePool (Value
);
1526 SafeFreePool (ConfigElement
);
1534 This helper function is to be called by drivers to map configuration strings
1535 to configurations stored in byte array ("block") formats such as UEFI Variables.
1537 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1539 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
1541 @param Block A possibly null array of bytes representing the
1542 current block. Only bytes referenced in the
1543 ConfigResp string in the block are modified. If
1544 this parameter is null or if the *BlockSize
1545 parameter is (on input) shorter than required by
1546 the Configuration string, only the BlockSize
1547 parameter is updated and an appropriate status
1548 (see below) is returned.
1549 @param BlockSize The length of the Block in units of UINT8. On
1550 input, this is the size of the Block. On output,
1551 if successful, contains the index of the last
1552 modified byte in the Block.
1553 @param Progress On return, points to an element of the ConfigResp
1554 string filled in with the offset of the most
1555 recent '&' before the first failing name / value
1556 pair (or the beginning of the string if the
1557 failure is in the first name / value pair) or the
1558 terminating NULL if all was successful.
1560 @retval EFI_SUCCESS The request succeeded. Progress points to the null
1561 terminator at the end of the ConfigResp string.
1562 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
1563 points to the first character of ConfigResp.
1564 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
1565 Block parameter would result in this type of
1566 error. Progress points to the first character of
1568 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
1569 value pair. Block is left updated and
1570 Progress points at the '&' preceding the first
1577 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1578 IN CONST EFI_STRING ConfigResp
,
1579 IN OUT UINT8
*Block
,
1580 IN OUT UINTN
*BlockSize
,
1581 OUT EFI_STRING
*Progress
1584 HII_DATABASE_PRIVATE_DATA
*Private
;
1585 EFI_STRING StringPtr
;
1594 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
1595 return EFI_INVALID_PARAMETER
;
1598 if (ConfigResp
== NULL
|| Block
== NULL
) {
1599 *Progress
= ConfigResp
;
1600 return EFI_INVALID_PARAMETER
;
1603 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1604 ASSERT (Private
!= NULL
);
1606 StringPtr
= ConfigResp
;
1607 BufferSize
= *BlockSize
;
1613 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1614 *Progress
= StringPtr
;
1615 Status
= EFI_INVALID_PARAMETER
;
1618 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
1621 if (*StringPtr
== 0) {
1622 *Progress
= StringPtr
;
1623 Status
= EFI_INVALID_PARAMETER
;
1627 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
1630 if (*StringPtr
== 0) {
1631 *Progress
= StringPtr
;
1632 Status
= EFI_INVALID_PARAMETER
;
1641 // Parse each <ConfigElement> if exists
1642 // Only <BlockConfig> format is supported by this help function.
1643 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
1645 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
1646 StringPtr
+= StrLen (L
"OFFSET=");
1650 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1651 if (Status
== EFI_OUT_OF_RESOURCES
) {
1652 *Progress
= ConfigResp
;
1659 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1661 SafeFreePool (TmpBuffer
);
1663 StringPtr
+= Length
;
1664 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1665 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
1666 Status
= EFI_INVALID_PARAMETER
;
1669 StringPtr
+= StrLen (L
"&WIDTH=");
1674 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1675 if (Status
== EFI_OUT_OF_RESOURCES
) {
1676 *Progress
= ConfigResp
;
1683 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
1685 SafeFreePool (TmpBuffer
);
1687 StringPtr
+= Length
;
1688 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
1689 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
1690 Status
= EFI_INVALID_PARAMETER
;
1693 StringPtr
+= StrLen (L
"&VALUE=");
1698 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
1699 if (Status
== EFI_OUT_OF_RESOURCES
) {
1700 *Progress
= ConfigResp
;
1704 StringPtr
+= Length
;
1705 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1706 *Progress
= StringPtr
- Length
- 7;
1707 Status
= EFI_INVALID_PARAMETER
;
1712 // Update the Block with configuration info
1715 if (Offset
+ Width
> BufferSize
) {
1716 return EFI_DEVICE_ERROR
;
1719 CopyMem (Block
+ Offset
, Value
, Width
);
1720 *BlockSize
= Offset
+ Width
- 1;
1722 SafeFreePool (Value
);
1726 // If '\0', parsing is finished. Otherwise skip '&' to continue
1728 if (*StringPtr
== 0) {
1735 if (*StringPtr
!= 0) {
1736 *Progress
= StringPtr
- 1;
1737 Status
= EFI_INVALID_PARAMETER
;
1741 *Progress
= StringPtr
;
1746 SafeFreePool (Value
);
1752 This helper function is to be called by drivers to extract portions of
1753 a larger configuration string.
1755 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
1757 @param Configuration A null-terminated Unicode string in
1758 <MultiConfigAltResp> format.
1759 @param Guid A pointer to the GUID value to search for in the
1760 routing portion of the ConfigResp string when
1761 retrieving the requested data. If Guid is NULL,
1762 then all GUID values will be searched for.
1763 @param Name A pointer to the NAME value to search for in the
1764 routing portion of the ConfigResp string when
1765 retrieving the requested data. If Name is NULL,
1766 then all Name values will be searched for.
1767 @param DevicePath A pointer to the PATH value to search for in the
1768 routing portion of the ConfigResp string when
1769 retrieving the requested data. If DevicePath is
1770 NULL, then all DevicePath values will be searched
1772 @param AltCfgId A pointer to the ALTCFG value to search for in the
1773 routing portion of the ConfigResp string when
1774 retrieving the requested data. If this parameter
1775 is NULL, then the current setting will be
1777 @param AltCfgResp A pointer to a buffer which will be allocated by
1778 the function which contains the retrieved string
1779 as requested. This buffer is only allocated if
1780 the call was successful.
1782 @retval EFI_SUCCESS The request succeeded. The requested data was
1783 extracted and placed in the newly allocated
1785 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
1786 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1787 @retval EFI_NOT_FOUND Target for the specified routing data was not
1794 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
1795 IN CONST EFI_STRING Configuration
,
1796 IN CONST EFI_GUID
*Guid
,
1797 IN CONST EFI_STRING Name
,
1798 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1799 IN CONST UINT16
*AltCfgId
,
1800 OUT EFI_STRING
*AltCfgResp
1804 EFI_STRING StringPtr
;
1805 EFI_STRING HdrStart
;
1812 EFI_STRING AltIdStr
;
1819 // For size reduction, please define PcdSupportFullConfigRoutingProtocol
1820 // as FALSE. But this renders the system to not 100% compliant with
1821 // UEFI 2.1. Use this with caution.
1823 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol
)) {
1824 return EFI_UNSUPPORTED
;
1838 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
1839 return EFI_INVALID_PARAMETER
;
1842 StringPtr
= Configuration
;
1843 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1844 return EFI_INVALID_PARAMETER
;
1848 // Generate the sub string for later matching.
1850 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
1853 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1854 (VOID
*) DevicePath
,
1858 if (AltCfgId
!= NULL
) {
1859 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
1862 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1864 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1867 while (*StringPtr
!= 0) {
1869 // Try to match the GUID
1872 TmpPtr
= StrStr (StringPtr
, GuidStr
);
1873 if (TmpPtr
== NULL
) {
1874 Status
= EFI_NOT_FOUND
;
1880 // Jump to <NameHdr>
1883 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
1885 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
1886 if (StringPtr
== NULL
) {
1887 Status
= EFI_NOT_FOUND
;
1895 // Try to match the NAME
1897 if (GuidFlag
&& !NameFlag
) {
1898 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
1902 // Jump to <PathHdr>
1905 StringPtr
+= StrLen (NameStr
);
1907 StringPtr
= StrStr (StringPtr
, L
"PATH=");
1908 if (StringPtr
== NULL
) {
1909 Status
= EFI_NOT_FOUND
;
1918 // Try to match the DevicePath
1920 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
1921 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
1926 // Jump to '&' before <DescHdr> or <ConfigBody>
1928 if (DevicePath
!= NULL
) {
1929 StringPtr
+= StrLen (PathStr
);
1931 StringPtr
= StrStr (StringPtr
, L
"&");
1932 if (StringPtr
== NULL
) {
1933 Status
= EFI_NOT_FOUND
;
1938 HdrEnd
= ++StringPtr
;
1943 // Try to match the AltCfgId
1945 if (GuidFlag
&& NameFlag
&& PathFlag
) {
1946 if (AltCfgId
== NULL
) {
1948 // Return Current Setting when AltCfgId is NULL.
1950 Status
= OutputConfigBody (StringPtr
, &Result
);
1954 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
1956 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
1961 Status
= OutputConfigBody (StringPtr
, &Result
);
1967 Status
= EFI_NOT_FOUND
;
1971 if (!EFI_ERROR (Status
)) {
1973 // Copy the <ConfigHdr> and <ConfigBody>
1975 Length
= HdrEnd
- HdrStart
+ StrLen (Result
);
1976 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1977 if (*AltCfgResp
== NULL
) {
1978 Status
= EFI_OUT_OF_RESOURCES
;
1980 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
1981 StrCat (*AltCfgResp
, Result
);
1982 Status
= EFI_SUCCESS
;
1986 SafeFreePool (GuidStr
);
1987 SafeFreePool (NameStr
);
1988 SafeFreePool (PathStr
);
1989 SafeFreePool (AltIdStr
);
1990 SafeFreePool (Result
);