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