]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
Add check for NULL pointer.
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigRouting.c
CommitLineData
93e3992d 1/** @file\r
3cb3f198 2Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
93e3992d 3\r
84f9a9ec 4Copyright (c) 2007 - 2008, Intel Corporation\r
93e3992d 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
93e3992d 13**/\r
14\r
15\r
16#include "HiiDatabase.h"\r
84f9a9ec 17extern HII_DATABASE_PRIVATE_DATA mPrivate;\r
93e3992d 18\r
93e3992d 19/**\r
20 Calculate the number of Unicode characters of the incoming Configuration string,\r
21 not including NULL terminator.\r
22\r
e90b081a 23 This is a internal function.\r
24\r
93e3992d 25 @param String String in <MultiConfigRequest> or\r
26 <MultiConfigResp> format.\r
27\r
28 @return The number of Unicode characters.\r
29\r
30**/\r
93e3992d 31UINTN\r
32CalculateConfigStringLen (\r
33 IN EFI_STRING String\r
34 )\r
35{\r
84f9a9ec 36 EFI_STRING TmpPtr;\r
93e3992d 37\r
38 //\r
39 // "GUID=" should be the first element of incoming string.\r
40 //\r
41 ASSERT (String != NULL);\r
42 ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);\r
43\r
93e3992d 44 //\r
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".\r
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.\r
84f9a9ec
LG
47 // \r
48 TmpPtr = StrStr (String, L"&GUID=");\r
49 if (TmpPtr == NULL) {\r
50 return StrLen (String);\r
93e3992d 51 }\r
52\r
84f9a9ec 53 return (TmpPtr - String);\r
93e3992d 54}\r
55\r
56\r
57/**\r
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
59 from <PathHdr> of <ConfigHdr>.\r
60\r
e90b081a 61 This is a internal function.\r
62\r
93e3992d 63 @param String UEFI configuration string\r
64 @param DevicePath binary of a UEFI device path.\r
65\r
66 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
67 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
68 @retval EFI_SUCCESS The device path is retrieved and translated to\r
69 binary format.\r
70\r
71**/\r
93e3992d 72EFI_STATUS\r
73GetDevicePath (\r
74 IN EFI_STRING String,\r
75 OUT UINT8 **DevicePath\r
76 )\r
77{\r
78 UINTN Length;\r
79 EFI_STRING PathHdr;\r
80 EFI_STRING DevicePathString;\r
63d55bb9
LG
81 UINT8 *DevicePathBuffer;\r
82 CHAR16 TemStr[2];\r
83 UINTN Index;\r
84 UINT8 DigitUint8;\r
93e3992d 85\r
86 if (String == NULL || DevicePath == NULL) {\r
87 return EFI_INVALID_PARAMETER;\r
88 }\r
89\r
90 //\r
91 // Find the 'PATH=' of <PathHdr> and skip it.\r
92 //\r
93 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
94 if (*String == 0) {\r
95 return EFI_INVALID_PARAMETER;\r
96 }\r
97\r
98 String += StrLen (L"PATH=");\r
99 PathHdr = String;\r
100\r
101 //\r
102 // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
103 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
104 // of UEFI device path.\r
105 //\r
106 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
107 DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
108 if (DevicePathString == NULL) {\r
109 return EFI_OUT_OF_RESOURCES;\r
110 }\r
111 StrnCpy (DevicePathString, PathHdr, Length);\r
112 *(DevicePathString + Length) = 0;\r
113\r
114 //\r
115 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
116 // as the device path resides in RAM memory.\r
117 // Translate the data into binary.\r
93e3992d 118 //\r
63d55bb9
LG
119 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
120 if (DevicePathBuffer == NULL) {\r
676df92c 121 FreePool (DevicePathString);\r
93e3992d 122 return EFI_OUT_OF_RESOURCES;\r
123 }\r
124\r
63d55bb9
LG
125 ZeroMem (TemStr, sizeof (TemStr));\r
126 for (Index = 0; DevicePathString[Index] != L'\0'; Index ++) {\r
127 TemStr[0] = DevicePathString[Index];\r
128 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
129 if ((Index & 1) == 0) {\r
130 DevicePathBuffer [Index/2] = DigitUint8;\r
131 } else {\r
132 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
133 }\r
134 }\r
93e3992d 135\r
676df92c 136 FreePool (DevicePathString);\r
63d55bb9
LG
137 \r
138 *DevicePath = DevicePathBuffer;\r
93e3992d 139\r
140 return EFI_SUCCESS;\r
141\r
142}\r
143\r
63d55bb9
LG
144/**\r
145 Converts the unicode character of the string from uppercase to lowercase.\r
146 This is a internal function.\r
147\r
148 @param Str String to be converted\r
149\r
150**/\r
151VOID\r
152EFIAPI\r
153HiiToLower (\r
84f9a9ec 154 IN EFI_STRING ConfigString\r
63d55bb9
LG
155 )\r
156{\r
84f9a9ec
LG
157 EFI_STRING String;\r
158 BOOLEAN Lower;\r
159\r
160 ASSERT (ConfigString != NULL);\r
161\r
162 //\r
163 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
164 //\r
165 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
166 if (*String == L'=') {\r
167 Lower = TRUE;\r
168 } else if (*String == L'&') {\r
169 Lower = FALSE;\r
170 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
171 *String = (CHAR16) (*String - L'A' + L'a');\r
63d55bb9
LG
172 }\r
173 }\r
84f9a9ec
LG
174\r
175 return;\r
63d55bb9 176}\r
93e3992d 177\r
93e3992d 178/**\r
179 Generate a sub string then output it.\r
180\r
e90b081a 181 This is a internal function.\r
182\r
93e3992d 183 @param String A constant string which is the prefix of the to be\r
184 generated string, e.g. GUID=\r
84f9a9ec 185\r
93e3992d 186 @param BufferLen The length of the Buffer in bytes.\r
84f9a9ec 187\r
813acf3a 188 @param Buffer Points to a buffer which will be converted to be the \r
84f9a9ec
LG
189 content of the generated string.\r
190\r
191 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in \r
192 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
193 if 3, the buffer contains other data.\r
194\r
93e3992d 195 @param SubStr Points to the output string. It's caller's\r
196 responsibility to free this buffer.\r
197\r
198\r
199**/\r
93e3992d 200VOID\r
201GenerateSubStr (\r
202 IN CONST EFI_STRING String,\r
203 IN UINTN BufferLen,\r
813acf3a 204 IN VOID *Buffer,\r
205 IN UINT8 Flag,\r
93e3992d 206 OUT EFI_STRING *SubStr\r
207 )\r
208{\r
209 UINTN Length;\r
210 EFI_STRING Str;\r
813acf3a 211 EFI_STRING StringHeader;\r
63d55bb9
LG
212 CHAR16 *TemString;\r
213 CHAR16 *TemName;\r
214 UINT8 *TemBuffer;\r
215 UINTN Index;\r
93e3992d 216\r
217 ASSERT (String != NULL && SubStr != NULL);\r
218\r
219 if (Buffer == NULL) {\r
220 *SubStr = AllocateCopyPool (StrSize (String), String);\r
221 ASSERT (*SubStr != NULL);\r
222 return ;\r
223 }\r
84f9a9ec
LG
224 \r
225 //\r
226 // Header + Data + '&' + '\0'\r
227 //\r
813acf3a 228 Length = StrLen (String) + BufferLen * 2 + 1 + 1;\r
63d55bb9 229 Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
93e3992d 230 ASSERT (Str != NULL);\r
231\r
232 StrCpy (Str, String);\r
233 Length = (BufferLen * 2 + 1) * sizeof (CHAR16);\r
234\r
813acf3a 235 StringHeader = Str + StrLen (String);\r
63d55bb9 236 TemString = (CHAR16 *) StringHeader;\r
813acf3a 237\r
238 switch (Flag) {\r
239 case 1:\r
63d55bb9
LG
240 //\r
241 // Convert Buffer to Hex String in reverse order\r
242 //\r
243 TemBuffer = ((UINT8 *) Buffer);\r
244 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {\r
245 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
246 }\r
813acf3a 247 break;\r
248 case 2:\r
63d55bb9
LG
249 //\r
250 // Check buffer is enough\r
251 //\r
252 TemName = (CHAR16 *) Buffer;\r
84f9a9ec 253 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));\r
63d55bb9
LG
254 //\r
255 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
256 //\r
257 for (; *TemName != L'\0'; TemName++) {\r
258 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
259 }\r
813acf3a 260 break;\r
261 case 3:\r
813acf3a 262 //\r
63d55bb9 263 // Convert Buffer to Hex String\r
813acf3a 264 //\r
63d55bb9
LG
265 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;\r
266 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {\r
267 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
268 }\r
813acf3a 269 break;\r
270 default:\r
271 break;\r
272 }\r
93e3992d 273\r
63d55bb9
LG
274 //\r
275 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
276 //\r
84f9a9ec
LG
277 StrCat (Str, L"&"); \r
278 HiiToLower (Str);\r
93e3992d 279\r
280 *SubStr = Str;\r
281}\r
282\r
283\r
284/**\r
285 Retrieve the <ConfigBody> from String then output it.\r
286\r
e90b081a 287 This is a internal function.\r
288\r
93e3992d 289 @param String A sub string of a configuration string in\r
290 <MultiConfigAltResp> format.\r
291 @param ConfigBody Points to the output string. It's caller's\r
292 responsibility to free this buffer.\r
293\r
294 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.\r
295 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.\r
296 @retval EFI_SUCCESS All existing storage is exported.\r
297\r
298**/\r
93e3992d 299EFI_STATUS\r
300OutputConfigBody (\r
301 IN EFI_STRING String,\r
302 OUT EFI_STRING *ConfigBody\r
303 )\r
304{\r
305 EFI_STRING TmpPtr;\r
306 EFI_STRING Result;\r
307 UINTN Length;\r
308\r
309 if (String == NULL || ConfigBody == NULL) {\r
310 return EFI_INVALID_PARAMETER;\r
311 }\r
84f9a9ec
LG
312 \r
313 //\r
314 // The setting information should start OFFSET, not ALTCFG.\r
315 //\r
316 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {\r
317 return EFI_INVALID_PARAMETER;\r
318 }\r
93e3992d 319\r
320 TmpPtr = StrStr (String, L"GUID=");\r
321 if (TmpPtr == NULL) {\r
322 //\r
323 // It is the last <ConfigResp> of the incoming configuration string.\r
324 //\r
325 Result = AllocateCopyPool (StrSize (String), String);\r
326 if (Result == NULL) {\r
327 return EFI_OUT_OF_RESOURCES;\r
328 } else {\r
329 *ConfigBody = Result;\r
330 return EFI_SUCCESS;\r
331 }\r
332 }\r
333\r
334 Length = TmpPtr - String;\r
335 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
336 if (Result == NULL) {\r
337 return EFI_OUT_OF_RESOURCES;\r
338 }\r
339\r
340 *(Result + Length - 1) = 0;\r
341 *ConfigBody = Result;\r
342 return EFI_SUCCESS;\r
93e3992d 343}\r
344\r
93e3992d 345/**\r
346 Append a string to a multi-string format.\r
347\r
e90b081a 348 This is a internal function.\r
349\r
93e3992d 350 @param MultiString String in <MultiConfigRequest>,\r
351 <MultiConfigAltResp>, or <MultiConfigResp>. On\r
352 input, the buffer length of this string is\r
353 MAX_STRING_LENGTH. On output, the buffer length\r
354 might be updated.\r
355 @param AppendString NULL-terminated Unicode string.\r
356\r
357 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
358 @retval EFI_SUCCESS AppendString is append to the end of MultiString\r
359\r
360**/\r
93e3992d 361EFI_STATUS\r
362AppendToMultiString (\r
363 IN OUT EFI_STRING *MultiString,\r
364 IN EFI_STRING AppendString\r
365 )\r
366{\r
367 UINTN AppendStringSize;\r
368 UINTN MultiStringSize;\r
369\r
370 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
371 return EFI_INVALID_PARAMETER;\r
372 }\r
84f9a9ec
LG
373\r
374 AppendStringSize = StrSize (AppendString);\r
375 MultiStringSize = StrSize (*MultiString);\r
376\r
377 //\r
378 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
379 //\r
380 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
381 MultiStringSize > MAX_STRING_LENGTH) {\r
382 *MultiString = (EFI_STRING) ReallocatePool (\r
383 MultiStringSize,\r
384 MultiStringSize + AppendStringSize,\r
385 (VOID *) (*MultiString)\r
386 );\r
387 ASSERT (*MultiString != NULL);\r
388 }\r
389 //\r
390 // Append the incoming string\r
391 //\r
392 StrCat (*MultiString, AppendString);\r
393\r
394 return EFI_SUCCESS;\r
395}\r
396\r
397\r
398/**\r
399 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
400 or WIDTH or VALUE.\r
401 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
402\r
403 This is a internal function.\r
404\r
405 @param StringPtr String in <BlockConfig> format and points to the\r
406 first character of <Number>.\r
407 @param Number The output value. Caller takes the responsibility\r
408 to free memory.\r
409 @param Len Length of the <Number>, in characters.\r
410\r
411 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
412 structures.\r
413 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
414 successfully.\r
415\r
416**/\r
417EFI_STATUS\r
418GetValueOfNumber (\r
419 IN EFI_STRING StringPtr,\r
420 OUT UINT8 **Number,\r
421 OUT UINTN *Len\r
422 )\r
423{\r
424 EFI_STRING TmpPtr;\r
425 UINTN Length;\r
426 EFI_STRING Str;\r
427 UINT8 *Buf;\r
428 EFI_STATUS Status;\r
429 UINT8 DigitUint8;\r
430 UINTN Index;\r
431 CHAR16 TemStr[2];\r
432\r
433 ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);\r
434 ASSERT (*StringPtr != L'\0');\r
435\r
436 Buf = NULL;\r
437\r
438 TmpPtr = StringPtr;\r
439 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
440 StringPtr++;\r
441 }\r
442 *Len = StringPtr - TmpPtr;\r
443 Length = *Len + 1;\r
444\r
445 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
446 if (Str == NULL) {\r
447 Status = EFI_OUT_OF_RESOURCES;\r
448 goto Exit;\r
449 }\r
450 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
451 *(Str + *Len) = L'\0';\r
452\r
453 Length = (Length + 1) / 2;\r
454 Buf = (UINT8 *) AllocateZeroPool (Length);\r
455 if (Buf == NULL) {\r
456 Status = EFI_OUT_OF_RESOURCES;\r
457 goto Exit;\r
458 }\r
459 \r
460 Length = *Len;\r
461 ZeroMem (TemStr, sizeof (TemStr));\r
462 for (Index = 0; Index < Length; Index ++) {\r
463 TemStr[0] = Str[Length - Index - 1];\r
464 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
465 if ((Index & 1) == 0) {\r
466 Buf [Index/2] = DigitUint8;\r
467 } else {\r
468 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
469 }\r
470 }\r
471\r
472 *Number = Buf;\r
473 Status = EFI_SUCCESS;\r
474\r
475Exit:\r
476 if (Str != NULL) {\r
477 FreePool (Str);\r
478 }\r
479\r
480 return Status;\r
481}\r
482\r
483/**\r
484 This function merges DefaultAltCfgResp string into AltCfgResp string for\r
485 the missing AltCfgId in AltCfgResq.\r
486\r
487 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
488 <ConfigAltResp> format. The default value string \r
489 will be merged into it. \r
490 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
491 <MultiConfigAltResp> format. The default value \r
492 string may contain more than one ConfigAltResp\r
493 string for the different varstore buffer.\r
494\r
495 @retval EFI_SUCCESS The merged string returns.\r
496 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.\r
497**/\r
498EFI_STATUS\r
499EFIAPI\r
500MergeDefaultString (\r
501 IN OUT EFI_STRING *AltCfgResp,\r
502 IN EFI_STRING DefaultAltCfgResp\r
503 )\r
504{\r
505 EFI_STRING StringPtrDefault;\r
506 EFI_STRING StringPtrEnd;\r
507 CHAR16 TempChar;\r
508 EFI_STRING StringPtr;\r
509 EFI_STRING AltConfigHdr;\r
510 UINTN HeaderLength;\r
511 UINTN SizeAltCfgResp;\r
512 \r
513 if (*AltCfgResp == NULL) {\r
514 return EFI_INVALID_PARAMETER;\r
515 }\r
516 \r
517 //\r
518 // Get the requestr ConfigHdr\r
519 //\r
520 SizeAltCfgResp = 0;\r
521 StringPtr = *AltCfgResp;\r
522 \r
523 //\r
524 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
525 //\r
526 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
527 return EFI_INVALID_PARAMETER;\r
528 }\r
529 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
530 StringPtr++;\r
531 }\r
532 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
533 StringPtr++;\r
534 }\r
535 if (*StringPtr == L'\0') {\r
536 return EFI_INVALID_PARAMETER;\r
537 }\r
538 StringPtr += StrLen (L"&PATH=");\r
539 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
540 StringPtr ++;\r
541 }\r
542 HeaderLength = StringPtr - *AltCfgResp;\r
543\r
544 //\r
545 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"\r
546 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |\r
547 //\r
548 AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));\r
549 if (AltConfigHdr == NULL) {\r
550 return EFI_OUT_OF_RESOURCES;\r
551 }\r
552 StrCpy (AltConfigHdr, L"&");\r
553 StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);\r
554 StrCat (AltConfigHdr, L"&ALTCFG=");\r
555 HeaderLength = StrLen (AltConfigHdr);\r
556 \r
557 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
558 while (StringPtrDefault != NULL) {\r
559 //\r
560 // Get AltCfg Name\r
561 //\r
562 StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);\r
563 StringPtr = StrStr (*AltCfgResp, AltConfigHdr); \r
564 \r
565 //\r
566 // Append the found default value string to the input AltCfgResp\r
567 // \r
568 if (StringPtr == NULL) {\r
569 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");\r
570 SizeAltCfgResp = StrSize (*AltCfgResp);\r
571 if (StringPtrEnd == NULL) {\r
572 //\r
573 // No more default string is found.\r
574 //\r
575 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
576 SizeAltCfgResp,\r
577 SizeAltCfgResp + StrSize (StringPtrDefault),\r
578 (VOID *) (*AltCfgResp)\r
579 );\r
580 StrCat (*AltCfgResp, StringPtrDefault);\r
581 break;\r
582 } else {\r
583 TempChar = *StringPtrEnd;\r
584 *StringPtrEnd = L'\0';\r
585 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
586 SizeAltCfgResp,\r
587 SizeAltCfgResp + StrSize (StringPtrDefault),\r
588 (VOID *) (*AltCfgResp)\r
589 );\r
590 StrCat (*AltCfgResp, StringPtrDefault);\r
591 *StringPtrEnd = TempChar;\r
592 }\r
593 }\r
594 \r
595 //\r
596 // Find next AltCfg String\r
597 // \r
598 *(AltConfigHdr + HeaderLength) = L'\0';\r
599 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr); \r
600 }\r
601\r
602 return EFI_SUCCESS; \r
603}\r
604\r
605/**\r
606 This function finds the matched DefaultName for the input DefaultId\r
607\r
608 @param DefaultIdArray Array stores the map table between DefaultId and DefaultName.\r
609 @param VarDefaultId Default Id\r
610 @param VarDefaultName Default Name string ID for the input default ID.\r
611 \r
612 @retval EFI_SUCCESS The mapped default name string ID is found.\r
613 @retval EFI_NOT_FOUND The mapped default name string ID is not found.\r
614**/\r
615EFI_STATUS\r
616FindDefaultName (\r
617 IN IFR_DEFAULT_DATA *DefaultIdArray, \r
618 IN UINT16 VarDefaultId, \r
619 OUT EFI_STRING_ID *VarDefaultName\r
620 )\r
621{\r
622 LIST_ENTRY *Link;\r
623 IFR_DEFAULT_DATA *DefaultData;\r
624\r
625 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
626 DefaultData = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
627 if (DefaultData->DefaultId == VarDefaultId) {\r
628 *VarDefaultName = DefaultData->DefaultName;\r
629 return EFI_SUCCESS;\r
630 }\r
631 }\r
632 \r
633 return EFI_NOT_FOUND;\r
634}\r
635\r
636/**\r
637 This function inserts new DefaultValueData into the BlockData DefaultValue array.\r
638\r
639 @param BlockData The BlockData is updated to add new default value.\r
640 @param DefaultValueData The DefaultValue is added.\r
641\r
642**/\r
643VOID\r
644InsertDefaultValue (\r
645 IN IFR_BLOCK_DATA *BlockData,\r
646 IN IFR_DEFAULT_DATA *DefaultValueData\r
647 )\r
648{\r
649 LIST_ENTRY *Link;\r
650 IFR_DEFAULT_DATA *DefaultValueArray;\r
651\r
652 for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) {\r
653 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
654 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {\r
655 //\r
656 // Update the default value array in BlockData.\r
657 //\r
658 DefaultValueArray->Value = DefaultValueData->Value;\r
659 FreePool (DefaultValueData);\r
660 return;\r
661 } else if (DefaultValueArray->DefaultId > DefaultValueData->DefaultId) {\r
662 //\r
663 // Insert new default value data in the front of this default value array.\r
664 //\r
665 InsertTailList (Link, &DefaultValueData->Entry);\r
666 return;\r
667 }\r
668 }\r
669\r
670 //\r
671 // Insert new default value data in tail.\r
672 //\r
673 InsertTailList (Link, &DefaultValueData->Entry);\r
674 return;\r
675}\r
676\r
677/**\r
678 This function inserts new BlockData into the block link\r
679\r
680 @param BlockLink The list entry points to block array.\r
681 @param BlockData The point to BlockData is added.\r
682 \r
683**/\r
684VOID\r
685InsertBlockData (\r
686 IN LIST_ENTRY *BlockLink,\r
687 IN IFR_BLOCK_DATA **BlockData\r
688 )\r
689{\r
690 LIST_ENTRY *Link;\r
691 IFR_BLOCK_DATA *BlockArray;\r
692 IFR_BLOCK_DATA *BlockSingleData;\r
693\r
694 BlockSingleData = *BlockData;\r
695 \r
696 //\r
697 // Insert block data in its Offset and Width order.\r
698 //\r
699 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
700 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
701 if (BlockArray->Offset == BlockSingleData->Offset) {\r
702 if (BlockArray->Width > BlockSingleData->Width) {\r
703 //\r
704 // Insert this block data in the front of block array\r
705 //\r
706 InsertTailList (Link, &BlockSingleData->Entry);\r
707 return;\r
708 }\r
709\r
710 if (BlockArray->Width == BlockSingleData->Width) {\r
711 //\r
712 // The same block array has been added.\r
713 //\r
714 FreePool (BlockSingleData);\r
715 *BlockData = BlockArray;\r
716 return;\r
717 }\r
718 } else if (BlockArray->Offset > BlockSingleData->Offset) {\r
719 //\r
720 // Insert new block data in the front of block array \r
721 //\r
722 InsertTailList (Link, &BlockSingleData->Entry);\r
723 return;\r
724 }\r
725 }\r
726 \r
727 //\r
728 // Add new block data into the tail.\r
729 //\r
730 InsertTailList (Link, &BlockSingleData->Entry);\r
731 return; \r
732}\r
733\r
734/**\r
735 This function checks VarOffset and VarWidth is in the block range.\r
736\r
737 @param BlockArray The block array is to be checked. \r
738 @param VarOffset Offset of var to the structure\r
739 @param VarWidth Width of var.\r
740 \r
741 @retval TRUE This Var is in the block range.\r
742 @retval FALSE This Var is not in the block range.\r
743**/\r
744BOOLEAN\r
745BlockArrayCheck (\r
746 IN IFR_BLOCK_DATA *RequestBlockArray,\r
747 IN UINT16 VarOffset,\r
748 IN UINT16 VarWidth\r
749 )\r
750{\r
751 LIST_ENTRY *Link;\r
752 IFR_BLOCK_DATA *BlockData;\r
753 \r
754 //\r
755 // No Request Block array, all vars are got.\r
756 //\r
757 if (RequestBlockArray == NULL) {\r
758 return TRUE;\r
759 }\r
760 \r
761 //\r
762 // Check the input var is in the request block range.\r
763 //\r
764 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {\r
765 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
766 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
767 return TRUE;\r
768 }\r
769 }\r
770\r
771 return FALSE;\r
772}\r
773\r
774/**\r
775 This function parses Form Package to get the block array and the default\r
776 value array according to the request ConfigHdr.\r
777\r
778 @param Package Pointer to the form package data.\r
779 @param PackageLength Length of the pacakge.\r
780 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
781 the first found varstore will be as ConfigHdr.\r
782 @param RequestBlockArray The block array is retrieved from the request string.\r
783 @param VarStorageData VarStorage structure contains the got block and default value.\r
784 @param PIfrDefaultIdArray Point to the got default id and default name array.\r
785\r
786 @retval EFI_SUCCESS The block array and the default value array are got.\r
787 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges\r
788 are conflicted. \r
789 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
790**/\r
791EFI_STATUS\r
792EFIAPI\r
793ParseIfrData (\r
794 IN UINT8 *Package,\r
795 IN UINT32 PackageLenth,\r
796 IN EFI_STRING ConfigHdr,\r
797 IN IFR_BLOCK_DATA *RequestBlockArray,\r
798 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
799 OUT IFR_DEFAULT_DATA **PIfrDefaultIdArray\r
800 )\r
801{\r
802 EFI_STATUS Status;\r
803 UINTN IfrOffset;\r
804 EFI_IFR_VARSTORE *IfrVarStore;\r
805 EFI_IFR_OP_HEADER *IfrOpHdr;\r
806 EFI_IFR_ONE_OF *IfrOneOf;\r
807 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
808 EFI_IFR_DEFAULT *IfrDefault;\r
809 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
810 EFI_IFR_CHECKBOX *IfrCheckBox;\r
811 EFI_IFR_PASSWORD *IfrPassword;\r
812 EFI_IFR_STRING *IfrString;\r
813 IFR_DEFAULT_DATA *DefaultIdArray;\r
814 IFR_DEFAULT_DATA *DefaultData;\r
815 IFR_BLOCK_DATA *BlockData;\r
816 CHAR16 *VarStoreName;\r
817 UINT16 VarOffset;\r
818 UINT16 VarWidth;\r
819 EFI_STRING_ID VarDefaultName;\r
820 UINT16 VarDefaultId;\r
821 EFI_STRING GuidStr;\r
822 EFI_STRING NameStr;\r
823 EFI_STRING TempStr;\r
824 UINTN LengthString;\r
825\r
826 //\r
827 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
828 //\r
829 LengthString = 0;\r
830 Status = EFI_SUCCESS;\r
831 GuidStr = NULL;\r
832 NameStr = NULL;\r
833 TempStr = NULL;\r
834 BlockData = NULL;\r
835 DefaultData = NULL;\r
836 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
837 if (DefaultIdArray == NULL) {\r
838 return EFI_OUT_OF_RESOURCES;\r
839 }\r
840 InitializeListHead (&DefaultIdArray->Entry);\r
841\r
842 //\r
843 // Go through the form package to parse OpCode one by one.\r
844 //\r
845 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
846 while (IfrOffset < PackageLenth) {\r
847 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
848\r
849 switch (IfrOpHdr->OpCode) {\r
850 case EFI_IFR_VARSTORE_OP:\r
851 //\r
852 // VarStore is found. Don't need to search any more.\r
853 //\r
854 if (VarStorageData->Size != 0) {\r
855 break;\r
856 }\r
857\r
858 //\r
859 // Get the requied varstore information\r
860 // Add varstore by Guid and Name in ConfigHdr\r
861 // Make sure Offset is in varstore size and varstoreid\r
862 //\r
863 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
864 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
865 if (VarStoreName == NULL) {\r
866 Status = EFI_OUT_OF_RESOURCES;\r
867 goto Done;\r
868 }\r
869 AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);\r
870\r
871 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);\r
872 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
873 LengthString = StrLen (GuidStr);\r
874 LengthString = LengthString + StrLen (NameStr) + 1;\r
875 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
876 if (TempStr == NULL) {\r
877 FreePool (GuidStr);\r
878 FreePool (NameStr);\r
879 Status = EFI_OUT_OF_RESOURCES;\r
880 goto Done;\r
881 }\r
882 StrCpy (TempStr, GuidStr);\r
883 StrCat (TempStr, NameStr);\r
884 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
885 //\r
886 // Find the matched VarStore\r
887 //\r
888 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
889 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
890 VarStorageData->Size = IfrVarStore->Size;\r
891 VarStorageData->Name = VarStoreName;\r
892 } else {\r
893 //\r
894 // No found, free the allocated memory \r
895 //\r
896 FreePool (VarStoreName);\r
897 }\r
898 //\r
899 // Free alllocated temp string.\r
900 //\r
901 FreePool (TempStr);\r
902 FreePool (GuidStr);\r
903 FreePool (NameStr);\r
904 break;\r
905\r
906 case EFI_IFR_DEFAULTSTORE_OP:\r
907 //\r
908 // Add new the map between default id and default name.\r
909 //\r
910 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
911 if (DefaultData == NULL) {\r
912 Status = EFI_OUT_OF_RESOURCES;\r
913 goto Done;\r
914 }\r
915 DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
916 DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
917 InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry);\r
918 DefaultData = NULL;\r
919 break;\r
920\r
921 case EFI_IFR_FORM_OP:\r
922 //\r
923 // No matched varstore is found and directly return.\r
924 //\r
925 if (VarStorageData->Size == 0) {\r
926 Status = EFI_SUCCESS;\r
927 goto Done;\r
928 }\r
929 break;\r
930\r
931 case EFI_IFR_ONE_OF_OP:\r
932 case EFI_IFR_NUMERIC_OP:\r
933 //\r
934 // Numeric and OneOf has the same opcode structure.\r
935 //\r
936\r
937 //\r
938 // Check whether this question is for the requested varstore.\r
939 //\r
940 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
941 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {\r
942 break;\r
943 }\r
944 \r
945 //\r
946 // Get Offset/Width by Question header and OneOf Flags\r
947 //\r
948 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
949 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
950 //\r
951 // Check whether this question is in requested block array.\r
952 //\r
953 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
954 //\r
955 // This question is not in the requested string. Skip it.\r
956 //\r
957 break;\r
958 }\r
959\r
960 //\r
961 // Check this var question is in the var storage \r
962 //\r
963 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
964 Status = EFI_INVALID_PARAMETER;\r
965 goto Done;\r
966 }\r
967 \r
968 //\r
969 // Set Block Data\r
970 //\r
971 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
972 if (BlockData == NULL) {\r
973 Status = EFI_OUT_OF_RESOURCES;\r
974 goto Done;\r
975 }\r
976 BlockData->Offset = VarOffset;\r
977 BlockData->Width = VarWidth;\r
978 BlockData->QuestionId = IfrOneOf->Question.QuestionId;\r
979 BlockData->OpCode = IfrOpHdr->OpCode;\r
980 BlockData->Scope = IfrOpHdr->Scope;\r
981 InitializeListHead (&BlockData->DefaultValueEntry);\r
982 //\r
983 // Add Block Data into VarStorageData BlockEntry\r
984 //\r
985 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
986 break;\r
987\r
988 case EFI_IFR_ORDERED_LIST_OP:\r
989 //\r
990 // offset by question header\r
991 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
992 // no default value and default id, how to define its default value?\r
993 //\r
994 \r
995 //\r
996 // Check whether this question is for the requested varstore.\r
997 //\r
998 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
999 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1000 break;\r
1001 }\r
1002 \r
1003 //\r
1004 // Get Offset/Width by Question header and OneOf Flags\r
1005 //\r
1006 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;\r
1007 VarWidth = IfrOrderedList->MaxContainers;\r
1008\r
1009 //\r
1010 // Check whether this question is in requested block array.\r
1011 //\r
1012 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1013 //\r
1014 // This question is not in the requested string. Skip it.\r
1015 //\r
1016 break;\r
1017 }\r
1018\r
1019 //\r
1020 // Check this var question is in the var storage \r
1021 //\r
1022 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1023 Status = EFI_INVALID_PARAMETER;\r
1024 goto Done;\r
1025 }\r
1026 \r
1027 //\r
1028 // Set Block Data\r
1029 //\r
1030 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1031 if (BlockData == NULL) {\r
1032 Status = EFI_OUT_OF_RESOURCES;\r
1033 goto Done;\r
1034 }\r
1035 BlockData->Offset = VarOffset;\r
1036 BlockData->Width = VarWidth;\r
1037 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;\r
1038 BlockData->OpCode = IfrOpHdr->OpCode;\r
1039 BlockData->Scope = IfrOpHdr->Scope;\r
1040 InitializeListHead (&BlockData->DefaultValueEntry);\r
1041 \r
1042 //\r
1043 // Add Block Data into VarStorageData BlockEntry\r
1044 //\r
1045 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1046 break;\r
1047\r
1048 case EFI_IFR_CHECKBOX_OP:\r
1049 //\r
1050 // EFI_IFR_DEFAULT_OP\r
1051 // offset by question header\r
1052 // width is 1 sizeof (BOOLEAN)\r
1053 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1054 // value by DefaultOption\r
1055 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1056 // \r
1057\r
1058 //\r
1059 // Check whether this question is for the requested varstore.\r
1060 //\r
1061 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1062 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1063 break;\r
1064 }\r
1065 \r
1066 //\r
1067 // Get Offset/Width by Question header and OneOf Flags\r
1068 //\r
1069 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
1070 VarWidth = sizeof (BOOLEAN);\r
1071\r
1072 //\r
1073 // Check whether this question is in requested block array.\r
1074 //\r
1075 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1076 //\r
1077 // This question is not in the requested string. Skip it.\r
1078 //\r
1079 break;\r
1080 }\r
1081\r
1082 //\r
1083 // Check this var question is in the var storage \r
1084 //\r
1085 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1086 Status = EFI_INVALID_PARAMETER;\r
1087 goto Done;\r
1088 }\r
1089 \r
1090 //\r
1091 // Set Block Data\r
1092 //\r
1093 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1094 if (BlockData == NULL) {\r
1095 Status = EFI_OUT_OF_RESOURCES;\r
1096 goto Done;\r
1097 }\r
1098 BlockData->Offset = VarOffset;\r
1099 BlockData->Width = VarWidth;\r
1100 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;\r
1101 BlockData->OpCode = IfrOpHdr->OpCode;\r
1102 BlockData->Scope = IfrOpHdr->Scope;\r
1103 InitializeListHead (&BlockData->DefaultValueEntry);\r
1104 //\r
1105 // Add Block Data into VarStorageData BlockEntry\r
1106 //\r
1107 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1108 \r
1109 //\r
1110 // Add default value by CheckBox Flags \r
1111 //\r
1112 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1113 //\r
1114 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1115 //\r
1116 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1117 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1118 if (EFI_ERROR (Status)) {\r
1119 goto Done;\r
1120 }\r
1121 //\r
1122 // Prepare new DefaultValue\r
1123 //\r
1124 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1125 if (DefaultData == NULL) {\r
1126 Status = EFI_OUT_OF_RESOURCES;\r
1127 goto Done;\r
1128 }\r
1129 DefaultData->DefaultId = VarDefaultId;\r
1130 DefaultData->DefaultName = VarDefaultName;\r
1131 DefaultData->Value = 1;\r
1132 //\r
1133 // Add DefaultValue into current BlockData\r
1134 //\r
1135 InsertDefaultValue (BlockData, DefaultData);\r
1136 }\r
1137\r
1138 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1139 //\r
1140 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1141 //\r
1142 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1143 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1144 if (EFI_ERROR (Status)) {\r
1145 goto Done;\r
1146 }\r
1147 //\r
1148 // Prepare new DefaultValue\r
1149 //\r
1150 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1151 if (DefaultData == NULL) {\r
1152 Status = EFI_OUT_OF_RESOURCES;\r
1153 goto Done;\r
1154 }\r
1155 DefaultData->DefaultId = VarDefaultId;\r
1156 DefaultData->DefaultName = VarDefaultName;\r
1157 DefaultData->Value = 1;\r
1158 //\r
1159 // Add DefaultValue into current BlockData\r
1160 //\r
1161 InsertDefaultValue (BlockData, DefaultData);\r
1162 }\r
1163 break;\r
1164\r
1165 case EFI_IFR_STRING_OP:\r
1166 //\r
1167 // offset by question header\r
1168 // width MaxSize * sizeof (CHAR16)\r
1169 // no default value, only block array\r
1170 //\r
1171\r
1172 //\r
1173 // Check whether this question is for the requested varstore.\r
1174 //\r
1175 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1176 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1177 break;\r
1178 }\r
1179 \r
1180 //\r
1181 // Get Offset/Width by Question header and OneOf Flags\r
1182 //\r
1183 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;\r
1184 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1185\r
1186 //\r
1187 // Check whether this question is in requested block array.\r
1188 //\r
1189 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1190 //\r
1191 // This question is not in the requested string. Skip it.\r
1192 //\r
1193 break;\r
1194 }\r
1195\r
1196 //\r
1197 // Check this var question is in the var storage \r
1198 //\r
1199 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1200 Status = EFI_INVALID_PARAMETER;\r
1201 goto Done;\r
1202 }\r
1203 \r
1204 //\r
1205 // Set Block Data\r
1206 //\r
1207 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1208 if (BlockData == NULL) {\r
1209 Status = EFI_OUT_OF_RESOURCES;\r
1210 goto Done;\r
1211 }\r
1212 BlockData->Offset = VarOffset;\r
1213 BlockData->Width = VarWidth;\r
1214 BlockData->QuestionId = IfrString->Question.QuestionId;\r
1215 BlockData->OpCode = IfrOpHdr->OpCode;\r
1216 InitializeListHead (&BlockData->DefaultValueEntry);\r
1217 \r
1218 //\r
1219 // Add Block Data into VarStorageData BlockEntry\r
1220 //\r
1221 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1222 \r
1223 //\r
1224 // No default value for string.\r
1225 //\r
1226 BlockData = NULL;\r
1227 break;\r
1228\r
1229 case EFI_IFR_PASSWORD_OP:\r
1230 //\r
1231 // offset by question header\r
1232 // width MaxSize * sizeof (CHAR16)\r
1233 // no default value, only block array\r
1234 //\r
1235\r
1236 //\r
1237 // Check whether this question is for the requested varstore.\r
1238 //\r
1239 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
1240 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1241 break;\r
1242 }\r
1243 \r
1244 //\r
1245 // Get Offset/Width by Question header and OneOf Flags\r
1246 //\r
1247 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;\r
1248 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
1249\r
1250 //\r
1251 // Check whether this question is in requested block array.\r
1252 //\r
1253 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1254 //\r
1255 // This question is not in the requested string. Skip it.\r
1256 //\r
1257 break;\r
1258 }\r
1259\r
1260 //\r
1261 // Check this var question is in the var storage \r
1262 //\r
1263 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1264 Status = EFI_INVALID_PARAMETER;\r
1265 goto Done;\r
1266 }\r
1267 \r
1268 //\r
1269 // Set Block Data\r
1270 //\r
1271 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1272 if (BlockData == NULL) {\r
1273 Status = EFI_OUT_OF_RESOURCES;\r
1274 goto Done;\r
1275 }\r
1276 BlockData->Offset = VarOffset;\r
1277 BlockData->Width = VarWidth;\r
1278 BlockData->QuestionId = IfrPassword->Question.QuestionId;\r
1279 BlockData->OpCode = IfrOpHdr->OpCode;\r
1280 InitializeListHead (&BlockData->DefaultValueEntry);\r
1281 \r
1282 //\r
1283 // Add Block Data into VarStorageData BlockEntry\r
1284 //\r
1285 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1286 \r
1287 //\r
1288 // No default value for string.\r
1289 //\r
1290 BlockData = NULL;\r
1291 break;\r
1292\r
1293 case EFI_IFR_ONE_OF_OPTION_OP:\r
1294 //\r
1295 // No matched block data is ignored.\r
1296 //\r
1297 if (BlockData == NULL || BlockData->Scope == 0) {\r
1298 break;\r
1299 }\r
1300 \r
1301 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1302 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1303 //\r
1304 // Get ordered list option data type.\r
1305 //\r
1306 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
1307 VarWidth = 1;\r
1308 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1309 VarWidth = 2;\r
1310 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1311 VarWidth = 4;\r
1312 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1313 VarWidth = 8;\r
1314 } else {\r
1315 //\r
1316 // Invalid ordered list option data type.\r
1317 //\r
1318 Status = EFI_INVALID_PARAMETER;\r
1319 goto Done;\r
1320 }\r
1321 //\r
1322 // Calculate Ordered list QuestionId width.\r
1323 //\r
1324 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
1325 BlockData = NULL;\r
1326 break;\r
1327 }\r
1328\r
1329 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
1330 //\r
1331 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1332 //\r
1333 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1334 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1335 if (EFI_ERROR (Status)) {\r
1336 goto Done;\r
1337 }\r
1338 //\r
1339 // Prepare new DefaultValue\r
1340 //\r
1341 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1342 if (DefaultData == NULL) {\r
1343 Status = EFI_OUT_OF_RESOURCES;\r
1344 goto Done;\r
1345 }\r
1346 DefaultData->DefaultId = VarDefaultId;\r
1347 DefaultData->DefaultName = VarDefaultName;\r
1348 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1349 //\r
1350 // Add DefaultValue into current BlockData\r
1351 //\r
1352 InsertDefaultValue (BlockData, DefaultData);\r
1353 }\r
1354\r
1355 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
1356 //\r
1357 // Set default ID to Manufacture ID and Get DefaultName String ID\r
1358 //\r
1359 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1360 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1361 if (EFI_ERROR (Status)) {\r
1362 goto Done;\r
1363 }\r
1364 //\r
1365 // Prepare new DefaultValue\r
1366 //\r
1367 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1368 if (DefaultData == NULL) {\r
1369 Status = EFI_OUT_OF_RESOURCES;\r
1370 goto Done;\r
1371 }\r
1372 DefaultData->DefaultId = VarDefaultId;\r
1373 DefaultData->DefaultName = VarDefaultName;\r
1374 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1375 //\r
1376 // Add DefaultValue into current BlockData\r
1377 //\r
1378 InsertDefaultValue (BlockData, DefaultData);\r
1379 }\r
1380 break;\r
1381\r
1382 case EFI_IFR_DEFAULT_OP:\r
1383 //\r
1384 // Update Current BlockData to the default value.\r
1385 //\r
1386 if (BlockData == NULL || BlockData->Scope == 0) {\r
1387 //\r
1388 // No matched block data is ignored. \r
1389 //\r
1390 break;\r
1391 }\r
1392\r
1393 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1394 //\r
1395 // OrderedList Opcode is no default value.\r
1396 //\r
1397 break;\r
1398 }\r
1399 //\r
1400 // Get the DefaultId and DefaultName String ID\r
1401 //\r
1402 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
1403 VarDefaultId = IfrDefault->DefaultId;\r
1404 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1405 if (EFI_ERROR (Status)) {\r
1406 goto Done;\r
1407 }\r
1408 //\r
1409 // Prepare new DefaultValue\r
1410 //\r
1411 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1412 if (DefaultData == NULL) {\r
1413 Status = EFI_OUT_OF_RESOURCES;\r
1414 goto Done;\r
1415 }\r
1416 DefaultData->DefaultId = VarDefaultId;\r
1417 DefaultData->DefaultName = VarDefaultName;\r
1418 DefaultData->Value = IfrDefault->Value.u64;\r
1419 //\r
1420 // Add DefaultValue into current BlockData\r
1421 //\r
1422 InsertDefaultValue (BlockData, DefaultData);\r
1423 break;\r
1424 case EFI_IFR_END_OP:\r
1425 //\r
1426 // End Opcode is for Var.\r
1427 //\r
1428 if (BlockData != NULL && BlockData->Scope > 0) {\r
1429 BlockData->Scope--;\r
1430 }\r
1431 break;\r
1432 default:\r
1433 if (BlockData != NULL && BlockData->Scope > 0) {\r
1434 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
1435 }\r
1436 break;\r
1437 }\r
1438\r
1439 IfrOffset += IfrOpHdr->Length;\r
1440 }\r
1441\r
1442Done:\r
1443 //\r
1444 // Set the defualt ID array.\r
1445 //\r
1446 *PIfrDefaultIdArray = DefaultIdArray;\r
1447\r
1448 return Status; \r
1449}\r
1450\r
1451/**\r
1452 This function gets the full request string and full default value string by \r
1453 parsing IFR data in HII form packages. \r
1454 \r
1455 When Request points to NULL string, the request string and default value string \r
1456 for each varstore in form package will return. \r
1457\r
1458 @param HiiHandle Hii Handle which Hii Packages are registered.\r
1459 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
1460 @param Request Pointer to a null-terminated Unicode string in\r
1461 <ConfigRequest> format. When it doesn't contain\r
1462 any RequestElement, it will be updated to return \r
1463 the full RequestElement retrieved from IFR data.\r
1464 If it points to NULL, the request string for the first\r
1465 varstore in form package will be merged into a\r
1466 <MultiConfigRequest> format string and return. \r
1467 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
1468 <ConfigAltResp> format. When the pointer is to NULL,\r
1469 the full default value string retrieved from IFR data\r
1470 will return. When the pinter is to a string, the\r
1471 full default value string retrieved from IFR data\r
1472 will be merged into the input string and return.\r
1473 When Request points to NULL, the default value string \r
1474 for each varstore in form package will be merged into \r
1475 a <MultiConfigAltResp> format string and return.\r
1476 @retval EFI_SUCCESS The Results string is set to the full request string.\r
1477 And AltCfgResp contains all default value string.\r
1478 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
1479 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
1480 can't be found in Form package.\r
1481 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
1482 @retval EFI_INVALID_PARAMETER *Request points to NULL.\r
1483\r
1484**/\r
1485EFI_STATUS\r
1486EFIAPI\r
1487GetFullStringFromHiiFormPackages (\r
1488 IN EFI_HII_HANDLE HiiHandle,\r
1489 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1490 IN OUT EFI_STRING *Request,\r
1491 IN OUT EFI_STRING *AltCfgResp\r
1492 )\r
1493{\r
1494 EFI_STATUS Status;\r
1495 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
1496 UINT32 PackageListLength; \r
1497 UINTN BufferSize;\r
1498 IFR_BLOCK_DATA *RequestBlockArray;\r
1499 IFR_BLOCK_DATA *BlockData;\r
1500 IFR_BLOCK_DATA *NextBlockData;\r
1501 IFR_DEFAULT_DATA *DefaultValueData;\r
1502 IFR_DEFAULT_DATA *DefaultId;\r
1503 IFR_DEFAULT_DATA *DefaultIdArray;\r
1504 EFI_HII_PACKAGE_HEADER PacakgeHeader;\r
1505 UINT32 PackageOffset;\r
1506 IFR_VARSTORAGE_DATA *VarStorageData;\r
1507 EFI_STRING DefaultAltCfgResp;\r
1508 EFI_STRING FullConfigRequest;\r
1509 EFI_STRING ConfigHdr;\r
1510 EFI_STRING GuidStr;\r
1511 EFI_STRING NameStr;\r
1512 EFI_STRING PathStr;\r
1513 EFI_STRING StringPtr;\r
1514 UINTN Length;\r
1515 UINT8 *TmpBuffer;\r
1516 UINT16 Offset;\r
1517 UINT16 Width;\r
1518 LIST_ENTRY *Link;\r
1519 LIST_ENTRY *LinkData;\r
1520 LIST_ENTRY *LinkDefault;\r
1521\r
1522 //\r
1523 // Initialize the local variables.\r
1524 //\r
1525 RequestBlockArray = NULL;\r
1526 VarStorageData = NULL;\r
1527 DefaultAltCfgResp = NULL;\r
1528 FullConfigRequest = NULL;\r
1529 ConfigHdr = NULL;\r
1530 DefaultIdArray = NULL;\r
1531 GuidStr = NULL;\r
1532 NameStr = NULL;\r
1533 PathStr = NULL;\r
1534\r
1535 //\r
1536 // 1. Get HiiPackage by HiiHandle\r
1537 //\r
1538 BufferSize = 0;\r
1539 HiiPackageList = NULL;\r
1540 Status = HiiExportPackageLists (&mPrivate.HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1541\r
1542 //\r
1543 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
1544 //\r
1545 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1546 return Status;\r
1547 }\r
1548\r
1549 HiiPackageList = AllocatePool (BufferSize);\r
1550 if (HiiPackageList == NULL) {\r
1551 return EFI_OUT_OF_RESOURCES;\r
1552 }\r
1553\r
1554 //\r
1555 // Get PackageList on HiiHandle\r
1556 //\r
1557 Status = HiiExportPackageLists (&mPrivate.HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1558 if (EFI_ERROR (Status)) {\r
1559 goto Done;\r
1560 }\r
1561\r
1562 //\r
1563 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
1564 // 1) Request is NULL.\r
1565 // 2) Request is not NULL. And it doesn't contain any BlockArray.\r
1566 // 3) Request is not NULL. And it containts BlockArray.\r
1567 //\r
1568\r
1569 //\r
1570 // Initialize VarStorageData to store the var store Block and Default value information.\r
1571 //\r
1572 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
1573 if (VarStorageData == NULL) {\r
1574 Status = EFI_OUT_OF_RESOURCES;\r
1575 goto Done;\r
1576 }\r
1577\r
1578 InitializeListHead (&VarStorageData->Entry);\r
1579 InitializeListHead (&VarStorageData->BlockEntry);\r
1580\r
1581 //\r
1582 // Gte the request block array by Request String \r
1583 //\r
1584 StringPtr = NULL;\r
1585 if (*Request != NULL) {\r
1586 StringPtr = StrStr (*Request, L"&OFFSET=");\r
1587 }\r
1588 if (StringPtr != NULL) {\r
1589 //\r
1590 // Init RequestBlockArray\r
1591 //\r
1592 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1593 if (RequestBlockArray == NULL) {\r
1594 Status = EFI_OUT_OF_RESOURCES;\r
1595 goto Done;\r
1596 }\r
1597 InitializeListHead (&RequestBlockArray->Entry);\r
1598\r
1599 //\r
1600 // Get the request Block array from the request string\r
1601 // Offset and Width\r
1602 //\r
1603\r
1604 //\r
1605 // Parse each <RequestElement> if exists\r
1606 // Only <BlockName> format is supported by this help function.\r
1607 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
1608 //\r
1609 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
1610 //\r
1611 // Skip the OFFSET string\r
1612 // \r
1613 StringPtr += StrLen (L"&OFFSET=");\r
1614 //\r
1615 // Get Offset\r
1616 //\r
1617 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1618 if (EFI_ERROR (Status)) {\r
1619 goto Done;\r
1620 }\r
1621 Offset = 0;\r
1622 CopyMem (\r
1623 &Offset,\r
1624 TmpBuffer,\r
1625 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1626 );\r
1627 FreePool (TmpBuffer);\r
1628 \r
1629 StringPtr += Length;\r
1630 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1631 Status = EFI_INVALID_PARAMETER;\r
1632 goto Done;\r
1633 }\r
1634 StringPtr += StrLen (L"&WIDTH=");\r
1635 \r
1636 //\r
1637 // Get Width\r
1638 //\r
1639 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1640 if (EFI_ERROR (Status)) {\r
1641 goto Done;\r
1642 }\r
1643 Width = 0;\r
1644 CopyMem (\r
1645 &Width,\r
1646 TmpBuffer,\r
1647 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1648 );\r
1649 FreePool (TmpBuffer);\r
1650\r
1651 StringPtr += Length;\r
1652 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1653 Status = EFI_INVALID_PARAMETER;\r
1654 goto Done;\r
1655 }\r
1656 \r
1657 //\r
1658 // Set Block Data\r
1659 //\r
1660 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1661 if (BlockData == NULL) {\r
1662 Status = EFI_OUT_OF_RESOURCES;\r
1663 goto Done;\r
1664 }\r
1665 BlockData->Offset = Offset;\r
1666 BlockData->Width = Width;\r
1667 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
1668\r
1669 //\r
1670 // If '\0', parsing is finished. \r
1671 //\r
1672 if (*StringPtr == 0) {\r
1673 break;\r
1674 }\r
1675 }\r
1676 \r
1677 //\r
1678 // Merge the requested block data.\r
1679 //\r
1680 Link = RequestBlockArray->Entry.ForwardLink;\r
1681 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
1682 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1683 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
1684 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
1685 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
1686 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
1687 }\r
1688 RemoveEntryList (Link->ForwardLink);\r
1689 FreePool (NextBlockData);\r
1690 continue;\r
1691 }\r
1692 Link = Link->ForwardLink; \r
1693 }\r
1694 }\r
1695 \r
1696 //\r
1697 // Get the form package\r
1698 //\r
1699 PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1700 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
1701 while (PackageOffset < PackageListLength) {\r
1702 CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
1703\r
1704 if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1705 //\r
1706 // Reset VarStorageData\r
1707 //\r
1708 VarStorageData->Size = 0;\r
1709 VarStorageData->VarStoreId = 0;\r
1710 if (VarStorageData->Name != NULL) {\r
1711 FreePool (VarStorageData->Name);\r
1712 VarStorageData->Name = NULL;\r
1713 }\r
1714\r
1715 //\r
1716 // Parse the opcode in form package \r
1717 //\r
1718 Status = ParseIfrData ((UINT8 *) HiiPackageList + PackageOffset, PacakgeHeader.Length, *Request, RequestBlockArray, VarStorageData, &DefaultIdArray);\r
1719 if (EFI_ERROR (Status)) {\r
1720 goto Done;\r
1721 }\r
1722\r
1723 //\r
1724 // Only one form is in a pacakge list.\r
1725 //\r
1726 break;\r
1727 }\r
1728\r
1729 PackageOffset += PacakgeHeader.Length;\r
1730 }\r
76c24251
LG
1731 \r
1732 //\r
1733 // No requested varstore in IFR data and directly return\r
1734 //\r
1735 if (VarStorageData->Size == 0) {\r
1736 goto Done;\r
1737 }\r
84f9a9ec
LG
1738\r
1739 //\r
1740 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
1741 //\r
1742\r
1743 //\r
1744 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
1745 //\r
1746 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
1747 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
1748 GenerateSubStr (\r
1749 L"PATH=",\r
1750 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
1751 (VOID *) DevicePath,\r
1752 1,\r
1753 &PathStr\r
1754 );\r
1755 Length = StrLen (GuidStr);\r
1756 Length = Length + StrLen (NameStr);\r
1757 Length = Length + StrLen (PathStr) + 1;\r
1758 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
1759 if (ConfigHdr == NULL) {\r
1760 Status = EFI_OUT_OF_RESOURCES;\r
1761 goto Done; \r
1762 }\r
1763 StrCpy (ConfigHdr, GuidStr);\r
1764 StrCat (ConfigHdr, NameStr);\r
1765 StrCat (ConfigHdr, PathStr);\r
1766\r
1767 //\r
1768 // Remove the last character L'&'\r
1769 //\r
1770 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';\r
1771\r
1772 if (RequestBlockArray == NULL) {\r
1773 //\r
1774 // Append VarStorageData BlockEntry into *Request string\r
1775 // Now support only one varstore in a form package.\r
1776 //\r
1777\r
1778 //\r
1779 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
1780 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
1781 //\r
1782\r
1783 //\r
1784 // Compute the length of the entire request starting with <ConfigHdr> and a \r
1785 // Null-terminator\r
1786 //\r
1787 Length = StrLen (ConfigHdr) + 1;\r
1788\r
1789 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1790 //\r
1791 // Add <BlockName> length for each Offset/Width pair\r
1792 //\r
1793 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
1794 // | 8 | 4 | 7 | 4 |\r
1795 //\r
1796 Length = Length + (8 + 4 + 7 + 4);\r
1797 }\r
1798 \r
1799 //\r
1800 // Allocate buffer for the entire <ConfigRequest>\r
1801 //\r
1802 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
1803 if (FullConfigRequest == NULL) {\r
1804 goto Done;\r
1805 }\r
1806 StringPtr = FullConfigRequest;\r
1807 \r
1808 //\r
1809 // Start with <ConfigHdr>\r
1810 //\r
1811 StrCpy (StringPtr, ConfigHdr);\r
1812 StringPtr += StrLen (StringPtr);\r
1813\r
1814 //\r
1815 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
1816 //\r
1817 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1818 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1819 //\r
1820 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
1821 //\r
1822 UnicodeSPrint (\r
1823 StringPtr, \r
1824 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
1825 L"&OFFSET=%04X&WIDTH=%04X", \r
1826 BlockData->Offset, \r
1827 BlockData->Width\r
1828 );\r
1829 StringPtr += StrLen (StringPtr);\r
1830 }\r
1831 //\r
1832 // Set to the got full request string.\r
1833 //\r
1834 HiiToLower (FullConfigRequest);\r
1835 if (*Request != NULL) {\r
1836 FreePool (*Request);\r
1837 }\r
1838 *Request = FullConfigRequest;\r
1839 }\r
1840 \r
1841 //\r
1842 // 4. Construct Default Value string in AltResp according to request element.\r
1843 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
1844 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
1845 //\r
93e3992d 1846\r
1847 //\r
84f9a9ec 1848 // Add length for <ConfigHdr> + '\0'\r
93e3992d 1849 //\r
84f9a9ec
LG
1850 Length = StrLen (ConfigHdr) + 1;\r
1851 \r
1852 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
1853 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
1854 //\r
1855 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
1856 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
1857 //\r
1858 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
1859 \r
1860 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
1861 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
1862 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
1863 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
1864 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
1865 //\r
1866 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
1867 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
1868 //\r
1869 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2); \r
1870 }\r
1871 }\r
1872 }\r
93e3992d 1873 }\r
84f9a9ec 1874\r
93e3992d 1875 //\r
84f9a9ec 1876 // Allocate buffer for the entire <DefaultAltCfgResp>\r
93e3992d 1877 //\r
84f9a9ec
LG
1878 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
1879 if (DefaultAltCfgResp == NULL) {\r
1880 goto Done;\r
1881 }\r
1882 StringPtr = DefaultAltCfgResp;\r
93e3992d 1883\r
84f9a9ec
LG
1884 //\r
1885 // Start with <ConfigHdr>\r
1886 //\r
1887 StrCpy (StringPtr, ConfigHdr);\r
1888 StringPtr += StrLen (StringPtr);\r
93e3992d 1889\r
84f9a9ec
LG
1890 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
1891 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
1892 //\r
1893 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
1894 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
1895 //\r
1896 UnicodeSPrint (\r
1897 StringPtr, \r
1898 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
1899 L"&%s&ALTCFG=%04X", \r
1900 ConfigHdr, \r
1901 DefaultId->DefaultName\r
1902 );\r
1903 StringPtr += StrLen (StringPtr);\r
1904 \r
1905 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
1906 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
1907 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
1908 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
1909 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
1910 //\r
1911 // Add <BlockConfig>\r
1912 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
1913 //\r
1914 UnicodeSPrint (\r
1915 StringPtr, \r
1916 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
1917 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
1918 BlockData->Offset, \r
1919 BlockData->Width\r
1920 );\r
1921 StringPtr += StrLen (StringPtr);\r
1922\r
1923 //\r
1924 // Convert Value to a hex string in "%x" format\r
1925 // NOTE: This is in the opposite byte that GUID and PATH use\r
1926 //\r
1927 Width = BlockData->Width;\r
1928 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
1929 for (; Width > 0; Width--) {\r
1930 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
1931 }\r
1932 }\r
1933 }\r
1934 }\r
93e3992d 1935 }\r
84f9a9ec 1936 HiiToLower (DefaultAltCfgResp);\r
93e3992d 1937\r
84f9a9ec
LG
1938 //\r
1939 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
1940 //\r
1941 if (*AltCfgResp != NULL) {\r
1942 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
1943 FreePool (DefaultAltCfgResp);\r
1944 } else {\r
1945 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 1946 }\r
93e3992d 1947\r
84f9a9ec
LG
1948Done:\r
1949 if (RequestBlockArray != NULL) {\r
1950 //\r
1951 // Free Link Array RequestBlockArray\r
1952 //\r
1953 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
1954 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
1955 RemoveEntryList (&BlockData->Entry);\r
1956 FreePool (BlockData);\r
1957 }\r
1958\r
1959 FreePool (RequestBlockArray);\r
93e3992d 1960 }\r
63d55bb9 1961 \r
84f9a9ec
LG
1962 if (VarStorageData != NULL) {\r
1963 //\r
1964 // Free link array VarStorageData\r
1965 //\r
1966 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
1967 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
1968 RemoveEntryList (&BlockData->Entry);\r
1969 //\r
1970 // Free default value link array\r
1971 //\r
1972 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
1973 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
1974 RemoveEntryList (&DefaultValueData->Entry);\r
1975 FreePool (DefaultValueData);\r
1976 }\r
1977 FreePool (BlockData);\r
63d55bb9 1978 }\r
84f9a9ec 1979 FreePool (VarStorageData);\r
93e3992d 1980 }\r
1981\r
84f9a9ec
LG
1982 if (DefaultIdArray != NULL) {\r
1983 //\r
1984 // Free DefaultId Array\r
1985 //\r
1986 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
1987 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
1988 RemoveEntryList (&DefaultId->Entry);\r
1989 FreePool (DefaultId);\r
1990 }\r
1991 FreePool (DefaultIdArray);\r
1992 }\r
1993 \r
1994 //\r
1995 // Free the allocated string \r
1996 //\r
1997 if (GuidStr != NULL) {\r
1998 FreePool (GuidStr);\r
1999 }\r
2000 if (NameStr != NULL) {\r
2001 FreePool (NameStr);\r
2002 }\r
2003 if (PathStr != NULL) {\r
2004 FreePool (PathStr);\r
2005 }\r
2006 if (ConfigHdr != NULL) {\r
2007 FreePool (ConfigHdr);\r
2008 }\r
93e3992d 2009\r
84f9a9ec
LG
2010 //\r
2011 // Free Pacakge data\r
2012 //\r
2013 if (HiiPackageList != NULL) {\r
2014 FreePool (HiiPackageList);\r
676df92c 2015 }\r
63d55bb9 2016\r
93e3992d 2017 return Status;\r
2018}\r
2019\r
93e3992d 2020/**\r
2021 This function allows a caller to extract the current configuration\r
2022 for one or more named elements from one or more drivers.\r
2023\r
2024 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2025 instance.\r
2026 @param Request A null-terminated Unicode string in\r
2027 <MultiConfigRequest> format.\r
2028 @param Progress On return, points to a character in the Request\r
2029 string. Points to the string's null terminator if\r
2030 request was successful. Points to the most recent\r
2031 & before the first failing name / value pair (or\r
2032 the beginning of the string if the failure is in\r
2033 the first name / value pair) if the request was\r
2034 not successful.\r
2035 @param Results Null-terminated Unicode string in\r
2036 <MultiConfigAltResp> format which has all values\r
2037 filled in for the names in the Request string.\r
2038 String to be allocated by the called function.\r
2039\r
2040 @retval EFI_SUCCESS The Results string is filled with the values\r
2041 corresponding to all requested names.\r
2042 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2043 results that must be stored awaiting possible\r
2044 future protocols.\r
2045 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
2046 Progress set to the "G" in "GUID" of the routing\r
2047 header that doesn't match. Note: There is no\r
2048 requirement that all routing data be validated\r
2049 before any configuration extraction.\r
2050 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
2051 parameter would result in this type of error. The\r
2052 Progress parameter is set to NULL.\r
2053 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
2054 before the error or the beginning of the string.\r
2055 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
2056 name in question.\r
2057\r
2058**/\r
2059EFI_STATUS\r
2060EFIAPI\r
2061HiiConfigRoutingExtractConfig (\r
2062 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2063 IN CONST EFI_STRING Request,\r
2064 OUT EFI_STRING *Progress,\r
2065 OUT EFI_STRING *Results\r
2066 )\r
2067{\r
84f9a9ec 2068 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2069 EFI_STRING StringPtr;\r
2070 EFI_STRING ConfigRequest;\r
2071 UINTN Length;\r
2072 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2073 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 2074 EFI_STATUS Status;\r
84f9a9ec
LG
2075 LIST_ENTRY *Link;\r
2076 HII_DATABASE_RECORD *Database;\r
2077 UINT8 *DevicePathPkg;\r
2078 UINT8 *CurrentDevicePath;\r
93e3992d 2079 EFI_HANDLE DriverHandle;\r
84f9a9ec 2080 EFI_HII_HANDLE HiiHandle;\r
93e3992d 2081 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2082 EFI_STRING AccessProgress;\r
2083 EFI_STRING AccessResults;\r
84f9a9ec 2084 EFI_STRING DefaultResults;\r
8d00a0f1 2085 BOOLEAN FirstElement;\r
84f9a9ec 2086 UINTN DevicePathLength;\r
93e3992d 2087\r
2088 if (This == NULL || Progress == NULL || Results == NULL) {\r
2089 return EFI_INVALID_PARAMETER;\r
2090 }\r
2091\r
2092 if (Request == NULL) {\r
2093 *Progress = NULL;\r
2094 return EFI_INVALID_PARAMETER;\r
2095 }\r
2096\r
84f9a9ec 2097 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2098 StringPtr = Request;\r
2099 *Progress = StringPtr;\r
84f9a9ec
LG
2100 DefaultResults = NULL;\r
2101 ConfigRequest = NULL;\r
2102 Status = EFI_SUCCESS;\r
2103 AccessResults = NULL;\r
2104 DevicePath = NULL;\r
93e3992d 2105\r
2106 //\r
2107 // The first element of <MultiConfigRequest> should be\r
2108 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2109 //\r
2110 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2111 return EFI_INVALID_PARAMETER;\r
2112 }\r
2113\r
8d00a0f1 2114 FirstElement = TRUE;\r
2115\r
93e3992d 2116 //\r
2117 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2118 // Results if this fix length is insufficient.\r
2119 //\r
2120 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2121 if (*Results == NULL) {\r
2122 return EFI_OUT_OF_RESOURCES;\r
2123 }\r
2124\r
2125 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2126 //\r
2127 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
2128 // or most recent & before the error.\r
2129 //\r
2130 if (StringPtr == Request) {\r
2131 *Progress = StringPtr;\r
2132 } else {\r
2133 *Progress = StringPtr - 1;\r
2134 }\r
2135\r
2136 //\r
2137 // Process each <ConfigRequest> of <MultiConfigRequest>\r
2138 //\r
2139 Length = CalculateConfigStringLen (StringPtr);\r
2140 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2141 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
2142 Status = EFI_OUT_OF_RESOURCES;\r
2143 goto Done;\r
93e3992d 2144 }\r
2145 *(ConfigRequest + Length) = 0;\r
2146\r
2147 //\r
2148 // Get the UEFI device path\r
2149 //\r
2150 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
2151 if (EFI_ERROR (Status)) {\r
84f9a9ec 2152 goto Done;\r
93e3992d 2153 }\r
2154\r
2155 //\r
84f9a9ec
LG
2156 // Find driver which matches the routing data.\r
2157 //\r
2158 DriverHandle = NULL;\r
2159 HiiHandle = NULL;\r
2160 DevicePathLength = GetDevicePathSize (DevicePath);\r
2161 for (Link = Private->DatabaseList.ForwardLink;\r
2162 Link != &Private->DatabaseList;\r
2163 Link = Link->ForwardLink\r
2164 ) {\r
2165 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2166 \r
2167 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2168 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
2169 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) && \r
2170 (CompareMem (\r
2171 DevicePath,\r
2172 CurrentDevicePath,\r
2173 DevicePathLength\r
2174 ) == 0)) {\r
2175 DriverHandle = Database->DriverHandle;\r
2176 HiiHandle = Database->Handle;\r
2177 break;\r
2178 }\r
2179 }\r
2180 }\r
2181 \r
2182 //\r
2183 // Try to find driver handle by device path.\r
93e3992d 2184 //\r
84f9a9ec
LG
2185 if (DriverHandle == NULL) {\r
2186 TempDevicePath = DevicePath;\r
2187 Status = gBS->LocateDevicePath (\r
2188 &gEfiDevicePathProtocolGuid,\r
2189 &TempDevicePath,\r
2190 &DriverHandle\r
2191 );\r
2192 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2193 //\r
2194 // Routing data does not match any known driver.\r
2195 // Set Progress to the 'G' in "GUID" of the routing header.\r
2196 //\r
2197 *Progress = StringPtr;\r
2198 Status = EFI_NOT_FOUND;\r
2199 goto Done;\r
2200 }\r
2201 }\r
2202 \r
2203 //\r
2204 // Check whether ConfigRequest contains request string OFFSET/WIDTH\r
2205 //\r
2206 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {\r
93e3992d 2207 //\r
84f9a9ec 2208 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 2209 //\r
84f9a9ec
LG
2210 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &DefaultResults);\r
2211 if (EFI_ERROR (Status)) {\r
2212 goto Done;\r
2213 }\r
76c24251
LG
2214 //\r
2215 // Not any request block is found.\r
2216 //\r
2217 if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {\r
2218 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
2219 goto NextConfigString;\r
2220 }\r
93e3992d 2221 }\r
2222\r
2223 //\r
2224 // Call corresponding ConfigAccess protocol to extract settings\r
2225 //\r
2226 Status = gBS->HandleProtocol (\r
2227 DriverHandle,\r
2228 &gEfiHiiConfigAccessProtocolGuid,\r
2229 (VOID **) &ConfigAccess\r
2230 );\r
2231 ASSERT_EFI_ERROR (Status);\r
2232\r
2233 Status = ConfigAccess->ExtractConfig (\r
2234 ConfigAccess,\r
2235 ConfigRequest,\r
2236 &AccessProgress,\r
2237 &AccessResults\r
2238 );\r
2239 if (EFI_ERROR (Status)) {\r
2240 //\r
2241 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
2242 // Map it to the progress on <MultiConfigRequest> then return it.\r
2243 //\r
8d00a0f1 2244 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 2245 goto Done;\r
93e3992d 2246 }\r
2247\r
2248 //\r
8d00a0f1 2249 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2250 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 2251 //\r
2252 ASSERT (*AccessProgress == 0);\r
8d00a0f1 2253\r
84f9a9ec
LG
2254 //\r
2255 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2256 //\r
2257 if (HiiHandle != NULL) {\r
2258 if (DefaultResults == NULL) {\r
2259 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &AccessResults);\r
2260 } else {\r
2261 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
2262 }\r
2263 }\r
2264 FreePool (DevicePath);\r
2265 DevicePath = NULL;\r
2266 \r
2267 if (EFI_ERROR (Status)) {\r
2268 goto Done;\r
2269 }\r
2270\r
2271 //\r
2272 // Free the allocated memory.\r
2273 //\r
2274 if (DefaultResults != NULL) {\r
2275 FreePool (DefaultResults);\r
2276 DefaultResults = NULL;\r
2277 }\r
76c24251
LG
2278\r
2279NextConfigString: \r
8d00a0f1 2280 if (!FirstElement) {\r
2281 Status = AppendToMultiString (Results, L"&");\r
2282 ASSERT_EFI_ERROR (Status);\r
2283 }\r
2284 \r
93e3992d 2285 Status = AppendToMultiString (Results, AccessResults);\r
2286 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 2287\r
2288 FirstElement = FALSE;\r
84f9a9ec 2289\r
676df92c 2290 FreePool (AccessResults);\r
93e3992d 2291 AccessResults = NULL;\r
676df92c 2292 FreePool (ConfigRequest);\r
93e3992d 2293 ConfigRequest = NULL;\r
2294\r
2295 //\r
2296 // Go to next <ConfigRequest> (skip '&').\r
2297 //\r
2298 StringPtr += Length;\r
2299 if (*StringPtr == 0) {\r
2300 *Progress = StringPtr;\r
2301 break;\r
2302 }\r
2303\r
2304 StringPtr++;\r
93e3992d 2305 }\r
2306\r
84f9a9ec
LG
2307Done:\r
2308 if (EFI_ERROR (Status)) {\r
2309 FreePool (*Results);\r
76c24251 2310 *Results = NULL;\r
84f9a9ec
LG
2311 }\r
2312 \r
2313 if (ConfigRequest != NULL) {\r
2314 FreePool (ConfigRequest);\r
2315 }\r
2316 \r
2317 if (AccessResults != NULL) {\r
2318 FreePool (AccessResults);\r
2319 }\r
2320 \r
2321 if (DefaultResults != NULL) {\r
2322 FreePool (DefaultResults);\r
2323 }\r
2324 \r
2325 if (DevicePath != NULL) {\r
2326 FreePool (DevicePath);\r
2327 } \r
93e3992d 2328\r
84f9a9ec 2329 return Status;\r
93e3992d 2330}\r
2331\r
2332\r
2333/**\r
2334 This function allows the caller to request the current configuration for the\r
2335 entirety of the current HII database and returns the data in a\r
2336 null-terminated Unicode string.\r
2337\r
2338 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2339 instance.\r
2340 @param Results Null-terminated Unicode string in\r
2341 <MultiConfigAltResp> format which has all values\r
2342 filled in for the names in the Request string.\r
2343 String to be allocated by the called function.\r
2344 De-allocation is up to the caller.\r
2345\r
2346 @retval EFI_SUCCESS The Results string is filled with the values\r
2347 corresponding to all requested names.\r
2348 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2349 results that must be stored awaiting possible\r
2350 future protocols.\r
2351 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
2352 parameter would result in this type of error.\r
2353\r
2354**/\r
2355EFI_STATUS\r
2356EFIAPI\r
2357HiiConfigRoutingExportConfig (\r
2358 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2359 OUT EFI_STRING *Results\r
2360 )\r
2361{\r
93e3992d 2362 EFI_STATUS Status;\r
93e3992d 2363 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
2364 EFI_STRING AccessResults;\r
2365 EFI_STRING Progress;\r
2366 EFI_STRING ConfigRequest;\r
8d00a0f1 2367 UINTN Index;\r
2368 EFI_HANDLE *ConfigAccessHandles;\r
2369 UINTN NumberConfigAccessHandles;\r
2370 BOOLEAN FirstElement;\r
84f9a9ec
LG
2371 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2372 EFI_HII_HANDLE HiiHandle;\r
2373 EFI_STRING DefaultResults;\r
2374 HII_DATABASE_PRIVATE_DATA *Private;\r
2375 LIST_ENTRY *Link;\r
2376 HII_DATABASE_RECORD *Database;\r
2377 UINT8 *DevicePathPkg;\r
2378 UINT8 *CurrentDevicePath;\r
2379 UINTN DevicePathLength;\r
93e3992d 2380\r
2381 if (This == NULL || Results == NULL) {\r
2382 return EFI_INVALID_PARAMETER;\r
2383 }\r
2384\r
84f9a9ec
LG
2385 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2386\r
93e3992d 2387 //\r
2388 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2389 // Results if this fix length is insufficient.\r
2390 //\r
2391 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2392 if (*Results == NULL) {\r
2393 return EFI_OUT_OF_RESOURCES;\r
2394 }\r
2395\r
8d00a0f1 2396 NumberConfigAccessHandles = 0;\r
2397 Status = gBS->LocateHandleBuffer (\r
2398 ByProtocol,\r
2399 &gEfiHiiConfigAccessProtocolGuid,\r
2400 NULL,\r
2401 &NumberConfigAccessHandles,\r
2402 &ConfigAccessHandles\r
2403 );\r
2404 if (EFI_ERROR (Status)) {\r
2405 return Status;\r
2406 }\r
93e3992d 2407\r
8d00a0f1 2408 FirstElement = TRUE;\r
93e3992d 2409\r
8d00a0f1 2410 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 2411 Status = gBS->HandleProtocol (\r
8d00a0f1 2412 ConfigAccessHandles[Index],\r
93e3992d 2413 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 2414 (VOID **) &ConfigAccess\r
93e3992d 2415 );\r
8d00a0f1 2416 if (EFI_ERROR (Status)) {\r
2417 continue;\r
2418 }\r
93e3992d 2419\r
84f9a9ec
LG
2420 //\r
2421 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
2422 //\r
2423 Progress = NULL;\r
2424 HiiHandle = NULL;\r
2425 ConfigRequest = NULL;\r
2426 DefaultResults = NULL;\r
2427 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
2428 DevicePathLength = GetDevicePathSize (DevicePath);\r
2429 if (DevicePath != NULL) {\r
2430 for (Link = Private->DatabaseList.ForwardLink;\r
2431 Link != &Private->DatabaseList;\r
2432 Link = Link->ForwardLink\r
2433 ) {\r
2434 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2435 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2436 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
2437 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) &&\r
2438 (CompareMem (\r
2439 DevicePath,\r
2440 CurrentDevicePath,\r
2441 DevicePathLength\r
2442 ) == 0)) {\r
2443 HiiHandle = Database->Handle;\r
2444 break;\r
2445 }\r
2446 }\r
2447 }\r
2448 }\r
2449\r
2450 //\r
2451 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2452 //\r
2453 if (HiiHandle != NULL && DevicePath != NULL) {\r
2454 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &DefaultResults);\r
2455 }\r
2456 //\r
2457 // Can't parse IFR data to get the request string and default string.\r
2458 //\r
2459 if (EFI_ERROR (Status)) {\r
2460 ConfigRequest = NULL;\r
2461 DefaultResults = NULL;\r
2462 }\r
2463 \r
93e3992d 2464 Status = ConfigAccess->ExtractConfig (\r
2465 ConfigAccess,\r
84f9a9ec
LG
2466 ConfigRequest,\r
2467 &Progress,\r
93e3992d 2468 &AccessResults\r
2469 );\r
8d00a0f1 2470 if (!EFI_ERROR (Status)) {\r
84f9a9ec
LG
2471 //\r
2472 // Merge the default sting from IFR code into the got setting from driver.\r
2473 //\r
2474 if (DefaultResults != NULL) {\r
2475 MergeDefaultString (&AccessResults, DefaultResults);\r
2476 FreePool (DefaultResults);\r
2477 }\r
2478 \r
8d00a0f1 2479 //\r
2480 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2481 // which seperates the first <ConfigAltResp> and the following ones. \r
2482 //\r
2483 if (!FirstElement) {\r
2484 Status = AppendToMultiString (Results, L"&");\r
2485 ASSERT_EFI_ERROR (Status);\r
676df92c 2486 }\r
8d00a0f1 2487 \r
2488 Status = AppendToMultiString (Results, AccessResults);\r
2489 ASSERT_EFI_ERROR (Status);\r
93e3992d 2490\r
8d00a0f1 2491 FirstElement = FALSE;\r
2492 \r
2493 FreePool (AccessResults);\r
2494 AccessResults = NULL;\r
2495 }\r
93e3992d 2496 }\r
f4113e1f 2497 FreePool (ConfigAccessHandles);\r
93e3992d 2498\r
8d00a0f1 2499 return EFI_SUCCESS; \r
93e3992d 2500}\r
2501\r
2502\r
2503/**\r
2504 This function processes the results of processing forms and routes it to the\r
2505 appropriate handlers or storage.\r
2506\r
2507 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2508 instance.\r
2509 @param Configuration A null-terminated Unicode string in\r
2510 <MulltiConfigResp> format.\r
2511 @param Progress A pointer to a string filled in with the offset of\r
2512 the most recent & before the first failing name /\r
2513 value pair (or the beginning of the string if the\r
2514 failure is in the first name / value pair) or the\r
2515 terminating NULL if all was successful.\r
2516\r
2517 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
2518 distribution.\r
2519 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2520 results that must be stored awaiting possible\r
2521 future protocols.\r
2522 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
2523 would result in this type of error.\r
2524 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
2525 found.\r
2526\r
2527**/\r
2528EFI_STATUS\r
2529EFIAPI\r
813acf3a 2530HiiConfigRoutingRouteConfig (\r
93e3992d 2531 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2532 IN CONST EFI_STRING Configuration,\r
2533 OUT EFI_STRING *Progress\r
2534 )\r
2535{\r
84f9a9ec 2536 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2537 EFI_STRING StringPtr;\r
2538 EFI_STRING ConfigResp;\r
2539 UINTN Length;\r
2540 EFI_STATUS Status;\r
2541 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2542 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
2543 LIST_ENTRY *Link;\r
2544 HII_DATABASE_RECORD *Database;\r
2545 UINT8 *DevicePathPkg;\r
2546 UINT8 *CurrentDevicePath;\r
93e3992d 2547 EFI_HANDLE DriverHandle;\r
2548 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2549 EFI_STRING AccessProgress;\r
84f9a9ec 2550 UINTN DevicePathLength;\r
93e3992d 2551\r
2552 if (This == NULL || Progress == NULL) {\r
2553 return EFI_INVALID_PARAMETER;\r
2554 }\r
2555\r
2556 if (Configuration == NULL) {\r
2557 *Progress = NULL;\r
2558 return EFI_INVALID_PARAMETER;\r
2559 }\r
2560\r
84f9a9ec 2561 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2562 StringPtr = Configuration;\r
2563 *Progress = StringPtr;\r
2564\r
2565 //\r
2566 // The first element of <MultiConfigResp> should be\r
2567 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2568 //\r
2569 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2570 return EFI_INVALID_PARAMETER;\r
2571 }\r
2572\r
2573 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2574 //\r
2575 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
2576 // or most recent & before the error.\r
2577 //\r
2578 if (StringPtr == Configuration) {\r
2579 *Progress = StringPtr;\r
2580 } else {\r
2581 *Progress = StringPtr - 1;\r
2582 }\r
2583\r
2584 //\r
2585 // Process each <ConfigResp> of <MultiConfigResp>\r
2586 //\r
2587 Length = CalculateConfigStringLen (StringPtr);\r
2588 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2589 if (ConfigResp == NULL) {\r
2590 return EFI_OUT_OF_RESOURCES;\r
2591 }\r
2592 //\r
2593 // Append '\0' to the end of ConfigRequest\r
2594 //\r
2595 *(ConfigResp + Length) = 0;\r
2596\r
2597 //\r
2598 // Get the UEFI device path\r
2599 //\r
2600 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
2601 if (EFI_ERROR (Status)) {\r
676df92c 2602 FreePool (ConfigResp);\r
93e3992d 2603 return Status;\r
2604 }\r
2605\r
2606 //\r
84f9a9ec
LG
2607 // Find driver which matches the routing data.\r
2608 //\r
2609 DriverHandle = NULL;\r
2610 DevicePathLength = GetDevicePathSize (DevicePath);\r
2611 for (Link = Private->DatabaseList.ForwardLink;\r
2612 Link != &Private->DatabaseList;\r
2613 Link = Link->ForwardLink\r
2614 ) {\r
2615 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2616\r
2617 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2618 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
2619 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) &&\r
2620 (CompareMem (\r
2621 DevicePath,\r
2622 CurrentDevicePath,\r
2623 DevicePathLength\r
2624 ) == 0)) {\r
2625 DriverHandle = Database->DriverHandle;\r
2626 break;\r
2627 }\r
2628 }\r
2629 }\r
93e3992d 2630\r
84f9a9ec
LG
2631 //\r
2632 // Try to find driver handle by device path.\r
2633 //\r
2634 if (DriverHandle == NULL) {\r
2635 TempDevicePath = DevicePath;\r
2636 Status = gBS->LocateDevicePath (\r
2637 &gEfiDevicePathProtocolGuid,\r
2638 &TempDevicePath,\r
2639 &DriverHandle\r
2640 );\r
2641 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2642 //\r
2643 // Routing data does not match any known driver.\r
2644 // Set Progress to the 'G' in "GUID" of the routing header.\r
2645 //\r
2646 FreePool (DevicePath);\r
2647 *Progress = StringPtr;\r
2648 FreePool (ConfigResp);\r
2649 return EFI_NOT_FOUND;\r
2650 }\r
93e3992d 2651 }\r
2652\r
84f9a9ec
LG
2653 FreePool (DevicePath);\r
2654\r
93e3992d 2655 //\r
2656 // Call corresponding ConfigAccess protocol to route settings\r
2657 //\r
2658 Status = gBS->HandleProtocol (\r
2659 DriverHandle,\r
2660 &gEfiHiiConfigAccessProtocolGuid,\r
2661 (VOID **) &ConfigAccess\r
2662 );\r
2663 ASSERT_EFI_ERROR (Status);\r
2664\r
2665 Status = ConfigAccess->RouteConfig (\r
2666 ConfigAccess,\r
2667 ConfigResp,\r
2668 &AccessProgress\r
2669 );\r
2670\r
2671 if (EFI_ERROR (Status)) {\r
2672 //\r
2673 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
2674 // Map it to the progress on <MultiConfigResp> then return it.\r
2675 //\r
8d00a0f1 2676 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 2677\r
676df92c 2678 FreePool (ConfigResp);\r
93e3992d 2679 return Status;\r
2680 }\r
2681\r
676df92c 2682 FreePool (ConfigResp);\r
93e3992d 2683 ConfigResp = NULL;\r
2684\r
2685 //\r
2686 // Go to next <ConfigResp> (skip '&').\r
2687 //\r
2688 StringPtr += Length;\r
2689 if (*StringPtr == 0) {\r
2690 *Progress = StringPtr;\r
2691 break;\r
2692 }\r
2693\r
2694 StringPtr++;\r
2695\r
2696 }\r
2697\r
2698 return EFI_SUCCESS;\r
93e3992d 2699}\r
2700\r
2701\r
2702/**\r
2703 This helper function is to be called by drivers to map configuration data\r
2704 stored in byte array ("block") formats such as UEFI Variables into current\r
2705 configuration strings.\r
2706\r
2707 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2708 instance.\r
2709 @param ConfigRequest A null-terminated Unicode string in\r
2710 <ConfigRequest> format.\r
2711 @param Block Array of bytes defining the block's configuration.\r
2712 @param BlockSize Length in bytes of Block.\r
2713 @param Config Filled-in configuration string. String allocated\r
2714 by the function. Returned only if call is\r
84f9a9ec 2715 successful. It is <ConfigResp> string format.\r
93e3992d 2716 @param Progress A pointer to a string filled in with the offset of\r
2717 the most recent & before the first failing\r
2718 name/value pair (or the beginning of the string if\r
2719 the failure is in the first name / value pair) or\r
2720 the terminating NULL if all was successful.\r
2721\r
2722 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
2723 terminator at the end of the ConfigRequest\r
2724 string.\r
2725 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
2726 points to the first character of ConfigRequest.\r
2727 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
2728 Block parameter would result in this type of\r
2729 error. Progress points to the first character of\r
2730 ConfigRequest.\r
2731 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
2732 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
2733 Block is left updated and Progress points at\r
2734 the "&" preceding the first non-<BlockName>.\r
2735\r
2736**/\r
2737EFI_STATUS\r
2738EFIAPI\r
2739HiiBlockToConfig (\r
2740 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2741 IN CONST EFI_STRING ConfigRequest,\r
2742 IN CONST UINT8 *Block,\r
2743 IN CONST UINTN BlockSize,\r
2744 OUT EFI_STRING *Config,\r
2745 OUT EFI_STRING *Progress\r
2746 )\r
2747{\r
84f9a9ec 2748 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2749 EFI_STRING StringPtr;\r
2750 UINTN Length;\r
2751 EFI_STATUS Status;\r
2752 EFI_STRING TmpPtr;\r
2753 UINT8 *TmpBuffer;\r
2754 UINTN Offset;\r
2755 UINTN Width;\r
2756 UINT8 *Value;\r
2757 EFI_STRING ValueStr;\r
2758 EFI_STRING ConfigElement;\r
63d55bb9
LG
2759 UINTN Index;\r
2760 UINT8 *TemBuffer;\r
2761 CHAR16 *TemString;\r
93e3992d 2762\r
2763 if (This == NULL || Progress == NULL || Config == NULL) {\r
2764 return EFI_INVALID_PARAMETER;\r
2765 }\r
2766\r
2767 if (Block == NULL || ConfigRequest == NULL) {\r
2768 *Progress = ConfigRequest;\r
2769 return EFI_INVALID_PARAMETER;\r
2770 }\r
2771\r
84f9a9ec
LG
2772\r
2773 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2774 ASSERT (Private != NULL);\r
2775\r
93e3992d 2776 StringPtr = ConfigRequest;\r
2777 ValueStr = NULL;\r
2778 Value = NULL;\r
2779 ConfigElement = NULL;\r
2780\r
2781 //\r
2782 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2783 // Results if this fix length is insufficient.\r
2784 //\r
2785 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2786 if (*Config == NULL) {\r
2787 return EFI_OUT_OF_RESOURCES;\r
2788 }\r
2789\r
2790 //\r
2791 // Jump <ConfigHdr>\r
2792 //\r
2793 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2794 *Progress = StringPtr;\r
2795 Status = EFI_INVALID_PARAMETER;\r
2796 goto Exit;\r
2797 }\r
2798 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
2799 StringPtr++;\r
2800 }\r
2801 if (*StringPtr == 0) {\r
76c24251 2802 *Progress = StringPtr - 1;\r
93e3992d 2803 Status = EFI_INVALID_PARAMETER;\r
2804 goto Exit;\r
2805 }\r
08e6463a 2806\r
2807 while (*StringPtr != L'&' && *StringPtr != 0) {\r
2808 StringPtr++;\r
2809 }\r
2810 if (*StringPtr == 0) {\r
76c24251 2811 *Progress = StringPtr - 1;\r
08e6463a 2812 Status = EFI_INVALID_PARAMETER;\r
2813 goto Exit;\r
2814 }\r
2815 //\r
2816 // Skip '&'\r
2817 //\r
2818 StringPtr++;\r
93e3992d 2819\r
2820 //\r
2821 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
2822 //\r
2823 Length = StringPtr - ConfigRequest;\r
2824 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
2825\r
2826 //\r
2827 // Parse each <RequestElement> if exists\r
2828 // Only <BlockName> format is supported by this help function.\r
2829 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
2830 //\r
2831 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
2832 //\r
2833 // Back up the header of one <BlockName>\r
2834 //\r
2835 TmpPtr = StringPtr;\r
2836\r
2837 StringPtr += StrLen (L"OFFSET=");\r
2838 //\r
2839 // Get Offset\r
2840 //\r
2841 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2842 if (Status == EFI_OUT_OF_RESOURCES) {\r
2843 *Progress = ConfigRequest;\r
2844 goto Exit;\r
2845 }\r
2846 Offset = 0;\r
2847 CopyMem (\r
2848 &Offset,\r
2849 TmpBuffer,\r
2850 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
2851 );\r
676df92c 2852 FreePool (TmpBuffer);\r
93e3992d 2853\r
2854 StringPtr += Length;\r
2855 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
2856 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
2857 Status = EFI_INVALID_PARAMETER;\r
2858 goto Exit;\r
2859 }\r
2860 StringPtr += StrLen (L"&WIDTH=");\r
2861\r
2862 //\r
2863 // Get Width\r
2864 //\r
2865 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2866 if (Status == EFI_OUT_OF_RESOURCES) {\r
2867 *Progress = ConfigRequest;\r
2868 goto Exit;\r
2869 }\r
2870 Width = 0;\r
2871 CopyMem (\r
2872 &Width,\r
2873 TmpBuffer,\r
2874 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
2875 );\r
676df92c 2876 FreePool (TmpBuffer);\r
93e3992d 2877\r
2878 StringPtr += Length;\r
2879 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2880 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
2881 Status = EFI_INVALID_PARAMETER;\r
2882 goto Exit;\r
2883 }\r
2884\r
2885 //\r
2886 // Calculate Value and convert it to hex string.\r
2887 //\r
2888 if (Offset + Width > BlockSize) {\r
2889 *Progress = StringPtr;\r
2890 Status = EFI_DEVICE_ERROR;\r
2891 goto Exit;\r
2892 }\r
2893\r
2894 Value = (UINT8 *) AllocateZeroPool (Width);\r
2895 if (Value == NULL) {\r
2896 *Progress = ConfigRequest;\r
2897 Status = EFI_OUT_OF_RESOURCES;\r
2898 goto Exit;\r
2899 }\r
2900\r
2901 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
2902\r
2903 Length = Width * 2 + 1;\r
2904 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
2905 if (ValueStr == NULL) {\r
2906 *Progress = ConfigRequest;\r
2907 Status = EFI_OUT_OF_RESOURCES;\r
2908 goto Exit;\r
2909 }\r
63d55bb9
LG
2910 \r
2911 TemString = ValueStr;\r
2912 TemBuffer = Value + Width - 1;\r
2913 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
2914 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
2915 }\r
813acf3a 2916\r
676df92c 2917 FreePool (Value);\r
93e3992d 2918 Value = NULL;\r
2919\r
2920 //\r
2921 // Build a ConfigElement\r
2922 //\r
2923 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
2924 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
2925 if (ConfigElement == NULL) {\r
2926 Status = EFI_OUT_OF_RESOURCES;\r
2927 goto Exit;\r
2928 }\r
2929 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
2930 if (*StringPtr == 0) {\r
2931 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
2932 }\r
2933 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
2934 StrCat (ConfigElement, L"VALUE=");\r
2935 StrCat (ConfigElement, ValueStr);\r
2936\r
2937 AppendToMultiString (Config, ConfigElement);\r
2938\r
676df92c 2939 FreePool (ConfigElement);\r
2940 FreePool (ValueStr);\r
93e3992d 2941 ConfigElement = NULL;\r
2942 ValueStr = NULL;\r
2943\r
2944 //\r
2945 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
2946 //\r
2947 if (*StringPtr == 0) {\r
2948 break;\r
2949 }\r
2950 AppendToMultiString (Config, L"&");\r
2951 StringPtr++;\r
2952\r
2953 }\r
2954\r
2955 if (*StringPtr != 0) {\r
2956 *Progress = StringPtr - 1;\r
2957 Status = EFI_INVALID_PARAMETER;\r
2958 goto Exit;\r
2959 }\r
84f9a9ec
LG
2960 \r
2961 HiiToLower (*Config);\r
93e3992d 2962 *Progress = StringPtr;\r
2963 return EFI_SUCCESS;\r
2964\r
2965Exit:\r
76c24251
LG
2966 if (*Config != NULL) {\r
2967 FreePool (*Config);\r
2968 *Config = NULL;\r
2969 }\r
676df92c 2970 if (ValueStr != NULL) {\r
2971 FreePool (ValueStr);\r
2972 }\r
2973 if (Value != NULL) {\r
2974 FreePool (Value);\r
2975 }\r
69367b5b 2976 if (ConfigElement != NULL) {\r
676df92c 2977 FreePool (ConfigElement);\r
2978 }\r
93e3992d 2979\r
2980 return Status;\r
2981\r
2982}\r
2983\r
2984\r
2985/**\r
2986 This helper function is to be called by drivers to map configuration strings\r
2987 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
2988\r
2989 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2990 instance.\r
2991 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
84f9a9ec 2992 format. It can be ConfigAltResp format string.\r
93e3992d 2993 @param Block A possibly null array of bytes representing the\r
2994 current block. Only bytes referenced in the\r
2995 ConfigResp string in the block are modified. If\r
2996 this parameter is null or if the *BlockSize\r
2997 parameter is (on input) shorter than required by\r
2998 the Configuration string, only the BlockSize\r
2999 parameter is updated and an appropriate status\r
3000 (see below) is returned.\r
3001 @param BlockSize The length of the Block in units of UINT8. On\r
3002 input, this is the size of the Block. On output,\r
3003 if successful, contains the index of the last\r
3004 modified byte in the Block.\r
3005 @param Progress On return, points to an element of the ConfigResp\r
3006 string filled in with the offset of the most\r
3007 recent '&' before the first failing name / value\r
3008 pair (or the beginning of the string if the\r
3009 failure is in the first name / value pair) or the\r
3010 terminating NULL if all was successful.\r
3011\r
3012 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
3013 terminator at the end of the ConfigResp string.\r
3014 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
3015 points to the first character of ConfigResp.\r
3016 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
3017 Block parameter would result in this type of\r
3018 error. Progress points to the first character of\r
3019 ConfigResp.\r
3020 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
3021 value pair. Block is left updated and\r
3022 Progress points at the '&' preceding the first\r
3023 non-<BlockName>.\r
3024\r
3025**/\r
3026EFI_STATUS\r
3027EFIAPI\r
3028HiiConfigToBlock (\r
3029 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3030 IN CONST EFI_STRING ConfigResp,\r
3031 IN OUT UINT8 *Block,\r
3032 IN OUT UINTN *BlockSize,\r
3033 OUT EFI_STRING *Progress\r
3034 )\r
3035{\r
3036 HII_DATABASE_PRIVATE_DATA *Private;\r
3037 EFI_STRING StringPtr;\r
3038 UINTN Length;\r
3039 EFI_STATUS Status;\r
3040 UINT8 *TmpBuffer;\r
3041 UINTN Offset;\r
3042 UINTN Width;\r
3043 UINT8 *Value;\r
3044 UINTN BufferSize;\r
3045\r
3046 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
3047 return EFI_INVALID_PARAMETER;\r
3048 }\r
3049\r
3050 if (ConfigResp == NULL || Block == NULL) {\r
3051 *Progress = ConfigResp;\r
3052 return EFI_INVALID_PARAMETER;\r
3053 }\r
3054\r
3055 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3056 ASSERT (Private != NULL);\r
3057\r
3058 StringPtr = ConfigResp;\r
3059 BufferSize = *BlockSize;\r
3060 Value = NULL;\r
3061\r
3062 //\r
3063 // Jump <ConfigHdr>\r
3064 //\r
3065 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3066 *Progress = StringPtr;\r
3067 Status = EFI_INVALID_PARAMETER;\r
3068 goto Exit;\r
3069 }\r
3070 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
3071 StringPtr++;\r
3072 }\r
3073 if (*StringPtr == 0) {\r
3074 *Progress = StringPtr;\r
3075 Status = EFI_INVALID_PARAMETER;\r
3076 goto Exit;\r
3077 }\r
08e6463a 3078\r
3079 while (*StringPtr != L'&' && *StringPtr != 0) {\r
3080 StringPtr++;\r
3081 }\r
3082 if (*StringPtr == 0) {\r
3083 *Progress = StringPtr;\r
3084 Status = EFI_INVALID_PARAMETER;\r
3085 goto Exit;\r
3086 }\r
3087 //\r
3088 // Skip '&'\r
3089 //\r
3090 StringPtr++;\r
93e3992d 3091\r
3092 //\r
3093 // Parse each <ConfigElement> if exists\r
3094 // Only <BlockConfig> format is supported by this help function.\r
3095 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
3096 //\r
3097 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
3098 StringPtr += StrLen (L"OFFSET=");\r
3099 //\r
3100 // Get Offset\r
3101 //\r
3102 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 3103 if (EFI_ERROR (Status)) {\r
93e3992d 3104 *Progress = ConfigResp;\r
3105 goto Exit;\r
3106 }\r
3107 Offset = 0;\r
3108 CopyMem (\r
3109 &Offset,\r
3110 TmpBuffer,\r
3111 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3112 );\r
676df92c 3113 FreePool (TmpBuffer);\r
93e3992d 3114\r
3115 StringPtr += Length;\r
3116 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3117 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
3118 Status = EFI_INVALID_PARAMETER;\r
3119 goto Exit;\r
3120 }\r
3121 StringPtr += StrLen (L"&WIDTH=");\r
3122\r
3123 //\r
3124 // Get Width\r
3125 //\r
3126 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3127 if (Status == EFI_OUT_OF_RESOURCES) {\r
3128 *Progress = ConfigResp;\r
3129 goto Exit;\r
3130 }\r
3131 Width = 0;\r
3132 CopyMem (\r
3133 &Width,\r
3134 TmpBuffer,\r
3135 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3136 );\r
676df92c 3137 FreePool (TmpBuffer);\r
93e3992d 3138\r
3139 StringPtr += Length;\r
3140 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
3141 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
3142 Status = EFI_INVALID_PARAMETER;\r
3143 goto Exit;\r
3144 }\r
3145 StringPtr += StrLen (L"&VALUE=");\r
3146\r
3147 //\r
3148 // Get Value\r
3149 //\r
3150 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 3151 if (EFI_ERROR (Status)) {\r
93e3992d 3152 *Progress = ConfigResp;\r
3153 goto Exit;\r
3154 }\r
3155\r
3156 StringPtr += Length;\r
3157 if (*StringPtr != 0 && *StringPtr != L'&') {\r
3158 *Progress = StringPtr - Length - 7;\r
3159 Status = EFI_INVALID_PARAMETER;\r
3160 goto Exit;\r
3161 }\r
3162\r
3163 //\r
3164 // Update the Block with configuration info\r
3165 //\r
3166\r
3167 if (Offset + Width > BufferSize) {\r
3168 return EFI_DEVICE_ERROR;\r
3169 }\r
3170\r
3171 CopyMem (Block + Offset, Value, Width);\r
3172 *BlockSize = Offset + Width - 1;\r
3173\r
676df92c 3174 FreePool (Value);\r
93e3992d 3175 Value = NULL;\r
3176\r
3177 //\r
3178 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
3179 //\r
3180 if (*StringPtr == 0) {\r
3181 break;\r
3182 }\r
3183\r
3184 StringPtr++;\r
3185 }\r
84f9a9ec
LG
3186 \r
3187 //\r
3188 // The input string is ConfigAltResp format.\r
3189 //\r
3190 if ((*StringPtr != 0) && (StrnCmp (StringPtr, L"&GUID=", StrLen (L"&GUID=")) != 0)) {\r
93e3992d 3191 *Progress = StringPtr - 1;\r
3192 Status = EFI_INVALID_PARAMETER;\r
3193 goto Exit;\r
3194 }\r
3195\r
3196 *Progress = StringPtr;\r
3197 return EFI_SUCCESS;\r
3198\r
3199Exit:\r
3200\r
676df92c 3201 if (Value != NULL) {\r
3202 FreePool (Value);\r
3203 }\r
93e3992d 3204 return Status;\r
3205}\r
3206\r
3207\r
3208/**\r
3209 This helper function is to be called by drivers to extract portions of\r
3210 a larger configuration string.\r
3211\r
3212 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3213 instance.\r
3214 @param Configuration A null-terminated Unicode string in\r
84f9a9ec 3215 <MultiConfigAltResp> format. It is <ConfigAltResp> format.\r
93e3992d 3216 @param Guid A pointer to the GUID value to search for in the\r
3217 routing portion of the ConfigResp string when\r
3218 retrieving the requested data. If Guid is NULL,\r
3219 then all GUID values will be searched for.\r
3220 @param Name A pointer to the NAME value to search for in the\r
3221 routing portion of the ConfigResp string when\r
3222 retrieving the requested data. If Name is NULL,\r
3223 then all Name values will be searched for.\r
3224 @param DevicePath A pointer to the PATH value to search for in the\r
3225 routing portion of the ConfigResp string when\r
3226 retrieving the requested data. If DevicePath is\r
3227 NULL, then all DevicePath values will be searched\r
3228 for.\r
3229 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
3230 routing portion of the ConfigResp string when\r
3231 retrieving the requested data. If this parameter\r
3232 is NULL, then the current setting will be\r
3233 retrieved.\r
3234 @param AltCfgResp A pointer to a buffer which will be allocated by\r
3235 the function which contains the retrieved string\r
3236 as requested. This buffer is only allocated if\r
84f9a9ec 3237 the call was successful. It is <ConfigResp> format.\r
93e3992d 3238\r
3239 @retval EFI_SUCCESS The request succeeded. The requested data was\r
3240 extracted and placed in the newly allocated\r
3241 AltCfgResp buffer.\r
3242 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
3243 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
3244 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
3245 found.\r
3246\r
3247**/\r
3248EFI_STATUS\r
3249EFIAPI\r
3250HiiGetAltCfg (\r
3251 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3252 IN CONST EFI_STRING Configuration,\r
3253 IN CONST EFI_GUID *Guid,\r
3254 IN CONST EFI_STRING Name,\r
3255 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
3256 IN CONST UINT16 *AltCfgId,\r
3257 OUT EFI_STRING *AltCfgResp\r
3258 )\r
3259{\r
93e3992d 3260 EFI_STATUS Status;\r
3261 EFI_STRING StringPtr;\r
e90b081a 3262 EFI_STRING HdrStart;\r
3263 EFI_STRING HdrEnd;\r
93e3992d 3264 EFI_STRING TmpPtr;\r
3265 UINTN Length;\r
e90b081a 3266 EFI_STRING GuidStr;\r
3267 EFI_STRING NameStr;\r
3268 EFI_STRING PathStr;\r
3269 EFI_STRING AltIdStr;\r
3270 EFI_STRING Result;\r
3271 BOOLEAN GuidFlag;\r
3272 BOOLEAN NameFlag;\r
3273 BOOLEAN PathFlag;\r
3274\r
3275 HdrStart = NULL;\r
3276 HdrEnd = NULL;\r
3277 GuidStr = NULL;\r
3278 NameStr = NULL;\r
3279 PathStr = NULL;\r
3280 AltIdStr = NULL;\r
3281 Result = NULL;\r
3282 GuidFlag = FALSE;\r
3283 NameFlag = FALSE;\r
3284 PathFlag = FALSE;\r
93e3992d 3285\r
3286 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
3287 return EFI_INVALID_PARAMETER;\r
3288 }\r
3289\r
3290 StringPtr = Configuration;\r
3291 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3292 return EFI_INVALID_PARAMETER;\r
3293 }\r
3294\r
3295 //\r
3296 // Generate the sub string for later matching.\r
3297 //\r
813acf3a 3298 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 3299 GenerateSubStr (\r
3300 L"PATH=",\r
3301 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 3302 (VOID *) DevicePath,\r
3303 1,\r
93e3992d 3304 &PathStr\r
3305 );\r
3306 if (AltCfgId != NULL) {\r
813acf3a 3307 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 3308 }\r
3309 if (Name != NULL) {\r
813acf3a 3310 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 3311 } else {\r
813acf3a 3312 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 3313 }\r
3314\r
3315 while (*StringPtr != 0) {\r
3316 //\r
3317 // Try to match the GUID\r
3318 //\r
3319 if (!GuidFlag) {\r
3320 TmpPtr = StrStr (StringPtr, GuidStr);\r
3321 if (TmpPtr == NULL) {\r
3322 Status = EFI_NOT_FOUND;\r
3323 goto Exit;\r
3324 }\r
3325 HdrStart = TmpPtr;\r
3326\r
3327 //\r
3328 // Jump to <NameHdr>\r
3329 //\r
3330 if (Guid != NULL) {\r
3331 StringPtr = TmpPtr + StrLen (GuidStr);\r
3332 } else {\r
3333 StringPtr = StrStr (TmpPtr, L"NAME=");\r
3334 if (StringPtr == NULL) {\r
3335 Status = EFI_NOT_FOUND;\r
3336 goto Exit;\r
3337 }\r
3338 }\r
3339 GuidFlag = TRUE;\r
3340 }\r
3341\r
3342 //\r
3343 // Try to match the NAME\r
3344 //\r
3345 if (GuidFlag && !NameFlag) {\r
3346 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
3347 GuidFlag = FALSE;\r
3348 } else {\r
3349 //\r
3350 // Jump to <PathHdr>\r
3351 //\r
3352 if (Name != NULL) {\r
3353 StringPtr += StrLen (NameStr);\r
3354 } else {\r
3355 StringPtr = StrStr (StringPtr, L"PATH=");\r
3356 if (StringPtr == NULL) {\r
3357 Status = EFI_NOT_FOUND;\r
3358 goto Exit;\r
3359 }\r
3360 }\r
3361 NameFlag = TRUE;\r
3362 }\r
3363 }\r
3364\r
3365 //\r
3366 // Try to match the DevicePath\r
3367 //\r
3368 if (GuidFlag && NameFlag && !PathFlag) {\r
3369 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
3370 GuidFlag = FALSE;\r
3371 NameFlag = FALSE;\r
3372 } else {\r
3373 //\r
3374 // Jump to '&' before <DescHdr> or <ConfigBody>\r
3375 //\r
3376 if (DevicePath != NULL) {\r
3377 StringPtr += StrLen (PathStr);\r
3378 } else {\r
3379 StringPtr = StrStr (StringPtr, L"&");\r
3380 if (StringPtr == NULL) {\r
3381 Status = EFI_NOT_FOUND;\r
3382 goto Exit;\r
3383 }\r
84f9a9ec 3384 StringPtr ++;\r
93e3992d 3385 }\r
3386 PathFlag = TRUE;\r
84f9a9ec 3387 HdrEnd = StringPtr;\r
93e3992d 3388 }\r
3389 }\r
3390\r
3391 //\r
3392 // Try to match the AltCfgId\r
3393 //\r
3394 if (GuidFlag && NameFlag && PathFlag) {\r
3395 if (AltCfgId == NULL) {\r
3396 //\r
3397 // Return Current Setting when AltCfgId is NULL.\r
3398 //\r
3399 Status = OutputConfigBody (StringPtr, &Result);\r
3400 goto Exit;\r
3401 }\r
3402 //\r
3403 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
3404 //\r
3405 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
3406 GuidFlag = FALSE;\r
3407 NameFlag = FALSE;\r
3408 PathFlag = FALSE;\r
3409 } else {\r
84f9a9ec
LG
3410 //\r
3411 // Skip AltIdStr and &\r
3412 //\r
3413 StringPtr = StringPtr + StrLen (AltIdStr);\r
3414 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 3415 goto Exit;\r
3416 }\r
3417 }\r
3418 }\r
3419\r
3420 Status = EFI_NOT_FOUND;\r
3421\r
3422Exit:\r
76c24251 3423 *AltCfgResp = NULL;\r
bc166db3 3424 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 3425 //\r
3426 // Copy the <ConfigHdr> and <ConfigBody>\r
3427 //\r
84f9a9ec 3428 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 3429 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
3430 if (*AltCfgResp == NULL) {\r
3431 Status = EFI_OUT_OF_RESOURCES;\r
3432 } else {\r
3433 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
3434 StrCat (*AltCfgResp, Result);\r
3435 Status = EFI_SUCCESS;\r
3436 }\r
3437 }\r
3438\r
676df92c 3439 if (GuidStr != NULL) {\r
3440 FreePool (GuidStr);\r
3441 }\r
3442 if (NameStr != NULL) {\r
3443 FreePool (NameStr);\r
3444 }\r
3445 if (PathStr != NULL) {\r
3446 FreePool (PathStr);\r
3447 }\r
3448 if (AltIdStr != NULL) {\r
3449 FreePool (AltIdStr);\r
3450 }\r
3451 if (Result != NULL) {\r
3452 FreePool (Result);\r
3453 }\r
93e3992d 3454\r
3455 return Status;\r
3456\r
93e3992d 3457}\r
3458\r
36fe40c2 3459\r