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