]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
To improve backward compatibility, add gEfiPrint2ProtocolGuid and rename gEfiPrintPro...
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigRouting.c
CommitLineData
93e3992d 1/** @file\r
2\r
36fe40c2 3Copyright (c) 2007 - 2008, Intel Corporation\r
93e3992d 4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 ConfigRouting.c\r
15\r
16Abstract:\r
17\r
18 Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
19\r
20Revision History\r
21\r
22\r
23**/\r
24\r
25\r
26#include "HiiDatabase.h"\r
27\r
93e3992d 28/**\r
29 Calculate the number of Unicode characters of the incoming Configuration string,\r
30 not including NULL terminator.\r
31\r
e90b081a 32 This is a internal function.\r
33\r
93e3992d 34 @param String String in <MultiConfigRequest> or\r
35 <MultiConfigResp> format.\r
36\r
37 @return The number of Unicode characters.\r
38\r
39**/\r
93e3992d 40UINTN\r
41CalculateConfigStringLen (\r
42 IN EFI_STRING String\r
43 )\r
44{\r
45 UINTN Length;\r
46\r
47 //\r
48 // "GUID=" should be the first element of incoming string.\r
49 //\r
50 ASSERT (String != NULL);\r
51 ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);\r
52\r
53 Length = StrLen (L"GUID=");\r
54 String += Length;\r
55\r
56 //\r
57 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".\r
58 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.\r
59 //\r
60 while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) {\r
61 Length++;\r
62 String++;\r
63 }\r
64\r
65 return Length;\r
66}\r
67\r
68\r
69/**\r
70 Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
71 from <PathHdr> of <ConfigHdr>.\r
72\r
e90b081a 73 This is a internal function.\r
74\r
93e3992d 75 @param String UEFI configuration string\r
76 @param DevicePath binary of a UEFI device path.\r
77\r
78 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
79 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
80 @retval EFI_SUCCESS The device path is retrieved and translated to\r
81 binary format.\r
82\r
83**/\r
93e3992d 84EFI_STATUS\r
85GetDevicePath (\r
86 IN EFI_STRING String,\r
87 OUT UINT8 **DevicePath\r
88 )\r
89{\r
90 UINTN Length;\r
91 EFI_STRING PathHdr;\r
92 EFI_STRING DevicePathString;\r
93\r
94 if (String == NULL || DevicePath == NULL) {\r
95 return EFI_INVALID_PARAMETER;\r
96 }\r
97\r
98 //\r
99 // Find the 'PATH=' of <PathHdr> and skip it.\r
100 //\r
101 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
102 if (*String == 0) {\r
103 return EFI_INVALID_PARAMETER;\r
104 }\r
105\r
106 String += StrLen (L"PATH=");\r
107 PathHdr = String;\r
108\r
109 //\r
110 // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
111 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
112 // of UEFI device path.\r
113 //\r
114 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
115 DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
116 if (DevicePathString == NULL) {\r
117 return EFI_OUT_OF_RESOURCES;\r
118 }\r
119 StrnCpy (DevicePathString, PathHdr, Length);\r
120 *(DevicePathString + Length) = 0;\r
121\r
122 //\r
123 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
124 // as the device path resides in RAM memory.\r
125 // Translate the data into binary.\r
93e3992d 126 //\r
127 Length /= 2;\r
128 *DevicePath = (UINT8 *) AllocateZeroPool (Length);\r
129 if (*DevicePath == NULL) {\r
130 SafeFreePool (DevicePathString);\r
131 return EFI_OUT_OF_RESOURCES;\r
132 }\r
133\r
813acf3a 134 HexStringToBuffer (*DevicePath, &Length, DevicePathString);\r
93e3992d 135\r
136 SafeFreePool (DevicePathString);\r
137\r
138 return EFI_SUCCESS;\r
139\r
140}\r
141\r
142\r
143/**\r
144 Extract Storage from all Form Packages in current hii database.\r
145\r
e90b081a 146 This is a internal function.\r
147\r
93e3992d 148 @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.\r
149 @param StorageListHead Storage link List head.\r
150\r
151 @retval EFI_NOT_FOUND There is no form package in current hii database.\r
152 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
153 @retval EFI_SUCCESS All existing storage is exported.\r
154\r
155**/\r
93e3992d 156EFI_STATUS\r
157ExportAllStorage (\r
158 IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,\r
159 IN OUT LIST_ENTRY *StorageListHead\r
160)\r
161{\r
162 EFI_STATUS Status;\r
163 UINTN BufferSize;\r
164 UINTN HandleCount;\r
165 EFI_HII_HANDLE *HandleBuffer;\r
166 UINTN Index;\r
167 UINTN Index2;\r
168 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
169 EFI_HII_PACKAGE_HEADER *Package;\r
170 UINT8 *OpCodeData;\r
171 UINT8 Operand;\r
172 UINT32 Offset;\r
173 HII_FORMSET_STORAGE *Storage;\r
174 EFI_HII_HANDLE HiiHandle;\r
175 EFI_HANDLE DriverHandle;\r
176 CHAR8 *AsciiString;\r
177 UINT32 PackageListLength;\r
178 EFI_HII_PACKAGE_HEADER PackageHeader;\r
179\r
180 //\r
181 // Find the package list which contains Form package.\r
182 //\r
183 BufferSize = 0;\r
184 HandleBuffer = NULL;\r
185 Status = HiiListPackageLists (\r
186 HiiDatabase,\r
187 EFI_HII_PACKAGE_FORM,\r
188 NULL,\r
189 &BufferSize,\r
190 HandleBuffer\r
191 );\r
192 if (Status == EFI_BUFFER_TOO_SMALL) {\r
193 HandleBuffer = AllocateZeroPool (BufferSize);\r
194 ASSERT (HandleBuffer != NULL);\r
195\r
196 Status = HiiListPackageLists (\r
197 HiiDatabase,\r
198 EFI_HII_PACKAGE_FORM,\r
199 NULL,\r
200 &BufferSize,\r
201 HandleBuffer\r
202 );\r
203 }\r
204 if (EFI_ERROR (Status)) {\r
205 SafeFreePool (HandleBuffer);\r
206 return Status;\r
207 }\r
208\r
209 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
210 for (Index = 0; Index < HandleCount; Index++) {\r
211 HiiHandle = HandleBuffer[Index];\r
212\r
213 BufferSize = 0;\r
214 HiiPackageList = NULL;\r
215 Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
216 if (Status == EFI_BUFFER_TOO_SMALL) {\r
217 HiiPackageList = AllocateZeroPool (BufferSize);\r
218 ASSERT (HiiPackageList != NULL);\r
219 Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
220 }\r
221 if (EFI_ERROR (Status)) {\r
222 SafeFreePool (HandleBuffer);\r
223 SafeFreePool (HiiPackageList);\r
224 return Status;\r
225 }\r
226\r
227 //\r
228 // Get Form package from this HII package List\r
229 //\r
230 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
231 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
232 Package = NULL;\r
233 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
234\r
235 while (Offset < PackageListLength) {\r
236 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
237 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
238 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
239 break;\r
240 }\r
241 Offset += PackageHeader.Length;\r
242 }\r
243 if (Offset >= PackageListLength) {\r
244 //\r
245 // Error here: No Form package found in this Package List\r
246 //\r
247 ASSERT (FALSE);\r
248 }\r
249\r
250 //\r
251 // Search Storage definition in this Form package\r
252 //\r
253 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
254 while (Offset < PackageHeader.Length) {\r
255 OpCodeData = ((UINT8 *) Package) + Offset;\r
256 Offset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
257\r
258 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
259\r
260 if ((Operand == EFI_IFR_VARSTORE_OP) ||\r
261 (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||\r
262 (Operand == EFI_IFR_VARSTORE_EFI_OP)) {\r
263\r
264 Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));\r
265 ASSERT (Storage != NULL);\r
266 InsertTailList (StorageListHead, &Storage->Entry);\r
267\r
268 Storage->Signature = HII_FORMSET_STORAGE_SIGNATURE;\r
269 Storage->HiiHandle = HiiHandle;\r
270\r
271 Status = HiiGetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle);\r
272 if (EFI_ERROR (Status)) {\r
273 SafeFreePool (HandleBuffer);\r
274 SafeFreePool (HiiPackageList);\r
275 SafeFreePool (Storage);\r
276 return Status;\r
277 }\r
278 Storage->DriverHandle = DriverHandle;\r
279\r
280 if (Operand == EFI_IFR_VARSTORE_OP) {\r
281 Storage->Type = EFI_HII_VARSTORE_BUFFER;\r
282\r
283 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
284 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));\r
285\r
286 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
287 Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);\r
288 ASSERT (Storage->Name != NULL);\r
289 for (Index2 = 0; AsciiString[Index2] != 0; Index2++) {\r
290 Storage->Name[Index2] = (CHAR16) AsciiString[Index2];\r
291 }\r
292 //\r
293 // Append '\0' to the end of the unicode string.\r
294 //\r
295 Storage->Name[Index2] = 0;\r
296 } else if (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
297 Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
298\r
299 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
300 } else if (Operand == EFI_IFR_VARSTORE_EFI_OP) {\r
301 Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;\r
302\r
303 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
304 }\r
305 }\r
306 }\r
307\r
308 SafeFreePool (HiiPackageList);\r
309 }\r
310\r
311 SafeFreePool (HandleBuffer);\r
312\r
313 return EFI_SUCCESS;\r
314}\r
315\r
316\r
317/**\r
318 Generate a sub string then output it.\r
319\r
e90b081a 320 This is a internal function.\r
321\r
93e3992d 322 @param String A constant string which is the prefix of the to be\r
323 generated string, e.g. GUID=\r
324 @param BufferLen The length of the Buffer in bytes.\r
813acf3a 325 @param Buffer Points to a buffer which will be converted to be the \r
326 content of the generated string.\r
327 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in \r
328 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
329 if 3, the buffer contains other data.\r
93e3992d 330 @param SubStr Points to the output string. It's caller's\r
331 responsibility to free this buffer.\r
332\r
333\r
334**/\r
93e3992d 335VOID\r
336GenerateSubStr (\r
337 IN CONST EFI_STRING String,\r
338 IN UINTN BufferLen,\r
813acf3a 339 IN VOID *Buffer,\r
340 IN UINT8 Flag,\r
93e3992d 341 OUT EFI_STRING *SubStr\r
342 )\r
343{\r
344 UINTN Length;\r
345 EFI_STRING Str;\r
346 EFI_STATUS Status;\r
813acf3a 347 EFI_STRING StringHeader;\r
93e3992d 348\r
349 ASSERT (String != NULL && SubStr != NULL);\r
350\r
351 if (Buffer == NULL) {\r
352 *SubStr = AllocateCopyPool (StrSize (String), String);\r
353 ASSERT (*SubStr != NULL);\r
354 return ;\r
355 }\r
356\r
813acf3a 357 Length = StrLen (String) + BufferLen * 2 + 1 + 1;\r
93e3992d 358 Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
359 ASSERT (Str != NULL);\r
360\r
361 StrCpy (Str, String);\r
362 Length = (BufferLen * 2 + 1) * sizeof (CHAR16);\r
363\r
813acf3a 364 Status = EFI_SUCCESS;\r
365 StringHeader = Str + StrLen (String);\r
366\r
367 switch (Flag) {\r
368 case 1:\r
369 Status = BufferToHexString (StringHeader, (UINT8 *) Buffer, BufferLen);\r
370 break;\r
371 case 2:\r
372 Status = UnicodeToConfigString (StringHeader, &Length, (CHAR16 *) Buffer);\r
373 break;\r
374 case 3:\r
375 Status = BufToHexString (StringHeader, &Length, (UINT8 *) Buffer, BufferLen);\r
376 //\r
377 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
378 //\r
379 ToLower (StringHeader);\r
380 break;\r
381 default:\r
382 break;\r
383 }\r
93e3992d 384\r
385 ASSERT_EFI_ERROR (Status);\r
386 StrCat (Str, L"&");\r
387\r
388 *SubStr = Str;\r
389}\r
390\r
391\r
392/**\r
393 Retrieve the <ConfigBody> from String then output it.\r
394\r
e90b081a 395 This is a internal function.\r
396\r
93e3992d 397 @param String A sub string of a configuration string in\r
398 <MultiConfigAltResp> format.\r
399 @param ConfigBody Points to the output string. It's caller's\r
400 responsibility to free this buffer.\r
401\r
402 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.\r
403 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.\r
404 @retval EFI_SUCCESS All existing storage is exported.\r
405\r
406**/\r
93e3992d 407EFI_STATUS\r
408OutputConfigBody (\r
409 IN EFI_STRING String,\r
410 OUT EFI_STRING *ConfigBody\r
411 )\r
412{\r
413 EFI_STRING TmpPtr;\r
414 EFI_STRING Result;\r
415 UINTN Length;\r
416\r
417 if (String == NULL || ConfigBody == NULL) {\r
418 return EFI_INVALID_PARAMETER;\r
419 }\r
420\r
421 TmpPtr = StrStr (String, L"GUID=");\r
422 if (TmpPtr == NULL) {\r
423 //\r
424 // It is the last <ConfigResp> of the incoming configuration string.\r
425 //\r
426 Result = AllocateCopyPool (StrSize (String), String);\r
427 if (Result == NULL) {\r
428 return EFI_OUT_OF_RESOURCES;\r
429 } else {\r
430 *ConfigBody = Result;\r
431 return EFI_SUCCESS;\r
432 }\r
433 }\r
434\r
435 Length = TmpPtr - String;\r
436 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
437 if (Result == NULL) {\r
438 return EFI_OUT_OF_RESOURCES;\r
439 }\r
440\r
441 *(Result + Length - 1) = 0;\r
442 *ConfigBody = Result;\r
443 return EFI_SUCCESS;\r
444\r
445}\r
446\r
447\r
e90b081a 448/**\r
449 Adjusts the size of a previously allocated buffer.\r
450\r
451\r
452 @param OldPool A pointer to the buffer whose size is being adjusted.\r
453 @param OldSize The size of the current buffer.\r
454 @param NewSize The size of the new buffer.\r
455\r
456 @return The new buffer allocated.\r
457\r
458**/\r
93e3992d 459VOID *\r
460ReallocatePool (\r
461 IN VOID *OldPool,\r
462 IN UINTN OldSize,\r
463 IN UINTN NewSize\r
464 )\r
93e3992d 465{\r
466 VOID *NewPool;\r
467\r
468 NewPool = NULL;\r
e90b081a 469 if (NewSize != 0) {\r
93e3992d 470 NewPool = AllocateZeroPool (NewSize);\r
471 }\r
472\r
e90b081a 473 if (OldPool != NULL) {\r
474 if (NewPool != NULL) {\r
93e3992d 475 CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
476 }\r
477\r
478 gBS->FreePool (OldPool);\r
479 }\r
480\r
481 return NewPool;\r
482}\r
483\r
484\r
485/**\r
486 Append a string to a multi-string format.\r
487\r
e90b081a 488 This is a internal function.\r
489\r
93e3992d 490 @param MultiString String in <MultiConfigRequest>,\r
491 <MultiConfigAltResp>, or <MultiConfigResp>. On\r
492 input, the buffer length of this string is\r
493 MAX_STRING_LENGTH. On output, the buffer length\r
494 might be updated.\r
495 @param AppendString NULL-terminated Unicode string.\r
496\r
497 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
498 @retval EFI_SUCCESS AppendString is append to the end of MultiString\r
499\r
500**/\r
93e3992d 501EFI_STATUS\r
502AppendToMultiString (\r
503 IN OUT EFI_STRING *MultiString,\r
504 IN EFI_STRING AppendString\r
505 )\r
506{\r
507 UINTN AppendStringSize;\r
508 UINTN MultiStringSize;\r
509\r
510 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
511 return EFI_INVALID_PARAMETER;\r
512 }\r
513\r
514 AppendStringSize = StrSize (AppendString);\r
515 MultiStringSize = StrSize (*MultiString);\r
516\r
517 //\r
518 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
519 //\r
520 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
521 MultiStringSize > MAX_STRING_LENGTH) {\r
522 *MultiString = (EFI_STRING) ReallocatePool (\r
523 (VOID *) (*MultiString),\r
524 MultiStringSize,\r
525 MultiStringSize + AppendStringSize\r
526 );\r
527 }\r
528\r
529 //\r
530 // Append the incoming string\r
531 //\r
532 StrCat (*MultiString, AppendString);\r
533\r
534 return EFI_SUCCESS;\r
535}\r
536\r
537\r
538/**\r
539 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
540 or WIDTH or VALUE.\r
541 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
542\r
e90b081a 543 This is a internal function.\r
544\r
93e3992d 545 @param StringPtr String in <BlockConfig> format and points to the\r
546 first character of <Number>.\r
547 @param Number The output value. Caller takes the responsibility\r
548 to free memory.\r
549 @param Len Length of the <Number>, in characters.\r
550\r
551 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
552 structures.\r
553 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
554 successfully.\r
555\r
556**/\r
93e3992d 557EFI_STATUS\r
558GetValueOfNumber (\r
559 IN EFI_STRING StringPtr,\r
560 OUT UINT8 **Number,\r
561 OUT UINTN *Len\r
562 )\r
563{\r
564 EFI_STRING TmpPtr;\r
565 UINTN Length;\r
566 EFI_STRING Str;\r
567 UINT8 *Buf;\r
568 EFI_STATUS Status;\r
569\r
570 ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);\r
571 ASSERT (*StringPtr != 0);\r
572\r
573 Buf = NULL;\r
574\r
575 TmpPtr = StringPtr;\r
576 while (*StringPtr != 0 && *StringPtr != L'&') {\r
577 StringPtr++;\r
578 }\r
579 *Len = StringPtr - TmpPtr;\r
580 Length = *Len + 1;\r
581\r
582 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING));\r
583 if (Str == NULL) {\r
584 Status = EFI_OUT_OF_RESOURCES;\r
585 goto Exit;\r
586 }\r
587 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
588 *(Str + *Len) = 0;\r
589\r
590 Length = (Length + 1) / 2;\r
591 Buf = (UINT8 *) AllocateZeroPool (Length);\r
592 if (Buf == NULL) {\r
593 Status = EFI_OUT_OF_RESOURCES;\r
594 goto Exit;\r
595 }\r
596\r
36fe40c2 597 Status = HexStringToBuf (Buf, &Length, Str, NULL);\r
93e3992d 598 if (EFI_ERROR (Status)) {\r
599 goto Exit;\r
600 }\r
601\r
602 *Number = Buf;\r
603 Status = EFI_SUCCESS;\r
604\r
605Exit:\r
606 SafeFreePool (Str);\r
607 return Status;\r
608}\r
609\r
610\r
611/**\r
612 This function allows a caller to extract the current configuration\r
613 for one or more named elements from one or more drivers.\r
614\r
615 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
616 instance.\r
617 @param Request A null-terminated Unicode string in\r
618 <MultiConfigRequest> format.\r
619 @param Progress On return, points to a character in the Request\r
620 string. Points to the string's null terminator if\r
621 request was successful. Points to the most recent\r
622 & before the first failing name / value pair (or\r
623 the beginning of the string if the failure is in\r
624 the first name / value pair) if the request was\r
625 not successful.\r
626 @param Results Null-terminated Unicode string in\r
627 <MultiConfigAltResp> format which has all values\r
628 filled in for the names in the Request string.\r
629 String to be allocated by the called function.\r
630\r
631 @retval EFI_SUCCESS The Results string is filled with the values\r
632 corresponding to all requested names.\r
633 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
634 results that must be stored awaiting possible\r
635 future protocols.\r
636 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
637 Progress set to the "G" in "GUID" of the routing\r
638 header that doesn't match. Note: There is no\r
639 requirement that all routing data be validated\r
640 before any configuration extraction.\r
641 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
642 parameter would result in this type of error. The\r
643 Progress parameter is set to NULL.\r
644 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
645 before the error or the beginning of the string.\r
646 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
647 name in question.\r
648\r
649**/\r
650EFI_STATUS\r
651EFIAPI\r
652HiiConfigRoutingExtractConfig (\r
653 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
654 IN CONST EFI_STRING Request,\r
655 OUT EFI_STRING *Progress,\r
656 OUT EFI_STRING *Results\r
657 )\r
658{\r
93e3992d 659 HII_DATABASE_PRIVATE_DATA *Private;\r
660 EFI_STRING StringPtr;\r
661 EFI_STRING ConfigRequest;\r
662 UINTN Length;\r
663 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
664 EFI_STATUS Status;\r
665 LIST_ENTRY *Link;\r
666 HII_DATABASE_RECORD *Database;\r
667 UINT8 *CurrentDevicePath;\r
668 EFI_HANDLE DriverHandle;\r
669 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
670 EFI_STRING AccessProgress;\r
671 EFI_STRING AccessResults;\r
672 UINTN RemainSize;\r
673 EFI_STRING TmpPtr;\r
674\r
e94358a3 675 //\r
676 // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
677 // as FALSE. But this renders the system to not 100% compliant with\r
678 // UEFI 2.1. Use this with caution.\r
679 //\r
680 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
681 return EFI_UNSUPPORTED;\r
682 }\r
683\r
93e3992d 684 if (This == NULL || Progress == NULL || Results == NULL) {\r
685 return EFI_INVALID_PARAMETER;\r
686 }\r
687\r
688 if (Request == NULL) {\r
689 *Progress = NULL;\r
690 return EFI_INVALID_PARAMETER;\r
691 }\r
692\r
693 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
694 StringPtr = Request;\r
695 *Progress = StringPtr;\r
696\r
697 //\r
698 // The first element of <MultiConfigRequest> should be\r
699 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
700 //\r
701 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
702 return EFI_INVALID_PARAMETER;\r
703 }\r
704\r
705 //\r
706 // Allocate a fix length of memory to store Results. Reallocate memory for\r
707 // Results if this fix length is insufficient.\r
708 //\r
709 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
710 if (*Results == NULL) {\r
711 return EFI_OUT_OF_RESOURCES;\r
712 }\r
713\r
714 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
715 //\r
716 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
717 // or most recent & before the error.\r
718 //\r
719 if (StringPtr == Request) {\r
720 *Progress = StringPtr;\r
721 } else {\r
722 *Progress = StringPtr - 1;\r
723 }\r
724\r
725 //\r
726 // Process each <ConfigRequest> of <MultiConfigRequest>\r
727 //\r
728 Length = CalculateConfigStringLen (StringPtr);\r
729 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
730 if (ConfigRequest == NULL) {\r
731 return EFI_OUT_OF_RESOURCES;\r
732 }\r
733 *(ConfigRequest + Length) = 0;\r
734\r
735 //\r
736 // Get the UEFI device path\r
737 //\r
738 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
739 if (EFI_ERROR (Status)) {\r
740 SafeFreePool (ConfigRequest);\r
741 return Status;\r
742 }\r
743\r
744 //\r
745 // Find driver which matches the routing data.\r
746 //\r
747 DriverHandle = NULL;\r
748 for (Link = Private->DatabaseList.ForwardLink;\r
749 Link != &Private->DatabaseList;\r
750 Link = Link->ForwardLink\r
751 ) {\r
752 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
753 CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
754 if (CurrentDevicePath != NULL) {\r
755 if (CompareMem (\r
756 DevicePath,\r
757 CurrentDevicePath,\r
758 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
759 ) == 0) {\r
760 DriverHandle = Database->DriverHandle;\r
761 break;\r
762 }\r
763 }\r
764 }\r
765\r
766 SafeFreePool (DevicePath);\r
767\r
768 if (DriverHandle == NULL) {\r
769 //\r
770 // Routing data does not match any known driver.\r
771 // Set Progress to the 'G' in "GUID" of the routing header.\r
772 //\r
773 *Progress = StringPtr;\r
774 SafeFreePool (ConfigRequest);\r
775 return EFI_NOT_FOUND;\r
776 }\r
777\r
778 //\r
779 // Call corresponding ConfigAccess protocol to extract settings\r
780 //\r
781 Status = gBS->HandleProtocol (\r
782 DriverHandle,\r
783 &gEfiHiiConfigAccessProtocolGuid,\r
784 (VOID **) &ConfigAccess\r
785 );\r
786 ASSERT_EFI_ERROR (Status);\r
787\r
788 Status = ConfigAccess->ExtractConfig (\r
789 ConfigAccess,\r
790 ConfigRequest,\r
791 &AccessProgress,\r
792 &AccessResults\r
793 );\r
794 if (EFI_ERROR (Status)) {\r
795 //\r
796 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
797 // Map it to the progress on <MultiConfigRequest> then return it.\r
798 //\r
799 RemainSize = StrSize (AccessProgress);\r
800 for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
801 *Progress = TmpPtr;\r
802\r
803 SafeFreePool (ConfigRequest);\r
804 return Status;\r
805 }\r
806\r
807 //\r
808 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
809 //\r
810 ASSERT (*AccessProgress == 0);\r
811 Status = AppendToMultiString (Results, AccessResults);\r
812 ASSERT_EFI_ERROR (Status);\r
813 SafeFreePool (AccessResults);\r
814 AccessResults = NULL;\r
815 SafeFreePool (ConfigRequest);\r
816 ConfigRequest = NULL;\r
817\r
818 //\r
819 // Go to next <ConfigRequest> (skip '&').\r
820 //\r
821 StringPtr += Length;\r
822 if (*StringPtr == 0) {\r
823 *Progress = StringPtr;\r
824 break;\r
825 }\r
826\r
827 StringPtr++;\r
828\r
829 }\r
830\r
831 return EFI_SUCCESS;\r
93e3992d 832\r
833}\r
834\r
835\r
836/**\r
837 This function allows the caller to request the current configuration for the\r
838 entirety of the current HII database and returns the data in a\r
839 null-terminated Unicode string.\r
840\r
841 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
842 instance.\r
843 @param Results Null-terminated Unicode string in\r
844 <MultiConfigAltResp> format which has all values\r
845 filled in for the names in the Request string.\r
846 String to be allocated by the called function.\r
847 De-allocation is up to the caller.\r
848\r
849 @retval EFI_SUCCESS The Results string is filled with the values\r
850 corresponding to all requested names.\r
851 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
852 results that must be stored awaiting possible\r
853 future protocols.\r
854 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
855 parameter would result in this type of error.\r
856\r
857**/\r
858EFI_STATUS\r
859EFIAPI\r
860HiiConfigRoutingExportConfig (\r
861 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
862 OUT EFI_STRING *Results\r
863 )\r
864{\r
93e3992d 865 EFI_STATUS Status;\r
866 HII_DATABASE_PRIVATE_DATA *Private;\r
867 LIST_ENTRY StorageListHdr;\r
868 HII_FORMSET_STORAGE *Storage;\r
869 LIST_ENTRY *Link;\r
870 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
871 UINTN Length;\r
872 EFI_STRING PathHdr;\r
873 UINTN PathHdrSize;\r
874 EFI_STRING ConfigRequest;\r
875 UINTN RequestSize;\r
876 EFI_STRING StringPtr;\r
877 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
878 EFI_STRING AccessProgress;\r
879 EFI_STRING AccessResults;\r
880 UINTN TmpSize;\r
881\r
e94358a3 882 //\r
883 // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
884 // as FALSE. But this renders the system to not 100% compliant with\r
885 // UEFI 2.1. Use this with caution.\r
886 //\r
887 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
888 return EFI_UNSUPPORTED;\r
889 }\r
890\r
93e3992d 891 if (This == NULL || Results == NULL) {\r
892 return EFI_INVALID_PARAMETER;\r
893 }\r
894\r
895 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
896\r
897 InitializeListHead (&StorageListHdr);\r
898\r
899 Status = ExportAllStorage (&Private->HiiDatabase, &StorageListHdr);\r
900 if (EFI_ERROR (Status)) {\r
901 return Status;\r
902 }\r
903\r
904 //\r
905 // Allocate a fix length of memory to store Results. Reallocate memory for\r
906 // Results if this fix length is insufficient.\r
907 //\r
908 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
909 if (*Results == NULL) {\r
910 return EFI_OUT_OF_RESOURCES;\r
911 }\r
912\r
913 //\r
914 // Parsing all formset storages.\r
915 //\r
916 for (Link = StorageListHdr.ForwardLink; Link != &StorageListHdr; Link = Link->ForwardLink) {\r
917 Storage = CR (Link, HII_FORMSET_STORAGE, Entry, HII_FORMSET_STORAGE_SIGNATURE);\r
918 //\r
919 // Find the corresponding device path instance\r
920 //\r
921 Status = gBS->HandleProtocol (\r
922 Storage->DriverHandle,\r
923 &gEfiDevicePathProtocolGuid,\r
924 (VOID **) &DevicePath\r
925 );\r
926 if (EFI_ERROR (Status)) {\r
927 return Status;\r
928 }\r
929 //\r
930 // Convert the device path binary to hex UNICODE %02x bytes in the same order\r
931 // as the device path resides in RAM memory.\r
932 //\r
933 Length = GetDevicePathSize (DevicePath);\r
934 PathHdrSize = (Length * 2 + 1) * sizeof (CHAR16);\r
935 PathHdr = (EFI_STRING) AllocateZeroPool (PathHdrSize);\r
936 if (PathHdr == NULL) {\r
937 return EFI_OUT_OF_RESOURCES;\r
938 }\r
813acf3a 939 Status = BufferToHexString (PathHdr, (UINT8 *) DevicePath, Length);\r
93e3992d 940 ASSERT_EFI_ERROR (Status);\r
941\r
942 //\r
943 // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.\r
944 // It means extract all possible configurations from this specific driver.\r
945 //\r
946 TmpSize = StrLen (L"GUID=&NAME=&PATH=");\r
813acf3a 947 RequestSize = (TmpSize + 32 + StrLen (Storage->Name) * 4)\r
93e3992d 948 * sizeof (CHAR16) + PathHdrSize;\r
949 ConfigRequest = (EFI_STRING) AllocateZeroPool (RequestSize);\r
950 if (ConfigRequest == NULL) {\r
951 SafeFreePool (PathHdr);\r
952 return EFI_OUT_OF_RESOURCES;\r
953 }\r
954\r
955 //\r
956 // Add <GuidHdr>\r
957 // <GuidHdr> ::= 'GUID='<Guid>\r
813acf3a 958 // Convert <Guid> in the same order as it resides in RAM memory.\r
93e3992d 959 //\r
960 StringPtr = ConfigRequest;\r
961 StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID="));\r
962 StringPtr += StrLen (L"GUID=");\r
963\r
813acf3a 964 Status = BufferToHexString (StringPtr, (UINT8 *) (&Storage->Guid), sizeof (EFI_GUID));\r
93e3992d 965 ASSERT_EFI_ERROR (Status);\r
813acf3a 966 \r
967 StringPtr += 32;\r
93e3992d 968 ASSERT (*StringPtr == 0);\r
969 *StringPtr = L'&';\r
970 StringPtr++;\r
971\r
972 //\r
973 // Add <NameHdr>\r
974 // <NameHdr> ::= 'NAME='<String>\r
975 //\r
976 StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME="));\r
977 StringPtr += StrLen (L"NAME=");\r
813acf3a 978\r
979 Length = (StrLen (Storage->Name) * 4 + 1) * sizeof (CHAR16);\r
980 Status = UnicodeToConfigString (StringPtr, &Length, Storage->Name);\r
981 ASSERT_EFI_ERROR (Status);\r
982 StringPtr += StrLen (Storage->Name) * 4;\r
983 \r
93e3992d 984 *StringPtr = L'&';\r
985 StringPtr++;\r
986\r
987 //\r
988 // Add <PathHdr>\r
989 // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>\r
990 //\r
991 StrnCpy (StringPtr, L"PATH=", StrLen (L"PATH="));\r
992 StringPtr += StrLen (L"PATH=");\r
993 StrCpy (StringPtr, PathHdr);\r
994\r
995 SafeFreePool (PathHdr);\r
996 PathHdr = NULL;\r
997\r
998 //\r
999 // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the\r
1000 // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>\r
1001 // is required to call ConfigAccess.ExtractConfig().\r
1002 //\r
1003 // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess\r
1004 // to handle such kind of "ConfigRequest". It is not supported till now.\r
1005 //\r
1006 // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()\r
1007 // will be updated as soon as the decision is made.\r
1008\r
1009 //\r
1010 // Route the request to corresponding ConfigAccess protocol to extract settings.\r
1011 //\r
1012 Status = gBS->HandleProtocol (\r
1013 Storage->DriverHandle,\r
1014 &gEfiHiiConfigAccessProtocolGuid,\r
1015 (VOID **) &ConfigAccess\r
1016 );\r
1017 ASSERT_EFI_ERROR (Status);\r
1018\r
1019 Status = ConfigAccess->ExtractConfig (\r
1020 ConfigAccess,\r
1021 ConfigRequest,\r
1022 &AccessProgress,\r
1023 &AccessResults\r
1024 );\r
1025 if (EFI_ERROR (Status)) {\r
1026 SafeFreePool (ConfigRequest);\r
1027 SafeFreePool (AccessResults);\r
1028 return EFI_INVALID_PARAMETER;\r
1029 }\r
1030\r
1031 //\r
1032 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
1033 //\r
1034 ASSERT (*AccessProgress == 0);\r
1035 Status = AppendToMultiString (Results, AccessResults);\r
1036 ASSERT_EFI_ERROR (Status);\r
1037 SafeFreePool (AccessResults);\r
1038 AccessResults = NULL;\r
1039 SafeFreePool (ConfigRequest);\r
1040 ConfigRequest = NULL;\r
1041\r
1042 }\r
1043\r
1044 //\r
1045 // Free the exported storage resource\r
1046 //\r
1047 while (!IsListEmpty (&StorageListHdr)) {\r
1048 Storage = CR (\r
1049 StorageListHdr.ForwardLink,\r
1050 HII_FORMSET_STORAGE,\r
1051 Entry,\r
1052 HII_FORMSET_STORAGE_SIGNATURE\r
1053 );\r
1054 RemoveEntryList (&Storage->Entry);\r
1055 SafeFreePool (Storage->Name);\r
1056 SafeFreePool (Storage);\r
1057 }\r
1058\r
1059 return EFI_SUCCESS;\r
93e3992d 1060}\r
1061\r
1062\r
1063/**\r
1064 This function processes the results of processing forms and routes it to the\r
1065 appropriate handlers or storage.\r
1066\r
1067 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1068 instance.\r
1069 @param Configuration A null-terminated Unicode string in\r
1070 <MulltiConfigResp> format.\r
1071 @param Progress A pointer to a string filled in with the offset of\r
1072 the most recent & before the first failing name /\r
1073 value pair (or the beginning of the string if the\r
1074 failure is in the first name / value pair) or the\r
1075 terminating NULL if all was successful.\r
1076\r
1077 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
1078 distribution.\r
1079 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
1080 results that must be stored awaiting possible\r
1081 future protocols.\r
1082 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
1083 would result in this type of error.\r
1084 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
1085 found.\r
1086\r
1087**/\r
1088EFI_STATUS\r
1089EFIAPI\r
813acf3a 1090HiiConfigRoutingRouteConfig (\r
93e3992d 1091 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1092 IN CONST EFI_STRING Configuration,\r
1093 OUT EFI_STRING *Progress\r
1094 )\r
1095{\r
93e3992d 1096 HII_DATABASE_PRIVATE_DATA *Private;\r
1097 EFI_STRING StringPtr;\r
1098 EFI_STRING ConfigResp;\r
1099 UINTN Length;\r
1100 EFI_STATUS Status;\r
1101 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1102 LIST_ENTRY *Link;\r
1103 HII_DATABASE_RECORD *Database;\r
1104 UINT8 *CurrentDevicePath;\r
1105 EFI_HANDLE DriverHandle;\r
1106 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
1107 EFI_STRING AccessProgress;\r
1108 UINTN RemainSize;\r
1109 EFI_STRING TmpPtr;\r
1110\r
e94358a3 1111 //\r
1112 // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
1113 // as FALSE. But this renders the system to not 100% compliant with\r
1114 // UEFI 2.1. Use this with caution.\r
1115 //\r
1116 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
1117 return EFI_UNSUPPORTED;\r
1118 }\r
1119\r
93e3992d 1120 if (This == NULL || Progress == NULL) {\r
1121 return EFI_INVALID_PARAMETER;\r
1122 }\r
1123\r
1124 if (Configuration == NULL) {\r
1125 *Progress = NULL;\r
1126 return EFI_INVALID_PARAMETER;\r
1127 }\r
1128\r
1129 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
1130 StringPtr = Configuration;\r
1131 *Progress = StringPtr;\r
1132\r
1133 //\r
1134 // The first element of <MultiConfigResp> should be\r
1135 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
1136 //\r
1137 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1138 return EFI_INVALID_PARAMETER;\r
1139 }\r
1140\r
1141 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
1142 //\r
1143 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
1144 // or most recent & before the error.\r
1145 //\r
1146 if (StringPtr == Configuration) {\r
1147 *Progress = StringPtr;\r
1148 } else {\r
1149 *Progress = StringPtr - 1;\r
1150 }\r
1151\r
1152 //\r
1153 // Process each <ConfigResp> of <MultiConfigResp>\r
1154 //\r
1155 Length = CalculateConfigStringLen (StringPtr);\r
1156 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
1157 if (ConfigResp == NULL) {\r
1158 return EFI_OUT_OF_RESOURCES;\r
1159 }\r
1160 //\r
1161 // Append '\0' to the end of ConfigRequest\r
1162 //\r
1163 *(ConfigResp + Length) = 0;\r
1164\r
1165 //\r
1166 // Get the UEFI device path\r
1167 //\r
1168 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
1169 if (EFI_ERROR (Status)) {\r
1170 SafeFreePool (ConfigResp);\r
1171 return Status;\r
1172 }\r
1173\r
1174 //\r
1175 // Find driver which matches the routing data.\r
1176 //\r
1177 DriverHandle = NULL;\r
1178 for (Link = Private->DatabaseList.ForwardLink;\r
1179 Link != &Private->DatabaseList;\r
1180 Link = Link->ForwardLink\r
1181 ) {\r
1182 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
1183 CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
1184 if (CurrentDevicePath != NULL) {\r
1185 if (CompareMem (\r
1186 DevicePath,\r
1187 CurrentDevicePath,\r
1188 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
1189 ) == 0) {\r
1190 DriverHandle = Database->DriverHandle;\r
1191 break;\r
1192 }\r
1193 }\r
1194 }\r
1195\r
1196 SafeFreePool (DevicePath);\r
1197\r
1198 if (DriverHandle == NULL) {\r
1199 //\r
1200 // Routing data does not match any known driver.\r
1201 // Set Progress to the 'G' in "GUID" of the routing header.\r
1202 //\r
1203 *Progress = StringPtr;\r
1204 SafeFreePool (ConfigResp);\r
1205 return EFI_NOT_FOUND;\r
1206 }\r
1207\r
1208 //\r
1209 // Call corresponding ConfigAccess protocol to route settings\r
1210 //\r
1211 Status = gBS->HandleProtocol (\r
1212 DriverHandle,\r
1213 &gEfiHiiConfigAccessProtocolGuid,\r
1214 (VOID **) &ConfigAccess\r
1215 );\r
1216 ASSERT_EFI_ERROR (Status);\r
1217\r
1218 Status = ConfigAccess->RouteConfig (\r
1219 ConfigAccess,\r
1220 ConfigResp,\r
1221 &AccessProgress\r
1222 );\r
1223\r
1224 if (EFI_ERROR (Status)) {\r
1225 //\r
1226 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
1227 // Map it to the progress on <MultiConfigResp> then return it.\r
1228 //\r
1229 RemainSize = StrSize (AccessProgress);\r
1230 for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
1231 *Progress = TmpPtr;\r
1232\r
1233 SafeFreePool (ConfigResp);\r
1234 return Status;\r
1235 }\r
1236\r
1237 SafeFreePool (ConfigResp);\r
1238 ConfigResp = NULL;\r
1239\r
1240 //\r
1241 // Go to next <ConfigResp> (skip '&').\r
1242 //\r
1243 StringPtr += Length;\r
1244 if (*StringPtr == 0) {\r
1245 *Progress = StringPtr;\r
1246 break;\r
1247 }\r
1248\r
1249 StringPtr++;\r
1250\r
1251 }\r
1252\r
1253 return EFI_SUCCESS;\r
93e3992d 1254}\r
1255\r
1256\r
1257/**\r
1258 This helper function is to be called by drivers to map configuration data\r
1259 stored in byte array ("block") formats such as UEFI Variables into current\r
1260 configuration strings.\r
1261\r
1262 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1263 instance.\r
1264 @param ConfigRequest A null-terminated Unicode string in\r
1265 <ConfigRequest> format.\r
1266 @param Block Array of bytes defining the block's configuration.\r
1267 @param BlockSize Length in bytes of Block.\r
1268 @param Config Filled-in configuration string. String allocated\r
1269 by the function. Returned only if call is\r
1270 successful.\r
1271 @param Progress A pointer to a string filled in with the offset of\r
1272 the most recent & before the first failing\r
1273 name/value pair (or the beginning of the string if\r
1274 the failure is in the first name / value pair) or\r
1275 the terminating NULL if all was successful.\r
1276\r
1277 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
1278 terminator at the end of the ConfigRequest\r
1279 string.\r
1280 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
1281 points to the first character of ConfigRequest.\r
1282 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
1283 Block parameter would result in this type of\r
1284 error. Progress points to the first character of\r
1285 ConfigRequest.\r
1286 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
1287 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
1288 Block is left updated and Progress points at\r
1289 the "&" preceding the first non-<BlockName>.\r
1290\r
1291**/\r
1292EFI_STATUS\r
1293EFIAPI\r
1294HiiBlockToConfig (\r
1295 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1296 IN CONST EFI_STRING ConfigRequest,\r
1297 IN CONST UINT8 *Block,\r
1298 IN CONST UINTN BlockSize,\r
1299 OUT EFI_STRING *Config,\r
1300 OUT EFI_STRING *Progress\r
1301 )\r
1302{\r
1303 HII_DATABASE_PRIVATE_DATA *Private;\r
1304 EFI_STRING StringPtr;\r
1305 UINTN Length;\r
1306 EFI_STATUS Status;\r
1307 EFI_STRING TmpPtr;\r
1308 UINT8 *TmpBuffer;\r
1309 UINTN Offset;\r
1310 UINTN Width;\r
1311 UINT8 *Value;\r
1312 EFI_STRING ValueStr;\r
1313 EFI_STRING ConfigElement;\r
1314\r
1315 if (This == NULL || Progress == NULL || Config == NULL) {\r
1316 return EFI_INVALID_PARAMETER;\r
1317 }\r
1318\r
1319 if (Block == NULL || ConfigRequest == NULL) {\r
1320 *Progress = ConfigRequest;\r
1321 return EFI_INVALID_PARAMETER;\r
1322 }\r
1323\r
1324\r
1325 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
1326 ASSERT (Private != NULL);\r
1327\r
1328 StringPtr = ConfigRequest;\r
1329 ValueStr = NULL;\r
1330 Value = NULL;\r
1331 ConfigElement = NULL;\r
1332\r
1333 //\r
1334 // Allocate a fix length of memory to store Results. Reallocate memory for\r
1335 // Results if this fix length is insufficient.\r
1336 //\r
1337 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
1338 if (*Config == NULL) {\r
1339 return EFI_OUT_OF_RESOURCES;\r
1340 }\r
1341\r
1342 //\r
1343 // Jump <ConfigHdr>\r
1344 //\r
1345 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1346 *Progress = StringPtr;\r
1347 Status = EFI_INVALID_PARAMETER;\r
1348 goto Exit;\r
1349 }\r
1350 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
1351 StringPtr++;\r
1352 }\r
1353 if (*StringPtr == 0) {\r
1354 *Progress = StringPtr;\r
1355 Status = EFI_INVALID_PARAMETER;\r
1356 goto Exit;\r
1357 }\r
1358 while (*StringPtr++ != L'&');\r
1359\r
1360 //\r
1361 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
1362 //\r
1363 Length = StringPtr - ConfigRequest;\r
1364 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
1365\r
1366 //\r
1367 // Parse each <RequestElement> if exists\r
1368 // Only <BlockName> format is supported by this help function.\r
1369 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
1370 //\r
1371 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
1372 //\r
1373 // Back up the header of one <BlockName>\r
1374 //\r
1375 TmpPtr = StringPtr;\r
1376\r
1377 StringPtr += StrLen (L"OFFSET=");\r
1378 //\r
1379 // Get Offset\r
1380 //\r
1381 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1382 if (Status == EFI_OUT_OF_RESOURCES) {\r
1383 *Progress = ConfigRequest;\r
1384 goto Exit;\r
1385 }\r
1386 Offset = 0;\r
1387 CopyMem (\r
1388 &Offset,\r
1389 TmpBuffer,\r
1390 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1391 );\r
1392 SafeFreePool (TmpBuffer);\r
1393\r
1394 StringPtr += Length;\r
1395 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1396 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
1397 Status = EFI_INVALID_PARAMETER;\r
1398 goto Exit;\r
1399 }\r
1400 StringPtr += StrLen (L"&WIDTH=");\r
1401\r
1402 //\r
1403 // Get Width\r
1404 //\r
1405 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1406 if (Status == EFI_OUT_OF_RESOURCES) {\r
1407 *Progress = ConfigRequest;\r
1408 goto Exit;\r
1409 }\r
1410 Width = 0;\r
1411 CopyMem (\r
1412 &Width,\r
1413 TmpBuffer,\r
1414 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1415 );\r
1416 SafeFreePool (TmpBuffer);\r
1417\r
1418 StringPtr += Length;\r
1419 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1420 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
1421 Status = EFI_INVALID_PARAMETER;\r
1422 goto Exit;\r
1423 }\r
1424\r
1425 //\r
1426 // Calculate Value and convert it to hex string.\r
1427 //\r
1428 if (Offset + Width > BlockSize) {\r
1429 *Progress = StringPtr;\r
1430 Status = EFI_DEVICE_ERROR;\r
1431 goto Exit;\r
1432 }\r
1433\r
1434 Value = (UINT8 *) AllocateZeroPool (Width);\r
1435 if (Value == NULL) {\r
1436 *Progress = ConfigRequest;\r
1437 Status = EFI_OUT_OF_RESOURCES;\r
1438 goto Exit;\r
1439 }\r
1440\r
1441 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
1442\r
1443 Length = Width * 2 + 1;\r
1444 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
1445 if (ValueStr == NULL) {\r
1446 *Progress = ConfigRequest;\r
1447 Status = EFI_OUT_OF_RESOURCES;\r
1448 goto Exit;\r
1449 }\r
1450\r
36fe40c2 1451 Status = BufToHexString (ValueStr, &Length, Value, Width);\r
93e3992d 1452 ASSERT_EFI_ERROR (Status);\r
813acf3a 1453 ToLower (ValueStr);\r
1454\r
93e3992d 1455 SafeFreePool (Value);\r
1456 Value = NULL;\r
1457\r
1458 //\r
1459 // Build a ConfigElement\r
1460 //\r
1461 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
1462 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
1463 if (ConfigElement == NULL) {\r
1464 Status = EFI_OUT_OF_RESOURCES;\r
1465 goto Exit;\r
1466 }\r
1467 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
1468 if (*StringPtr == 0) {\r
1469 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
1470 }\r
1471 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
1472 StrCat (ConfigElement, L"VALUE=");\r
1473 StrCat (ConfigElement, ValueStr);\r
1474\r
1475 AppendToMultiString (Config, ConfigElement);\r
1476\r
1477 SafeFreePool (ConfigElement);\r
1478 SafeFreePool (ValueStr);\r
1479 ConfigElement = NULL;\r
1480 ValueStr = NULL;\r
1481\r
1482 //\r
1483 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
1484 //\r
1485 if (*StringPtr == 0) {\r
1486 break;\r
1487 }\r
1488 AppendToMultiString (Config, L"&");\r
1489 StringPtr++;\r
1490\r
1491 }\r
1492\r
1493 if (*StringPtr != 0) {\r
1494 *Progress = StringPtr - 1;\r
1495 Status = EFI_INVALID_PARAMETER;\r
1496 goto Exit;\r
1497 }\r
1498\r
1499 *Progress = StringPtr;\r
1500 return EFI_SUCCESS;\r
1501\r
1502Exit:\r
1503\r
1504 SafeFreePool (*Config);\r
1505 SafeFreePool (ValueStr);\r
1506 SafeFreePool (Value);\r
1507 SafeFreePool (ConfigElement);\r
1508\r
1509 return Status;\r
1510\r
1511}\r
1512\r
1513\r
1514/**\r
1515 This helper function is to be called by drivers to map configuration strings\r
1516 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
1517\r
1518 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1519 instance.\r
1520 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
1521 format.\r
1522 @param Block A possibly null array of bytes representing the\r
1523 current block. Only bytes referenced in the\r
1524 ConfigResp string in the block are modified. If\r
1525 this parameter is null or if the *BlockSize\r
1526 parameter is (on input) shorter than required by\r
1527 the Configuration string, only the BlockSize\r
1528 parameter is updated and an appropriate status\r
1529 (see below) is returned.\r
1530 @param BlockSize The length of the Block in units of UINT8. On\r
1531 input, this is the size of the Block. On output,\r
1532 if successful, contains the index of the last\r
1533 modified byte in the Block.\r
1534 @param Progress On return, points to an element of the ConfigResp\r
1535 string filled in with the offset of the most\r
1536 recent '&' before the first failing name / value\r
1537 pair (or the beginning of the string if the\r
1538 failure is in the first name / value pair) or the\r
1539 terminating NULL if all was successful.\r
1540\r
1541 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
1542 terminator at the end of the ConfigResp string.\r
1543 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
1544 points to the first character of ConfigResp.\r
1545 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
1546 Block parameter would result in this type of\r
1547 error. Progress points to the first character of\r
1548 ConfigResp.\r
1549 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
1550 value pair. Block is left updated and\r
1551 Progress points at the '&' preceding the first\r
1552 non-<BlockName>.\r
1553\r
1554**/\r
1555EFI_STATUS\r
1556EFIAPI\r
1557HiiConfigToBlock (\r
1558 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1559 IN CONST EFI_STRING ConfigResp,\r
1560 IN OUT UINT8 *Block,\r
1561 IN OUT UINTN *BlockSize,\r
1562 OUT EFI_STRING *Progress\r
1563 )\r
1564{\r
1565 HII_DATABASE_PRIVATE_DATA *Private;\r
1566 EFI_STRING StringPtr;\r
1567 UINTN Length;\r
1568 EFI_STATUS Status;\r
1569 UINT8 *TmpBuffer;\r
1570 UINTN Offset;\r
1571 UINTN Width;\r
1572 UINT8 *Value;\r
1573 UINTN BufferSize;\r
1574\r
1575 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
1576 return EFI_INVALID_PARAMETER;\r
1577 }\r
1578\r
1579 if (ConfigResp == NULL || Block == NULL) {\r
1580 *Progress = ConfigResp;\r
1581 return EFI_INVALID_PARAMETER;\r
1582 }\r
1583\r
1584 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
1585 ASSERT (Private != NULL);\r
1586\r
1587 StringPtr = ConfigResp;\r
1588 BufferSize = *BlockSize;\r
1589 Value = NULL;\r
1590\r
1591 //\r
1592 // Jump <ConfigHdr>\r
1593 //\r
1594 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1595 *Progress = StringPtr;\r
1596 Status = EFI_INVALID_PARAMETER;\r
1597 goto Exit;\r
1598 }\r
1599 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
1600 StringPtr++;\r
1601 }\r
1602 if (*StringPtr == 0) {\r
1603 *Progress = StringPtr;\r
1604 Status = EFI_INVALID_PARAMETER;\r
1605 goto Exit;\r
1606 }\r
1607 while (*StringPtr++ != L'&');\r
1608\r
1609 //\r
1610 // Parse each <ConfigElement> if exists\r
1611 // Only <BlockConfig> format is supported by this help function.\r
1612 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
1613 //\r
1614 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
1615 StringPtr += StrLen (L"OFFSET=");\r
1616 //\r
1617 // Get Offset\r
1618 //\r
1619 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1620 if (Status == EFI_OUT_OF_RESOURCES) {\r
1621 *Progress = ConfigResp;\r
1622 goto Exit;\r
1623 }\r
1624 Offset = 0;\r
1625 CopyMem (\r
1626 &Offset,\r
1627 TmpBuffer,\r
1628 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1629 );\r
1630 SafeFreePool (TmpBuffer);\r
1631\r
1632 StringPtr += Length;\r
1633 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1634 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
1635 Status = EFI_INVALID_PARAMETER;\r
1636 goto Exit;\r
1637 }\r
1638 StringPtr += StrLen (L"&WIDTH=");\r
1639\r
1640 //\r
1641 // Get Width\r
1642 //\r
1643 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1644 if (Status == EFI_OUT_OF_RESOURCES) {\r
1645 *Progress = ConfigResp;\r
1646 goto Exit;\r
1647 }\r
1648 Width = 0;\r
1649 CopyMem (\r
1650 &Width,\r
1651 TmpBuffer,\r
1652 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1653 );\r
1654 SafeFreePool (TmpBuffer);\r
1655\r
1656 StringPtr += Length;\r
1657 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
1658 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
1659 Status = EFI_INVALID_PARAMETER;\r
1660 goto Exit;\r
1661 }\r
1662 StringPtr += StrLen (L"&VALUE=");\r
1663\r
1664 //\r
1665 // Get Value\r
1666 //\r
1667 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
1668 if (Status == EFI_OUT_OF_RESOURCES) {\r
1669 *Progress = ConfigResp;\r
1670 goto Exit;\r
1671 }\r
1672\r
1673 StringPtr += Length;\r
1674 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1675 *Progress = StringPtr - Length - 7;\r
1676 Status = EFI_INVALID_PARAMETER;\r
1677 goto Exit;\r
1678 }\r
1679\r
1680 //\r
1681 // Update the Block with configuration info\r
1682 //\r
1683\r
1684 if (Offset + Width > BufferSize) {\r
1685 return EFI_DEVICE_ERROR;\r
1686 }\r
1687\r
1688 CopyMem (Block + Offset, Value, Width);\r
1689 *BlockSize = Offset + Width - 1;\r
1690\r
1691 SafeFreePool (Value);\r
1692 Value = NULL;\r
1693\r
1694 //\r
1695 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
1696 //\r
1697 if (*StringPtr == 0) {\r
1698 break;\r
1699 }\r
1700\r
1701 StringPtr++;\r
1702 }\r
1703\r
1704 if (*StringPtr != 0) {\r
1705 *Progress = StringPtr - 1;\r
1706 Status = EFI_INVALID_PARAMETER;\r
1707 goto Exit;\r
1708 }\r
1709\r
1710 *Progress = StringPtr;\r
1711 return EFI_SUCCESS;\r
1712\r
1713Exit:\r
1714\r
1715 SafeFreePool (Value);\r
1716 return Status;\r
1717}\r
1718\r
1719\r
1720/**\r
1721 This helper function is to be called by drivers to extract portions of\r
1722 a larger configuration string.\r
1723\r
1724 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1725 instance.\r
1726 @param Configuration A null-terminated Unicode string in\r
1727 <MultiConfigAltResp> format.\r
1728 @param Guid A pointer to the GUID value to search for in the\r
1729 routing portion of the ConfigResp string when\r
1730 retrieving the requested data. If Guid is NULL,\r
1731 then all GUID values will be searched for.\r
1732 @param Name A pointer to the NAME value to search for in the\r
1733 routing portion of the ConfigResp string when\r
1734 retrieving the requested data. If Name is NULL,\r
1735 then all Name values will be searched for.\r
1736 @param DevicePath A pointer to the PATH value to search for in the\r
1737 routing portion of the ConfigResp string when\r
1738 retrieving the requested data. If DevicePath is\r
1739 NULL, then all DevicePath values will be searched\r
1740 for.\r
1741 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
1742 routing portion of the ConfigResp string when\r
1743 retrieving the requested data. If this parameter\r
1744 is NULL, then the current setting will be\r
1745 retrieved.\r
1746 @param AltCfgResp A pointer to a buffer which will be allocated by\r
1747 the function which contains the retrieved string\r
1748 as requested. This buffer is only allocated if\r
1749 the call was successful.\r
1750\r
1751 @retval EFI_SUCCESS The request succeeded. The requested data was\r
1752 extracted and placed in the newly allocated\r
1753 AltCfgResp buffer.\r
1754 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
1755 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
1756 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
1757 found.\r
1758\r
1759**/\r
1760EFI_STATUS\r
1761EFIAPI\r
1762HiiGetAltCfg (\r
1763 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1764 IN CONST EFI_STRING Configuration,\r
1765 IN CONST EFI_GUID *Guid,\r
1766 IN CONST EFI_STRING Name,\r
1767 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1768 IN CONST UINT16 *AltCfgId,\r
1769 OUT EFI_STRING *AltCfgResp\r
1770 )\r
1771{\r
93e3992d 1772 EFI_STATUS Status;\r
1773 EFI_STRING StringPtr;\r
e90b081a 1774 EFI_STRING HdrStart;\r
1775 EFI_STRING HdrEnd;\r
93e3992d 1776 EFI_STRING TmpPtr;\r
1777 UINTN Length;\r
e90b081a 1778 EFI_STRING GuidStr;\r
1779 EFI_STRING NameStr;\r
1780 EFI_STRING PathStr;\r
1781 EFI_STRING AltIdStr;\r
1782 EFI_STRING Result;\r
1783 BOOLEAN GuidFlag;\r
1784 BOOLEAN NameFlag;\r
1785 BOOLEAN PathFlag;\r
1786\r
e94358a3 1787 //\r
1788 // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
1789 // as FALSE. But this renders the system to not 100% compliant with\r
1790 // UEFI 2.1. Use this with caution.\r
1791 //\r
1792 if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
1793 return EFI_UNSUPPORTED;\r
1794 }\r
1795\r
e90b081a 1796 HdrStart = NULL;\r
1797 HdrEnd = NULL;\r
1798 GuidStr = NULL;\r
1799 NameStr = NULL;\r
1800 PathStr = NULL;\r
1801 AltIdStr = NULL;\r
1802 Result = NULL;\r
1803 GuidFlag = FALSE;\r
1804 NameFlag = FALSE;\r
1805 PathFlag = FALSE;\r
93e3992d 1806\r
1807 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
1808 return EFI_INVALID_PARAMETER;\r
1809 }\r
1810\r
1811 StringPtr = Configuration;\r
1812 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1813 return EFI_INVALID_PARAMETER;\r
1814 }\r
1815\r
1816 //\r
1817 // Generate the sub string for later matching.\r
1818 //\r
813acf3a 1819 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 1820 GenerateSubStr (\r
1821 L"PATH=",\r
1822 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 1823 (VOID *) DevicePath,\r
1824 1,\r
93e3992d 1825 &PathStr\r
1826 );\r
1827 if (AltCfgId != NULL) {\r
813acf3a 1828 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 1829 }\r
1830 if (Name != NULL) {\r
813acf3a 1831 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 1832 } else {\r
813acf3a 1833 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 1834 }\r
1835\r
1836 while (*StringPtr != 0) {\r
1837 //\r
1838 // Try to match the GUID\r
1839 //\r
1840 if (!GuidFlag) {\r
1841 TmpPtr = StrStr (StringPtr, GuidStr);\r
1842 if (TmpPtr == NULL) {\r
1843 Status = EFI_NOT_FOUND;\r
1844 goto Exit;\r
1845 }\r
1846 HdrStart = TmpPtr;\r
1847\r
1848 //\r
1849 // Jump to <NameHdr>\r
1850 //\r
1851 if (Guid != NULL) {\r
1852 StringPtr = TmpPtr + StrLen (GuidStr);\r
1853 } else {\r
1854 StringPtr = StrStr (TmpPtr, L"NAME=");\r
1855 if (StringPtr == NULL) {\r
1856 Status = EFI_NOT_FOUND;\r
1857 goto Exit;\r
1858 }\r
1859 }\r
1860 GuidFlag = TRUE;\r
1861 }\r
1862\r
1863 //\r
1864 // Try to match the NAME\r
1865 //\r
1866 if (GuidFlag && !NameFlag) {\r
1867 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
1868 GuidFlag = FALSE;\r
1869 } else {\r
1870 //\r
1871 // Jump to <PathHdr>\r
1872 //\r
1873 if (Name != NULL) {\r
1874 StringPtr += StrLen (NameStr);\r
1875 } else {\r
1876 StringPtr = StrStr (StringPtr, L"PATH=");\r
1877 if (StringPtr == NULL) {\r
1878 Status = EFI_NOT_FOUND;\r
1879 goto Exit;\r
1880 }\r
1881 }\r
1882 NameFlag = TRUE;\r
1883 }\r
1884 }\r
1885\r
1886 //\r
1887 // Try to match the DevicePath\r
1888 //\r
1889 if (GuidFlag && NameFlag && !PathFlag) {\r
1890 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
1891 GuidFlag = FALSE;\r
1892 NameFlag = FALSE;\r
1893 } else {\r
1894 //\r
1895 // Jump to '&' before <DescHdr> or <ConfigBody>\r
1896 //\r
1897 if (DevicePath != NULL) {\r
1898 StringPtr += StrLen (PathStr);\r
1899 } else {\r
1900 StringPtr = StrStr (StringPtr, L"&");\r
1901 if (StringPtr == NULL) {\r
1902 Status = EFI_NOT_FOUND;\r
1903 goto Exit;\r
1904 }\r
1905 }\r
1906 PathFlag = TRUE;\r
1907 HdrEnd = ++StringPtr;\r
1908 }\r
1909 }\r
1910\r
1911 //\r
1912 // Try to match the AltCfgId\r
1913 //\r
1914 if (GuidFlag && NameFlag && PathFlag) {\r
1915 if (AltCfgId == NULL) {\r
1916 //\r
1917 // Return Current Setting when AltCfgId is NULL.\r
1918 //\r
1919 Status = OutputConfigBody (StringPtr, &Result);\r
1920 goto Exit;\r
1921 }\r
1922 //\r
1923 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
1924 //\r
1925 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
1926 GuidFlag = FALSE;\r
1927 NameFlag = FALSE;\r
1928 PathFlag = FALSE;\r
1929 } else {\r
1930 Status = OutputConfigBody (StringPtr, &Result);\r
1931 goto Exit;\r
1932 }\r
1933 }\r
1934 }\r
1935\r
1936 Status = EFI_NOT_FOUND;\r
1937\r
1938Exit:\r
1939\r
1940 if (!EFI_ERROR (Status)) {\r
1941 //\r
1942 // Copy the <ConfigHdr> and <ConfigBody>\r
1943 //\r
1944 Length = HdrEnd - HdrStart + StrLen (Result);\r
1945 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
1946 if (*AltCfgResp == NULL) {\r
1947 Status = EFI_OUT_OF_RESOURCES;\r
1948 } else {\r
1949 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
1950 StrCat (*AltCfgResp, Result);\r
1951 Status = EFI_SUCCESS;\r
1952 }\r
1953 }\r
1954\r
1955 SafeFreePool (GuidStr);\r
1956 SafeFreePool (NameStr);\r
1957 SafeFreePool (PathStr);\r
1958 SafeFreePool (AltIdStr);\r
1959 SafeFreePool (Result);\r
1960\r
1961 return Status;\r
1962\r
93e3992d 1963}\r
1964\r
36fe40c2 1965\r