]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
1. Clean up MdePkg internal header files
[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
1f1cb2f2 876 if (TempStr == NULL) {\r
04da0b4a
LG
877 FreePool (GuidStr);\r
878 FreePool (NameStr);\r
1f1cb2f2 879 FreePool (VarStoreName);\r
84f9a9ec
LG
880 Status = EFI_OUT_OF_RESOURCES;\r
881 goto Done;\r
882 }\r
883 StrCpy (TempStr, GuidStr);\r
884 StrCat (TempStr, NameStr);\r
885 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
886 //\r
887 // Find the matched VarStore\r
888 //\r
889 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
890 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
891 VarStorageData->Size = IfrVarStore->Size;\r
892 VarStorageData->Name = VarStoreName;\r
893 } else {\r
894 //\r
895 // No found, free the allocated memory \r
896 //\r
897 FreePool (VarStoreName);\r
898 }\r
899 //\r
900 // Free alllocated temp string.\r
901 //\r
04da0b4a
LG
902 FreePool (GuidStr);\r
903 FreePool (NameStr);\r
84f9a9ec 904 FreePool (TempStr);\r
84f9a9ec
LG
905 break;\r
906\r
907 case EFI_IFR_DEFAULTSTORE_OP:\r
908 //\r
909 // Add new the map between default id and default name.\r
910 //\r
911 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
912 if (DefaultData == NULL) {\r
913 Status = EFI_OUT_OF_RESOURCES;\r
914 goto Done;\r
915 }\r
916 DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
917 DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
918 InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry);\r
919 DefaultData = NULL;\r
920 break;\r
921\r
922 case EFI_IFR_FORM_OP:\r
923 //\r
924 // No matched varstore is found and directly return.\r
925 //\r
926 if (VarStorageData->Size == 0) {\r
927 Status = EFI_SUCCESS;\r
928 goto Done;\r
929 }\r
930 break;\r
931\r
932 case EFI_IFR_ONE_OF_OP:\r
933 case EFI_IFR_NUMERIC_OP:\r
934 //\r
935 // Numeric and OneOf has the same opcode structure.\r
936 //\r
937\r
938 //\r
939 // Check whether this question is for the requested varstore.\r
940 //\r
941 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
942 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {\r
943 break;\r
944 }\r
945 \r
946 //\r
947 // Get Offset/Width by Question header and OneOf Flags\r
948 //\r
949 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
950 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
951 //\r
952 // Check whether this question is in requested block array.\r
953 //\r
954 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
955 //\r
956 // This question is not in the requested string. Skip it.\r
957 //\r
958 break;\r
959 }\r
960\r
961 //\r
962 // Check this var question is in the var storage \r
963 //\r
964 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
965 Status = EFI_INVALID_PARAMETER;\r
966 goto Done;\r
967 }\r
968 \r
969 //\r
970 // Set Block Data\r
971 //\r
972 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
973 if (BlockData == NULL) {\r
974 Status = EFI_OUT_OF_RESOURCES;\r
975 goto Done;\r
976 }\r
977 BlockData->Offset = VarOffset;\r
978 BlockData->Width = VarWidth;\r
979 BlockData->QuestionId = IfrOneOf->Question.QuestionId;\r
980 BlockData->OpCode = IfrOpHdr->OpCode;\r
981 BlockData->Scope = IfrOpHdr->Scope;\r
982 InitializeListHead (&BlockData->DefaultValueEntry);\r
983 //\r
984 // Add Block Data into VarStorageData BlockEntry\r
985 //\r
986 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
987 break;\r
988\r
989 case EFI_IFR_ORDERED_LIST_OP:\r
990 //\r
991 // offset by question header\r
992 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
993 // no default value and default id, how to define its default value?\r
994 //\r
995 \r
996 //\r
997 // Check whether this question is for the requested varstore.\r
998 //\r
999 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
1000 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1001 break;\r
1002 }\r
1003 \r
1004 //\r
1005 // Get Offset/Width by Question header and OneOf Flags\r
1006 //\r
1007 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;\r
1008 VarWidth = IfrOrderedList->MaxContainers;\r
1009\r
1010 //\r
1011 // Check whether this question is in requested block array.\r
1012 //\r
1013 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1014 //\r
1015 // This question is not in the requested string. Skip it.\r
1016 //\r
1017 break;\r
1018 }\r
1019\r
1020 //\r
1021 // Check this var question is in the var storage \r
1022 //\r
1023 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1024 Status = EFI_INVALID_PARAMETER;\r
1025 goto Done;\r
1026 }\r
1027 \r
1028 //\r
1029 // Set Block Data\r
1030 //\r
1031 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1032 if (BlockData == NULL) {\r
1033 Status = EFI_OUT_OF_RESOURCES;\r
1034 goto Done;\r
1035 }\r
1036 BlockData->Offset = VarOffset;\r
1037 BlockData->Width = VarWidth;\r
1038 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;\r
1039 BlockData->OpCode = IfrOpHdr->OpCode;\r
1040 BlockData->Scope = IfrOpHdr->Scope;\r
1041 InitializeListHead (&BlockData->DefaultValueEntry);\r
1042 \r
1043 //\r
1044 // Add Block Data into VarStorageData BlockEntry\r
1045 //\r
1046 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1047 break;\r
1048\r
1049 case EFI_IFR_CHECKBOX_OP:\r
1050 //\r
1051 // EFI_IFR_DEFAULT_OP\r
1052 // offset by question header\r
1053 // width is 1 sizeof (BOOLEAN)\r
1054 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1055 // value by DefaultOption\r
1056 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1057 // \r
1058\r
1059 //\r
1060 // Check whether this question is for the requested varstore.\r
1061 //\r
1062 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1063 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1064 break;\r
1065 }\r
1066 \r
1067 //\r
1068 // Get Offset/Width by Question header and OneOf Flags\r
1069 //\r
1070 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
1071 VarWidth = sizeof (BOOLEAN);\r
1072\r
1073 //\r
1074 // Check whether this question is in requested block array.\r
1075 //\r
1076 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1077 //\r
1078 // This question is not in the requested string. Skip it.\r
1079 //\r
1080 break;\r
1081 }\r
1082\r
1083 //\r
1084 // Check this var question is in the var storage \r
1085 //\r
1086 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1087 Status = EFI_INVALID_PARAMETER;\r
1088 goto Done;\r
1089 }\r
1090 \r
1091 //\r
1092 // Set Block Data\r
1093 //\r
1094 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1095 if (BlockData == NULL) {\r
1096 Status = EFI_OUT_OF_RESOURCES;\r
1097 goto Done;\r
1098 }\r
1099 BlockData->Offset = VarOffset;\r
1100 BlockData->Width = VarWidth;\r
1101 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;\r
1102 BlockData->OpCode = IfrOpHdr->OpCode;\r
1103 BlockData->Scope = IfrOpHdr->Scope;\r
1104 InitializeListHead (&BlockData->DefaultValueEntry);\r
1105 //\r
1106 // Add Block Data into VarStorageData BlockEntry\r
1107 //\r
1108 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1109 \r
1110 //\r
1111 // Add default value by CheckBox Flags \r
1112 //\r
1113 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1114 //\r
1115 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1116 //\r
1117 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1118 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1119 if (EFI_ERROR (Status)) {\r
1120 goto Done;\r
1121 }\r
1122 //\r
1123 // Prepare new DefaultValue\r
1124 //\r
1125 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1126 if (DefaultData == NULL) {\r
1127 Status = EFI_OUT_OF_RESOURCES;\r
1128 goto Done;\r
1129 }\r
1130 DefaultData->DefaultId = VarDefaultId;\r
1131 DefaultData->DefaultName = VarDefaultName;\r
1132 DefaultData->Value = 1;\r
1133 //\r
1134 // Add DefaultValue into current BlockData\r
1135 //\r
1136 InsertDefaultValue (BlockData, DefaultData);\r
1137 }\r
1138\r
1139 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1140 //\r
1141 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1142 //\r
1143 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1144 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1145 if (EFI_ERROR (Status)) {\r
1146 goto Done;\r
1147 }\r
1148 //\r
1149 // Prepare new DefaultValue\r
1150 //\r
1151 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1152 if (DefaultData == NULL) {\r
1153 Status = EFI_OUT_OF_RESOURCES;\r
1154 goto Done;\r
1155 }\r
1156 DefaultData->DefaultId = VarDefaultId;\r
1157 DefaultData->DefaultName = VarDefaultName;\r
1158 DefaultData->Value = 1;\r
1159 //\r
1160 // Add DefaultValue into current BlockData\r
1161 //\r
1162 InsertDefaultValue (BlockData, DefaultData);\r
1163 }\r
1164 break;\r
1165\r
1166 case EFI_IFR_STRING_OP:\r
1167 //\r
1168 // offset by question header\r
1169 // width MaxSize * sizeof (CHAR16)\r
1170 // no default value, only block array\r
1171 //\r
1172\r
1173 //\r
1174 // Check whether this question is for the requested varstore.\r
1175 //\r
1176 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1177 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1178 break;\r
1179 }\r
1180 \r
1181 //\r
1182 // Get Offset/Width by Question header and OneOf Flags\r
1183 //\r
1184 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;\r
1185 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1186\r
1187 //\r
1188 // Check whether this question is in requested block array.\r
1189 //\r
1190 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1191 //\r
1192 // This question is not in the requested string. Skip it.\r
1193 //\r
1194 break;\r
1195 }\r
1196\r
1197 //\r
1198 // Check this var question is in the var storage \r
1199 //\r
1200 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1201 Status = EFI_INVALID_PARAMETER;\r
1202 goto Done;\r
1203 }\r
1204 \r
1205 //\r
1206 // Set Block Data\r
1207 //\r
1208 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1209 if (BlockData == NULL) {\r
1210 Status = EFI_OUT_OF_RESOURCES;\r
1211 goto Done;\r
1212 }\r
1213 BlockData->Offset = VarOffset;\r
1214 BlockData->Width = VarWidth;\r
1215 BlockData->QuestionId = IfrString->Question.QuestionId;\r
1216 BlockData->OpCode = IfrOpHdr->OpCode;\r
1217 InitializeListHead (&BlockData->DefaultValueEntry);\r
1218 \r
1219 //\r
1220 // Add Block Data into VarStorageData BlockEntry\r
1221 //\r
1222 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1223 \r
1224 //\r
1225 // No default value for string.\r
1226 //\r
1227 BlockData = NULL;\r
1228 break;\r
1229\r
1230 case EFI_IFR_PASSWORD_OP:\r
1231 //\r
1232 // offset by question header\r
1233 // width MaxSize * sizeof (CHAR16)\r
1234 // no default value, only block array\r
1235 //\r
1236\r
1237 //\r
1238 // Check whether this question is for the requested varstore.\r
1239 //\r
1240 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
1241 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1242 break;\r
1243 }\r
1244 \r
1245 //\r
1246 // Get Offset/Width by Question header and OneOf Flags\r
1247 //\r
1248 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;\r
1249 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
1250\r
1251 //\r
1252 // Check whether this question is in requested block array.\r
1253 //\r
1254 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1255 //\r
1256 // This question is not in the requested string. Skip it.\r
1257 //\r
1258 break;\r
1259 }\r
1260\r
1261 //\r
1262 // Check this var question is in the var storage \r
1263 //\r
1264 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1265 Status = EFI_INVALID_PARAMETER;\r
1266 goto Done;\r
1267 }\r
1268 \r
1269 //\r
1270 // Set Block Data\r
1271 //\r
1272 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1273 if (BlockData == NULL) {\r
1274 Status = EFI_OUT_OF_RESOURCES;\r
1275 goto Done;\r
1276 }\r
1277 BlockData->Offset = VarOffset;\r
1278 BlockData->Width = VarWidth;\r
1279 BlockData->QuestionId = IfrPassword->Question.QuestionId;\r
1280 BlockData->OpCode = IfrOpHdr->OpCode;\r
1281 InitializeListHead (&BlockData->DefaultValueEntry);\r
1282 \r
1283 //\r
1284 // Add Block Data into VarStorageData BlockEntry\r
1285 //\r
1286 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1287 \r
1288 //\r
1289 // No default value for string.\r
1290 //\r
1291 BlockData = NULL;\r
1292 break;\r
1293\r
1294 case EFI_IFR_ONE_OF_OPTION_OP:\r
1295 //\r
1296 // No matched block data is ignored.\r
1297 //\r
1298 if (BlockData == NULL || BlockData->Scope == 0) {\r
1299 break;\r
1300 }\r
1301 \r
1302 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1303 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1304 //\r
1305 // Get ordered list option data type.\r
1306 //\r
1307 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
1308 VarWidth = 1;\r
1309 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1310 VarWidth = 2;\r
1311 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1312 VarWidth = 4;\r
1313 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1314 VarWidth = 8;\r
1315 } else {\r
1316 //\r
1317 // Invalid ordered list option data type.\r
1318 //\r
1319 Status = EFI_INVALID_PARAMETER;\r
1320 goto Done;\r
1321 }\r
1322 //\r
1323 // Calculate Ordered list QuestionId width.\r
1324 //\r
1325 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
1326 BlockData = NULL;\r
1327 break;\r
1328 }\r
1329\r
1330 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
1331 //\r
1332 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1333 //\r
1334 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1335 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1336 if (EFI_ERROR (Status)) {\r
1337 goto Done;\r
1338 }\r
1339 //\r
1340 // Prepare new DefaultValue\r
1341 //\r
1342 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1343 if (DefaultData == NULL) {\r
1344 Status = EFI_OUT_OF_RESOURCES;\r
1345 goto Done;\r
1346 }\r
1347 DefaultData->DefaultId = VarDefaultId;\r
1348 DefaultData->DefaultName = VarDefaultName;\r
1349 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1350 //\r
1351 // Add DefaultValue into current BlockData\r
1352 //\r
1353 InsertDefaultValue (BlockData, DefaultData);\r
1354 }\r
1355\r
1356 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
1357 //\r
1358 // Set default ID to Manufacture ID and Get DefaultName String ID\r
1359 //\r
1360 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1361 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1362 if (EFI_ERROR (Status)) {\r
1363 goto Done;\r
1364 }\r
1365 //\r
1366 // Prepare new DefaultValue\r
1367 //\r
1368 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1369 if (DefaultData == NULL) {\r
1370 Status = EFI_OUT_OF_RESOURCES;\r
1371 goto Done;\r
1372 }\r
1373 DefaultData->DefaultId = VarDefaultId;\r
1374 DefaultData->DefaultName = VarDefaultName;\r
1375 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1376 //\r
1377 // Add DefaultValue into current BlockData\r
1378 //\r
1379 InsertDefaultValue (BlockData, DefaultData);\r
1380 }\r
1381 break;\r
1382\r
1383 case EFI_IFR_DEFAULT_OP:\r
1384 //\r
1385 // Update Current BlockData to the default value.\r
1386 //\r
1387 if (BlockData == NULL || BlockData->Scope == 0) {\r
1388 //\r
1389 // No matched block data is ignored. \r
1390 //\r
1391 break;\r
1392 }\r
1393\r
1394 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1395 //\r
1396 // OrderedList Opcode is no default value.\r
1397 //\r
1398 break;\r
1399 }\r
1400 //\r
1401 // Get the DefaultId and DefaultName String ID\r
1402 //\r
1403 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
1404 VarDefaultId = IfrDefault->DefaultId;\r
1405 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1406 if (EFI_ERROR (Status)) {\r
1407 goto Done;\r
1408 }\r
1409 //\r
1410 // Prepare new DefaultValue\r
1411 //\r
1412 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1413 if (DefaultData == NULL) {\r
1414 Status = EFI_OUT_OF_RESOURCES;\r
1415 goto Done;\r
1416 }\r
1417 DefaultData->DefaultId = VarDefaultId;\r
1418 DefaultData->DefaultName = VarDefaultName;\r
1419 DefaultData->Value = IfrDefault->Value.u64;\r
1420 //\r
1421 // Add DefaultValue into current BlockData\r
1422 //\r
1423 InsertDefaultValue (BlockData, DefaultData);\r
1424 break;\r
1425 case EFI_IFR_END_OP:\r
1426 //\r
1427 // End Opcode is for Var.\r
1428 //\r
1429 if (BlockData != NULL && BlockData->Scope > 0) {\r
1430 BlockData->Scope--;\r
1431 }\r
1432 break;\r
1433 default:\r
1434 if (BlockData != NULL && BlockData->Scope > 0) {\r
1435 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
1436 }\r
1437 break;\r
1438 }\r
1439\r
1440 IfrOffset += IfrOpHdr->Length;\r
1441 }\r
1442\r
1443Done:\r
1444 //\r
1445 // Set the defualt ID array.\r
1446 //\r
1447 *PIfrDefaultIdArray = DefaultIdArray;\r
1448\r
1449 return Status; \r
1450}\r
1451\r
1452/**\r
1453 This function gets the full request string and full default value string by \r
1454 parsing IFR data in HII form packages. \r
1455 \r
1456 When Request points to NULL string, the request string and default value string \r
1457 for each varstore in form package will return. \r
1458\r
1459 @param HiiHandle Hii Handle which Hii Packages are registered.\r
1460 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
1461 @param Request Pointer to a null-terminated Unicode string in\r
1462 <ConfigRequest> format. When it doesn't contain\r
1463 any RequestElement, it will be updated to return \r
1464 the full RequestElement retrieved from IFR data.\r
1465 If it points to NULL, the request string for the first\r
1466 varstore in form package will be merged into a\r
1467 <MultiConfigRequest> format string and return. \r
1468 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
1469 <ConfigAltResp> format. When the pointer is to NULL,\r
1470 the full default value string retrieved from IFR data\r
1471 will return. When the pinter is to a string, the\r
1472 full default value string retrieved from IFR data\r
1473 will be merged into the input string and return.\r
1474 When Request points to NULL, the default value string \r
1475 for each varstore in form package will be merged into \r
1476 a <MultiConfigAltResp> format string and return.\r
1477 @retval EFI_SUCCESS The Results string is set to the full request string.\r
1478 And AltCfgResp contains all default value string.\r
1479 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
1480 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
1481 can't be found in Form package.\r
1482 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
1483 @retval EFI_INVALID_PARAMETER *Request points to NULL.\r
1484\r
1485**/\r
1486EFI_STATUS\r
1487EFIAPI\r
1488GetFullStringFromHiiFormPackages (\r
1489 IN EFI_HII_HANDLE HiiHandle,\r
1490 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1491 IN OUT EFI_STRING *Request,\r
1492 IN OUT EFI_STRING *AltCfgResp\r
1493 )\r
1494{\r
1495 EFI_STATUS Status;\r
1496 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
1497 UINT32 PackageListLength; \r
1498 UINTN BufferSize;\r
1499 IFR_BLOCK_DATA *RequestBlockArray;\r
1500 IFR_BLOCK_DATA *BlockData;\r
1501 IFR_BLOCK_DATA *NextBlockData;\r
1502 IFR_DEFAULT_DATA *DefaultValueData;\r
1503 IFR_DEFAULT_DATA *DefaultId;\r
1504 IFR_DEFAULT_DATA *DefaultIdArray;\r
1505 EFI_HII_PACKAGE_HEADER PacakgeHeader;\r
1506 UINT32 PackageOffset;\r
1507 IFR_VARSTORAGE_DATA *VarStorageData;\r
1508 EFI_STRING DefaultAltCfgResp;\r
1509 EFI_STRING FullConfigRequest;\r
1510 EFI_STRING ConfigHdr;\r
1511 EFI_STRING GuidStr;\r
1512 EFI_STRING NameStr;\r
1513 EFI_STRING PathStr;\r
1514 EFI_STRING StringPtr;\r
1515 UINTN Length;\r
1516 UINT8 *TmpBuffer;\r
1517 UINT16 Offset;\r
1518 UINT16 Width;\r
1519 LIST_ENTRY *Link;\r
1520 LIST_ENTRY *LinkData;\r
1521 LIST_ENTRY *LinkDefault;\r
1522\r
1523 //\r
1524 // Initialize the local variables.\r
1525 //\r
1526 RequestBlockArray = NULL;\r
1527 VarStorageData = NULL;\r
1528 DefaultAltCfgResp = NULL;\r
1529 FullConfigRequest = NULL;\r
1530 ConfigHdr = NULL;\r
1531 DefaultIdArray = NULL;\r
1532 GuidStr = NULL;\r
1533 NameStr = NULL;\r
1534 PathStr = NULL;\r
1535\r
1536 //\r
1537 // 1. Get HiiPackage by HiiHandle\r
1538 //\r
1539 BufferSize = 0;\r
1540 HiiPackageList = NULL;\r
1541 Status = HiiExportPackageLists (&mPrivate.HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1542\r
1543 //\r
1544 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
1545 //\r
1546 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1547 return Status;\r
1548 }\r
1549\r
1550 HiiPackageList = AllocatePool (BufferSize);\r
1551 if (HiiPackageList == NULL) {\r
1552 return EFI_OUT_OF_RESOURCES;\r
1553 }\r
1554\r
1555 //\r
1556 // Get PackageList on HiiHandle\r
1557 //\r
1558 Status = HiiExportPackageLists (&mPrivate.HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1559 if (EFI_ERROR (Status)) {\r
1560 goto Done;\r
1561 }\r
1562\r
1563 //\r
1564 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
1565 // 1) Request is NULL.\r
1566 // 2) Request is not NULL. And it doesn't contain any BlockArray.\r
1567 // 3) Request is not NULL. And it containts BlockArray.\r
1568 //\r
1569\r
1570 //\r
1571 // Initialize VarStorageData to store the var store Block and Default value information.\r
1572 //\r
1573 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
1574 if (VarStorageData == NULL) {\r
1575 Status = EFI_OUT_OF_RESOURCES;\r
1576 goto Done;\r
1577 }\r
1578\r
1579 InitializeListHead (&VarStorageData->Entry);\r
1580 InitializeListHead (&VarStorageData->BlockEntry);\r
1581\r
1582 //\r
1583 // Gte the request block array by Request String \r
1584 //\r
1585 StringPtr = NULL;\r
1586 if (*Request != NULL) {\r
1587 StringPtr = StrStr (*Request, L"&OFFSET=");\r
1588 }\r
1589 if (StringPtr != NULL) {\r
1590 //\r
1591 // Init RequestBlockArray\r
1592 //\r
1593 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1594 if (RequestBlockArray == NULL) {\r
1595 Status = EFI_OUT_OF_RESOURCES;\r
1596 goto Done;\r
1597 }\r
1598 InitializeListHead (&RequestBlockArray->Entry);\r
1599\r
1600 //\r
1601 // Get the request Block array from the request string\r
1602 // Offset and Width\r
1603 //\r
1604\r
1605 //\r
1606 // Parse each <RequestElement> if exists\r
1607 // Only <BlockName> format is supported by this help function.\r
1608 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
1609 //\r
1610 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
1611 //\r
1612 // Skip the OFFSET string\r
1613 // \r
1614 StringPtr += StrLen (L"&OFFSET=");\r
1615 //\r
1616 // Get Offset\r
1617 //\r
1618 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1619 if (EFI_ERROR (Status)) {\r
1620 goto Done;\r
1621 }\r
1622 Offset = 0;\r
1623 CopyMem (\r
1624 &Offset,\r
1625 TmpBuffer,\r
1626 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1627 );\r
1628 FreePool (TmpBuffer);\r
1629 \r
1630 StringPtr += Length;\r
1631 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1632 Status = EFI_INVALID_PARAMETER;\r
1633 goto Done;\r
1634 }\r
1635 StringPtr += StrLen (L"&WIDTH=");\r
1636 \r
1637 //\r
1638 // Get Width\r
1639 //\r
1640 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1641 if (EFI_ERROR (Status)) {\r
1642 goto Done;\r
1643 }\r
1644 Width = 0;\r
1645 CopyMem (\r
1646 &Width,\r
1647 TmpBuffer,\r
1648 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1649 );\r
1650 FreePool (TmpBuffer);\r
1651\r
1652 StringPtr += Length;\r
1653 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1654 Status = EFI_INVALID_PARAMETER;\r
1655 goto Done;\r
1656 }\r
1657 \r
1658 //\r
1659 // Set Block Data\r
1660 //\r
1661 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1662 if (BlockData == NULL) {\r
1663 Status = EFI_OUT_OF_RESOURCES;\r
1664 goto Done;\r
1665 }\r
1666 BlockData->Offset = Offset;\r
1667 BlockData->Width = Width;\r
1668 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
1669\r
1670 //\r
1671 // If '\0', parsing is finished. \r
1672 //\r
1673 if (*StringPtr == 0) {\r
1674 break;\r
1675 }\r
1676 }\r
1677 \r
1678 //\r
1679 // Merge the requested block data.\r
1680 //\r
1681 Link = RequestBlockArray->Entry.ForwardLink;\r
1682 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
1683 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1684 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
1685 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
1686 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
1687 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
1688 }\r
1689 RemoveEntryList (Link->ForwardLink);\r
1690 FreePool (NextBlockData);\r
1691 continue;\r
1692 }\r
1693 Link = Link->ForwardLink; \r
1694 }\r
1695 }\r
1696 \r
1697 //\r
1698 // Get the form package\r
1699 //\r
1700 PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1701 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
1702 while (PackageOffset < PackageListLength) {\r
1703 CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
1704\r
1705 if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1706 //\r
1707 // Reset VarStorageData\r
1708 //\r
1709 VarStorageData->Size = 0;\r
1710 VarStorageData->VarStoreId = 0;\r
1711 if (VarStorageData->Name != NULL) {\r
1712 FreePool (VarStorageData->Name);\r
1713 VarStorageData->Name = NULL;\r
1714 }\r
1715\r
1716 //\r
1717 // Parse the opcode in form package \r
1718 //\r
1719 Status = ParseIfrData ((UINT8 *) HiiPackageList + PackageOffset, PacakgeHeader.Length, *Request, RequestBlockArray, VarStorageData, &DefaultIdArray);\r
1720 if (EFI_ERROR (Status)) {\r
1721 goto Done;\r
1722 }\r
1723\r
1724 //\r
1725 // Only one form is in a pacakge list.\r
1726 //\r
1727 break;\r
1728 }\r
1729\r
1730 PackageOffset += PacakgeHeader.Length;\r
1731 }\r
76c24251
LG
1732 \r
1733 //\r
1734 // No requested varstore in IFR data and directly return\r
1735 //\r
1736 if (VarStorageData->Size == 0) {\r
1737 goto Done;\r
1738 }\r
84f9a9ec
LG
1739\r
1740 //\r
1741 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
1742 //\r
1743\r
1744 //\r
1745 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
1746 //\r
1747 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
1748 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
1749 GenerateSubStr (\r
1750 L"PATH=",\r
1751 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
1752 (VOID *) DevicePath,\r
1753 1,\r
1754 &PathStr\r
1755 );\r
1756 Length = StrLen (GuidStr);\r
1757 Length = Length + StrLen (NameStr);\r
1758 Length = Length + StrLen (PathStr) + 1;\r
1759 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
1760 if (ConfigHdr == NULL) {\r
1761 Status = EFI_OUT_OF_RESOURCES;\r
1762 goto Done; \r
1763 }\r
1764 StrCpy (ConfigHdr, GuidStr);\r
1765 StrCat (ConfigHdr, NameStr);\r
1766 StrCat (ConfigHdr, PathStr);\r
1767\r
1768 //\r
1769 // Remove the last character L'&'\r
1770 //\r
1771 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';\r
1772\r
1773 if (RequestBlockArray == NULL) {\r
1774 //\r
1775 // Append VarStorageData BlockEntry into *Request string\r
1776 // Now support only one varstore in a form package.\r
1777 //\r
1778\r
1779 //\r
1780 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
1781 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
1782 //\r
1783\r
1784 //\r
1785 // Compute the length of the entire request starting with <ConfigHdr> and a \r
1786 // Null-terminator\r
1787 //\r
1788 Length = StrLen (ConfigHdr) + 1;\r
1789\r
1790 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1791 //\r
1792 // Add <BlockName> length for each Offset/Width pair\r
1793 //\r
1794 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
1795 // | 8 | 4 | 7 | 4 |\r
1796 //\r
1797 Length = Length + (8 + 4 + 7 + 4);\r
1798 }\r
1799 \r
1800 //\r
1801 // Allocate buffer for the entire <ConfigRequest>\r
1802 //\r
1803 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
1804 if (FullConfigRequest == NULL) {\r
1805 goto Done;\r
1806 }\r
1807 StringPtr = FullConfigRequest;\r
1808 \r
1809 //\r
1810 // Start with <ConfigHdr>\r
1811 //\r
1812 StrCpy (StringPtr, ConfigHdr);\r
1813 StringPtr += StrLen (StringPtr);\r
1814\r
1815 //\r
1816 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
1817 //\r
1818 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1819 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1820 //\r
1821 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
1822 //\r
1823 UnicodeSPrint (\r
1824 StringPtr, \r
1825 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
1826 L"&OFFSET=%04X&WIDTH=%04X", \r
1827 BlockData->Offset, \r
1828 BlockData->Width\r
1829 );\r
1830 StringPtr += StrLen (StringPtr);\r
1831 }\r
1832 //\r
1833 // Set to the got full request string.\r
1834 //\r
1835 HiiToLower (FullConfigRequest);\r
1836 if (*Request != NULL) {\r
1837 FreePool (*Request);\r
1838 }\r
1839 *Request = FullConfigRequest;\r
1840 }\r
1841 \r
1842 //\r
1843 // 4. Construct Default Value string in AltResp according to request element.\r
1844 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
1845 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
1846 //\r
93e3992d 1847\r
1848 //\r
84f9a9ec 1849 // Add length for <ConfigHdr> + '\0'\r
93e3992d 1850 //\r
84f9a9ec
LG
1851 Length = StrLen (ConfigHdr) + 1;\r
1852 \r
1853 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
1854 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
1855 //\r
1856 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
1857 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
1858 //\r
1859 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
1860 \r
1861 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
1862 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
1863 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
1864 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
1865 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
1866 //\r
1867 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
1868 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
1869 //\r
1870 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2); \r
1871 }\r
1872 }\r
1873 }\r
93e3992d 1874 }\r
84f9a9ec 1875\r
93e3992d 1876 //\r
84f9a9ec 1877 // Allocate buffer for the entire <DefaultAltCfgResp>\r
93e3992d 1878 //\r
84f9a9ec
LG
1879 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
1880 if (DefaultAltCfgResp == NULL) {\r
1881 goto Done;\r
1882 }\r
1883 StringPtr = DefaultAltCfgResp;\r
93e3992d 1884\r
84f9a9ec
LG
1885 //\r
1886 // Start with <ConfigHdr>\r
1887 //\r
1888 StrCpy (StringPtr, ConfigHdr);\r
1889 StringPtr += StrLen (StringPtr);\r
93e3992d 1890\r
84f9a9ec
LG
1891 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
1892 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
1893 //\r
1894 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
1895 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
1896 //\r
1897 UnicodeSPrint (\r
1898 StringPtr, \r
1899 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
1900 L"&%s&ALTCFG=%04X", \r
1901 ConfigHdr, \r
1902 DefaultId->DefaultName\r
1903 );\r
1904 StringPtr += StrLen (StringPtr);\r
1905 \r
1906 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
1907 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
1908 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
1909 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
1910 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
1911 //\r
1912 // Add <BlockConfig>\r
1913 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
1914 //\r
1915 UnicodeSPrint (\r
1916 StringPtr, \r
1917 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
1918 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
1919 BlockData->Offset, \r
1920 BlockData->Width\r
1921 );\r
1922 StringPtr += StrLen (StringPtr);\r
1923\r
1924 //\r
1925 // Convert Value to a hex string in "%x" format\r
1926 // NOTE: This is in the opposite byte that GUID and PATH use\r
1927 //\r
1928 Width = BlockData->Width;\r
1929 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
1930 for (; Width > 0; Width--) {\r
1931 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
1932 }\r
1933 }\r
1934 }\r
1935 }\r
93e3992d 1936 }\r
84f9a9ec 1937 HiiToLower (DefaultAltCfgResp);\r
93e3992d 1938\r
84f9a9ec
LG
1939 //\r
1940 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
1941 //\r
1942 if (*AltCfgResp != NULL) {\r
1943 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
1944 FreePool (DefaultAltCfgResp);\r
1945 } else {\r
1946 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 1947 }\r
93e3992d 1948\r
84f9a9ec
LG
1949Done:\r
1950 if (RequestBlockArray != NULL) {\r
1951 //\r
1952 // Free Link Array RequestBlockArray\r
1953 //\r
1954 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
1955 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
1956 RemoveEntryList (&BlockData->Entry);\r
1957 FreePool (BlockData);\r
1958 }\r
1959\r
1960 FreePool (RequestBlockArray);\r
93e3992d 1961 }\r
63d55bb9 1962 \r
84f9a9ec
LG
1963 if (VarStorageData != NULL) {\r
1964 //\r
1965 // Free link array VarStorageData\r
1966 //\r
1967 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
1968 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
1969 RemoveEntryList (&BlockData->Entry);\r
1970 //\r
1971 // Free default value link array\r
1972 //\r
1973 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
1974 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
1975 RemoveEntryList (&DefaultValueData->Entry);\r
1976 FreePool (DefaultValueData);\r
1977 }\r
1978 FreePool (BlockData);\r
63d55bb9 1979 }\r
84f9a9ec 1980 FreePool (VarStorageData);\r
93e3992d 1981 }\r
1982\r
84f9a9ec
LG
1983 if (DefaultIdArray != NULL) {\r
1984 //\r
1985 // Free DefaultId Array\r
1986 //\r
1987 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
1988 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
1989 RemoveEntryList (&DefaultId->Entry);\r
1990 FreePool (DefaultId);\r
1991 }\r
1992 FreePool (DefaultIdArray);\r
1993 }\r
1994 \r
1995 //\r
1996 // Free the allocated string \r
1997 //\r
1998 if (GuidStr != NULL) {\r
1999 FreePool (GuidStr);\r
2000 }\r
2001 if (NameStr != NULL) {\r
2002 FreePool (NameStr);\r
2003 }\r
2004 if (PathStr != NULL) {\r
2005 FreePool (PathStr);\r
2006 }\r
2007 if (ConfigHdr != NULL) {\r
2008 FreePool (ConfigHdr);\r
2009 }\r
93e3992d 2010\r
84f9a9ec
LG
2011 //\r
2012 // Free Pacakge data\r
2013 //\r
2014 if (HiiPackageList != NULL) {\r
2015 FreePool (HiiPackageList);\r
676df92c 2016 }\r
63d55bb9 2017\r
93e3992d 2018 return Status;\r
2019}\r
2020\r
93e3992d 2021/**\r
2022 This function allows a caller to extract the current configuration\r
2023 for one or more named elements from one or more drivers.\r
2024\r
2025 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2026 instance.\r
2027 @param Request A null-terminated Unicode string in\r
2028 <MultiConfigRequest> format.\r
2029 @param Progress On return, points to a character in the Request\r
2030 string. Points to the string's null terminator if\r
2031 request was successful. Points to the most recent\r
2032 & before the first failing name / value pair (or\r
2033 the beginning of the string if the failure is in\r
2034 the first name / value pair) if the request was\r
2035 not successful.\r
2036 @param Results Null-terminated Unicode string in\r
2037 <MultiConfigAltResp> format which has all values\r
2038 filled in for the names in the Request string.\r
2039 String to be allocated by the called function.\r
2040\r
2041 @retval EFI_SUCCESS The Results string is filled with the values\r
2042 corresponding to all requested names.\r
2043 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2044 results that must be stored awaiting possible\r
2045 future protocols.\r
2046 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
2047 Progress set to the "G" in "GUID" of the routing\r
2048 header that doesn't match. Note: There is no\r
2049 requirement that all routing data be validated\r
2050 before any configuration extraction.\r
2051 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
2052 parameter would result in this type of error. The\r
2053 Progress parameter is set to NULL.\r
2054 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
2055 before the error or the beginning of the string.\r
2056 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
2057 name in question.\r
2058\r
2059**/\r
2060EFI_STATUS\r
2061EFIAPI\r
2062HiiConfigRoutingExtractConfig (\r
2063 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2064 IN CONST EFI_STRING Request,\r
2065 OUT EFI_STRING *Progress,\r
2066 OUT EFI_STRING *Results\r
2067 )\r
2068{\r
84f9a9ec 2069 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2070 EFI_STRING StringPtr;\r
2071 EFI_STRING ConfigRequest;\r
2072 UINTN Length;\r
2073 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2074 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 2075 EFI_STATUS Status;\r
84f9a9ec
LG
2076 LIST_ENTRY *Link;\r
2077 HII_DATABASE_RECORD *Database;\r
2078 UINT8 *DevicePathPkg;\r
2079 UINT8 *CurrentDevicePath;\r
93e3992d 2080 EFI_HANDLE DriverHandle;\r
84f9a9ec 2081 EFI_HII_HANDLE HiiHandle;\r
93e3992d 2082 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2083 EFI_STRING AccessProgress;\r
2084 EFI_STRING AccessResults;\r
84f9a9ec 2085 EFI_STRING DefaultResults;\r
8d00a0f1 2086 BOOLEAN FirstElement;\r
84f9a9ec 2087 UINTN DevicePathLength;\r
93e3992d 2088\r
2089 if (This == NULL || Progress == NULL || Results == NULL) {\r
2090 return EFI_INVALID_PARAMETER;\r
2091 }\r
2092\r
2093 if (Request == NULL) {\r
2094 *Progress = NULL;\r
2095 return EFI_INVALID_PARAMETER;\r
2096 }\r
2097\r
84f9a9ec 2098 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2099 StringPtr = Request;\r
2100 *Progress = StringPtr;\r
84f9a9ec
LG
2101 DefaultResults = NULL;\r
2102 ConfigRequest = NULL;\r
2103 Status = EFI_SUCCESS;\r
2104 AccessResults = NULL;\r
2105 DevicePath = NULL;\r
93e3992d 2106\r
2107 //\r
2108 // The first element of <MultiConfigRequest> should be\r
2109 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2110 //\r
2111 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2112 return EFI_INVALID_PARAMETER;\r
2113 }\r
2114\r
8d00a0f1 2115 FirstElement = TRUE;\r
2116\r
93e3992d 2117 //\r
2118 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2119 // Results if this fix length is insufficient.\r
2120 //\r
2121 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2122 if (*Results == NULL) {\r
2123 return EFI_OUT_OF_RESOURCES;\r
2124 }\r
2125\r
2126 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2127 //\r
2128 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
2129 // or most recent & before the error.\r
2130 //\r
2131 if (StringPtr == Request) {\r
2132 *Progress = StringPtr;\r
2133 } else {\r
2134 *Progress = StringPtr - 1;\r
2135 }\r
2136\r
2137 //\r
2138 // Process each <ConfigRequest> of <MultiConfigRequest>\r
2139 //\r
2140 Length = CalculateConfigStringLen (StringPtr);\r
2141 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2142 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
2143 Status = EFI_OUT_OF_RESOURCES;\r
2144 goto Done;\r
93e3992d 2145 }\r
2146 *(ConfigRequest + Length) = 0;\r
2147\r
2148 //\r
2149 // Get the UEFI device path\r
2150 //\r
2151 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
2152 if (EFI_ERROR (Status)) {\r
84f9a9ec 2153 goto Done;\r
93e3992d 2154 }\r
2155\r
2156 //\r
84f9a9ec
LG
2157 // Find driver which matches the routing data.\r
2158 //\r
2159 DriverHandle = NULL;\r
2160 HiiHandle = NULL;\r
2161 DevicePathLength = GetDevicePathSize (DevicePath);\r
2162 for (Link = Private->DatabaseList.ForwardLink;\r
2163 Link != &Private->DatabaseList;\r
2164 Link = Link->ForwardLink\r
2165 ) {\r
2166 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2167 \r
2168 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2169 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
2170 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) && \r
2171 (CompareMem (\r
2172 DevicePath,\r
2173 CurrentDevicePath,\r
2174 DevicePathLength\r
2175 ) == 0)) {\r
2176 DriverHandle = Database->DriverHandle;\r
2177 HiiHandle = Database->Handle;\r
2178 break;\r
2179 }\r
2180 }\r
2181 }\r
2182 \r
2183 //\r
2184 // Try to find driver handle by device path.\r
93e3992d 2185 //\r
84f9a9ec
LG
2186 if (DriverHandle == NULL) {\r
2187 TempDevicePath = DevicePath;\r
2188 Status = gBS->LocateDevicePath (\r
2189 &gEfiDevicePathProtocolGuid,\r
2190 &TempDevicePath,\r
2191 &DriverHandle\r
2192 );\r
2193 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2194 //\r
2195 // Routing data does not match any known driver.\r
2196 // Set Progress to the 'G' in "GUID" of the routing header.\r
2197 //\r
2198 *Progress = StringPtr;\r
2199 Status = EFI_NOT_FOUND;\r
2200 goto Done;\r
2201 }\r
2202 }\r
2203 \r
2204 //\r
2205 // Check whether ConfigRequest contains request string OFFSET/WIDTH\r
2206 //\r
2207 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {\r
93e3992d 2208 //\r
84f9a9ec 2209 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 2210 //\r
84f9a9ec
LG
2211 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &DefaultResults);\r
2212 if (EFI_ERROR (Status)) {\r
2213 goto Done;\r
2214 }\r
1f1cb2f2
LG
2215 //\r
2216 // Not any request block is found.\r
2217 //\r
2218 if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {\r
76c24251 2219 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
2220 goto NextConfigString;\r
2221 }\r
93e3992d 2222 }\r
2223\r
2224 //\r
2225 // Call corresponding ConfigAccess protocol to extract settings\r
2226 //\r
2227 Status = gBS->HandleProtocol (\r
2228 DriverHandle,\r
2229 &gEfiHiiConfigAccessProtocolGuid,\r
2230 (VOID **) &ConfigAccess\r
2231 );\r
2232 ASSERT_EFI_ERROR (Status);\r
2233\r
2234 Status = ConfigAccess->ExtractConfig (\r
2235 ConfigAccess,\r
2236 ConfigRequest,\r
2237 &AccessProgress,\r
2238 &AccessResults\r
2239 );\r
2240 if (EFI_ERROR (Status)) {\r
2241 //\r
2242 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
2243 // Map it to the progress on <MultiConfigRequest> then return it.\r
2244 //\r
8d00a0f1 2245 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 2246 goto Done;\r
93e3992d 2247 }\r
2248\r
2249 //\r
8d00a0f1 2250 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2251 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 2252 //\r
2253 ASSERT (*AccessProgress == 0);\r
8d00a0f1 2254\r
84f9a9ec
LG
2255 //\r
2256 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2257 //\r
2258 if (HiiHandle != NULL) {\r
2259 if (DefaultResults == NULL) {\r
2260 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &AccessResults);\r
2261 } else {\r
2262 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
2263 }\r
2264 }\r
2265 FreePool (DevicePath);\r
2266 DevicePath = NULL;\r
2267 \r
2268 if (EFI_ERROR (Status)) {\r
2269 goto Done;\r
2270 }\r
2271\r
2272 //\r
2273 // Free the allocated memory.\r
2274 //\r
2275 if (DefaultResults != NULL) {\r
2276 FreePool (DefaultResults);\r
2277 DefaultResults = NULL;\r
2278 }\r
76c24251
LG
2279\r
2280NextConfigString: \r
8d00a0f1 2281 if (!FirstElement) {\r
2282 Status = AppendToMultiString (Results, L"&");\r
2283 ASSERT_EFI_ERROR (Status);\r
2284 }\r
2285 \r
93e3992d 2286 Status = AppendToMultiString (Results, AccessResults);\r
2287 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 2288\r
2289 FirstElement = FALSE;\r
84f9a9ec 2290\r
676df92c 2291 FreePool (AccessResults);\r
93e3992d 2292 AccessResults = NULL;\r
676df92c 2293 FreePool (ConfigRequest);\r
93e3992d 2294 ConfigRequest = NULL;\r
2295\r
2296 //\r
2297 // Go to next <ConfigRequest> (skip '&').\r
2298 //\r
2299 StringPtr += Length;\r
2300 if (*StringPtr == 0) {\r
2301 *Progress = StringPtr;\r
2302 break;\r
2303 }\r
2304\r
2305 StringPtr++;\r
93e3992d 2306 }\r
2307\r
84f9a9ec
LG
2308Done:\r
2309 if (EFI_ERROR (Status)) {\r
2310 FreePool (*Results);\r
1f1cb2f2 2311 *Results = NULL;\r
84f9a9ec
LG
2312 }\r
2313 \r
2314 if (ConfigRequest != NULL) {\r
2315 FreePool (ConfigRequest);\r
2316 }\r
2317 \r
2318 if (AccessResults != NULL) {\r
2319 FreePool (AccessResults);\r
2320 }\r
2321 \r
2322 if (DefaultResults != NULL) {\r
2323 FreePool (DefaultResults);\r
2324 }\r
2325 \r
2326 if (DevicePath != NULL) {\r
2327 FreePool (DevicePath);\r
2328 } \r
93e3992d 2329\r
84f9a9ec 2330 return Status;\r
93e3992d 2331}\r
2332\r
2333\r
2334/**\r
2335 This function allows the caller to request the current configuration for the\r
2336 entirety of the current HII database and returns the data in a\r
2337 null-terminated Unicode string.\r
2338\r
2339 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2340 instance.\r
2341 @param Results Null-terminated Unicode string in\r
2342 <MultiConfigAltResp> format which has all values\r
2343 filled in for the names in the Request string.\r
2344 String to be allocated by the called function.\r
2345 De-allocation is up to the caller.\r
2346\r
2347 @retval EFI_SUCCESS The Results string is filled with the values\r
2348 corresponding to all requested names.\r
2349 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2350 results that must be stored awaiting possible\r
2351 future protocols.\r
2352 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
2353 parameter would result in this type of error.\r
2354\r
2355**/\r
2356EFI_STATUS\r
2357EFIAPI\r
2358HiiConfigRoutingExportConfig (\r
2359 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2360 OUT EFI_STRING *Results\r
2361 )\r
2362{\r
93e3992d 2363 EFI_STATUS Status;\r
93e3992d 2364 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
2365 EFI_STRING AccessResults;\r
2366 EFI_STRING Progress;\r
2367 EFI_STRING ConfigRequest;\r
8d00a0f1 2368 UINTN Index;\r
2369 EFI_HANDLE *ConfigAccessHandles;\r
2370 UINTN NumberConfigAccessHandles;\r
2371 BOOLEAN FirstElement;\r
84f9a9ec
LG
2372 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2373 EFI_HII_HANDLE HiiHandle;\r
2374 EFI_STRING DefaultResults;\r
2375 HII_DATABASE_PRIVATE_DATA *Private;\r
2376 LIST_ENTRY *Link;\r
2377 HII_DATABASE_RECORD *Database;\r
2378 UINT8 *DevicePathPkg;\r
2379 UINT8 *CurrentDevicePath;\r
2380 UINTN DevicePathLength;\r
93e3992d 2381\r
2382 if (This == NULL || Results == NULL) {\r
2383 return EFI_INVALID_PARAMETER;\r
2384 }\r
2385\r
84f9a9ec
LG
2386 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2387\r
93e3992d 2388 //\r
2389 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2390 // Results if this fix length is insufficient.\r
2391 //\r
2392 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2393 if (*Results == NULL) {\r
2394 return EFI_OUT_OF_RESOURCES;\r
2395 }\r
2396\r
8d00a0f1 2397 NumberConfigAccessHandles = 0;\r
2398 Status = gBS->LocateHandleBuffer (\r
2399 ByProtocol,\r
2400 &gEfiHiiConfigAccessProtocolGuid,\r
2401 NULL,\r
2402 &NumberConfigAccessHandles,\r
2403 &ConfigAccessHandles\r
2404 );\r
2405 if (EFI_ERROR (Status)) {\r
2406 return Status;\r
2407 }\r
93e3992d 2408\r
8d00a0f1 2409 FirstElement = TRUE;\r
93e3992d 2410\r
8d00a0f1 2411 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 2412 Status = gBS->HandleProtocol (\r
8d00a0f1 2413 ConfigAccessHandles[Index],\r
93e3992d 2414 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 2415 (VOID **) &ConfigAccess\r
93e3992d 2416 );\r
8d00a0f1 2417 if (EFI_ERROR (Status)) {\r
2418 continue;\r
2419 }\r
93e3992d 2420\r
84f9a9ec
LG
2421 //\r
2422 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
2423 //\r
2424 Progress = NULL;\r
2425 HiiHandle = NULL;\r
2426 ConfigRequest = NULL;\r
2427 DefaultResults = NULL;\r
2428 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
2429 DevicePathLength = GetDevicePathSize (DevicePath);\r
2430 if (DevicePath != NULL) {\r
2431 for (Link = Private->DatabaseList.ForwardLink;\r
2432 Link != &Private->DatabaseList;\r
2433 Link = Link->ForwardLink\r
2434 ) {\r
2435 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2436 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2437 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
2438 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) &&\r
2439 (CompareMem (\r
2440 DevicePath,\r
2441 CurrentDevicePath,\r
2442 DevicePathLength\r
2443 ) == 0)) {\r
2444 HiiHandle = Database->Handle;\r
2445 break;\r
2446 }\r
2447 }\r
2448 }\r
2449 }\r
2450\r
2451 //\r
2452 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2453 //\r
2454 if (HiiHandle != NULL && DevicePath != NULL) {\r
2455 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &DefaultResults);\r
2456 }\r
2457 //\r
2458 // Can't parse IFR data to get the request string and default string.\r
2459 //\r
2460 if (EFI_ERROR (Status)) {\r
2461 ConfigRequest = NULL;\r
2462 DefaultResults = NULL;\r
2463 }\r
2464 \r
93e3992d 2465 Status = ConfigAccess->ExtractConfig (\r
2466 ConfigAccess,\r
84f9a9ec
LG
2467 ConfigRequest,\r
2468 &Progress,\r
93e3992d 2469 &AccessResults\r
2470 );\r
8d00a0f1 2471 if (!EFI_ERROR (Status)) {\r
84f9a9ec
LG
2472 //\r
2473 // Merge the default sting from IFR code into the got setting from driver.\r
2474 //\r
2475 if (DefaultResults != NULL) {\r
2476 MergeDefaultString (&AccessResults, DefaultResults);\r
2477 FreePool (DefaultResults);\r
2478 }\r
2479 \r
8d00a0f1 2480 //\r
2481 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2482 // which seperates the first <ConfigAltResp> and the following ones. \r
2483 //\r
2484 if (!FirstElement) {\r
2485 Status = AppendToMultiString (Results, L"&");\r
2486 ASSERT_EFI_ERROR (Status);\r
676df92c 2487 }\r
8d00a0f1 2488 \r
2489 Status = AppendToMultiString (Results, AccessResults);\r
2490 ASSERT_EFI_ERROR (Status);\r
93e3992d 2491\r
8d00a0f1 2492 FirstElement = FALSE;\r
2493 \r
2494 FreePool (AccessResults);\r
2495 AccessResults = NULL;\r
2496 }\r
93e3992d 2497 }\r
f4113e1f 2498 FreePool (ConfigAccessHandles);\r
93e3992d 2499\r
8d00a0f1 2500 return EFI_SUCCESS; \r
93e3992d 2501}\r
2502\r
2503\r
2504/**\r
2505 This function processes the results of processing forms and routes it to the\r
2506 appropriate handlers or storage.\r
2507\r
2508 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2509 instance.\r
2510 @param Configuration A null-terminated Unicode string in\r
2511 <MulltiConfigResp> format.\r
2512 @param Progress A pointer to a string filled in with the offset of\r
2513 the most recent & before the first failing name /\r
2514 value pair (or the beginning of the string if the\r
2515 failure is in the first name / value pair) or the\r
2516 terminating NULL if all was successful.\r
2517\r
2518 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
2519 distribution.\r
2520 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2521 results that must be stored awaiting possible\r
2522 future protocols.\r
2523 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
2524 would result in this type of error.\r
2525 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
2526 found.\r
2527\r
2528**/\r
2529EFI_STATUS\r
2530EFIAPI\r
813acf3a 2531HiiConfigRoutingRouteConfig (\r
93e3992d 2532 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2533 IN CONST EFI_STRING Configuration,\r
2534 OUT EFI_STRING *Progress\r
2535 )\r
2536{\r
84f9a9ec 2537 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2538 EFI_STRING StringPtr;\r
2539 EFI_STRING ConfigResp;\r
2540 UINTN Length;\r
2541 EFI_STATUS Status;\r
2542 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2543 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
2544 LIST_ENTRY *Link;\r
2545 HII_DATABASE_RECORD *Database;\r
2546 UINT8 *DevicePathPkg;\r
2547 UINT8 *CurrentDevicePath;\r
93e3992d 2548 EFI_HANDLE DriverHandle;\r
2549 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2550 EFI_STRING AccessProgress;\r
84f9a9ec 2551 UINTN DevicePathLength;\r
93e3992d 2552\r
2553 if (This == NULL || Progress == NULL) {\r
2554 return EFI_INVALID_PARAMETER;\r
2555 }\r
2556\r
2557 if (Configuration == NULL) {\r
2558 *Progress = NULL;\r
2559 return EFI_INVALID_PARAMETER;\r
2560 }\r
2561\r
84f9a9ec 2562 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2563 StringPtr = Configuration;\r
2564 *Progress = StringPtr;\r
2565\r
2566 //\r
2567 // The first element of <MultiConfigResp> should be\r
2568 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2569 //\r
2570 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2571 return EFI_INVALID_PARAMETER;\r
2572 }\r
2573\r
2574 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2575 //\r
2576 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
2577 // or most recent & before the error.\r
2578 //\r
2579 if (StringPtr == Configuration) {\r
2580 *Progress = StringPtr;\r
2581 } else {\r
2582 *Progress = StringPtr - 1;\r
2583 }\r
2584\r
2585 //\r
2586 // Process each <ConfigResp> of <MultiConfigResp>\r
2587 //\r
2588 Length = CalculateConfigStringLen (StringPtr);\r
2589 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2590 if (ConfigResp == NULL) {\r
2591 return EFI_OUT_OF_RESOURCES;\r
2592 }\r
2593 //\r
2594 // Append '\0' to the end of ConfigRequest\r
2595 //\r
2596 *(ConfigResp + Length) = 0;\r
2597\r
2598 //\r
2599 // Get the UEFI device path\r
2600 //\r
2601 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
2602 if (EFI_ERROR (Status)) {\r
676df92c 2603 FreePool (ConfigResp);\r
93e3992d 2604 return Status;\r
2605 }\r
2606\r
2607 //\r
84f9a9ec
LG
2608 // Find driver which matches the routing data.\r
2609 //\r
2610 DriverHandle = NULL;\r
2611 DevicePathLength = GetDevicePathSize (DevicePath);\r
2612 for (Link = Private->DatabaseList.ForwardLink;\r
2613 Link != &Private->DatabaseList;\r
2614 Link = Link->ForwardLink\r
2615 ) {\r
2616 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2617\r
2618 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2619 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
2620 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) &&\r
2621 (CompareMem (\r
2622 DevicePath,\r
2623 CurrentDevicePath,\r
2624 DevicePathLength\r
2625 ) == 0)) {\r
2626 DriverHandle = Database->DriverHandle;\r
2627 break;\r
2628 }\r
2629 }\r
2630 }\r
93e3992d 2631\r
84f9a9ec
LG
2632 //\r
2633 // Try to find driver handle by device path.\r
2634 //\r
2635 if (DriverHandle == NULL) {\r
2636 TempDevicePath = DevicePath;\r
2637 Status = gBS->LocateDevicePath (\r
2638 &gEfiDevicePathProtocolGuid,\r
2639 &TempDevicePath,\r
2640 &DriverHandle\r
2641 );\r
2642 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2643 //\r
2644 // Routing data does not match any known driver.\r
2645 // Set Progress to the 'G' in "GUID" of the routing header.\r
2646 //\r
2647 FreePool (DevicePath);\r
2648 *Progress = StringPtr;\r
2649 FreePool (ConfigResp);\r
2650 return EFI_NOT_FOUND;\r
2651 }\r
93e3992d 2652 }\r
2653\r
84f9a9ec
LG
2654 FreePool (DevicePath);\r
2655\r
93e3992d 2656 //\r
2657 // Call corresponding ConfigAccess protocol to route settings\r
2658 //\r
2659 Status = gBS->HandleProtocol (\r
2660 DriverHandle,\r
2661 &gEfiHiiConfigAccessProtocolGuid,\r
2662 (VOID **) &ConfigAccess\r
2663 );\r
2664 ASSERT_EFI_ERROR (Status);\r
2665\r
2666 Status = ConfigAccess->RouteConfig (\r
2667 ConfigAccess,\r
2668 ConfigResp,\r
2669 &AccessProgress\r
2670 );\r
2671\r
2672 if (EFI_ERROR (Status)) {\r
2673 //\r
2674 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
2675 // Map it to the progress on <MultiConfigResp> then return it.\r
2676 //\r
8d00a0f1 2677 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 2678\r
676df92c 2679 FreePool (ConfigResp);\r
93e3992d 2680 return Status;\r
2681 }\r
2682\r
676df92c 2683 FreePool (ConfigResp);\r
93e3992d 2684 ConfigResp = NULL;\r
2685\r
2686 //\r
2687 // Go to next <ConfigResp> (skip '&').\r
2688 //\r
2689 StringPtr += Length;\r
2690 if (*StringPtr == 0) {\r
2691 *Progress = StringPtr;\r
2692 break;\r
2693 }\r
2694\r
2695 StringPtr++;\r
2696\r
2697 }\r
2698\r
2699 return EFI_SUCCESS;\r
93e3992d 2700}\r
2701\r
2702\r
2703/**\r
2704 This helper function is to be called by drivers to map configuration data\r
2705 stored in byte array ("block") formats such as UEFI Variables into current\r
2706 configuration strings.\r
2707\r
2708 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2709 instance.\r
2710 @param ConfigRequest A null-terminated Unicode string in\r
2711 <ConfigRequest> format.\r
2712 @param Block Array of bytes defining the block's configuration.\r
2713 @param BlockSize Length in bytes of Block.\r
2714 @param Config Filled-in configuration string. String allocated\r
2715 by the function. Returned only if call is\r
84f9a9ec 2716 successful. It is <ConfigResp> string format.\r
93e3992d 2717 @param Progress A pointer to a string filled in with the offset of\r
2718 the most recent & before the first failing\r
2719 name/value pair (or the beginning of the string if\r
2720 the failure is in the first name / value pair) or\r
2721 the terminating NULL if all was successful.\r
2722\r
2723 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
2724 terminator at the end of the ConfigRequest\r
2725 string.\r
2726 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
2727 points to the first character of ConfigRequest.\r
2728 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
2729 Block parameter would result in this type of\r
2730 error. Progress points to the first character of\r
2731 ConfigRequest.\r
2732 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
2733 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
2734 Block is left updated and Progress points at\r
2735 the "&" preceding the first non-<BlockName>.\r
2736\r
2737**/\r
2738EFI_STATUS\r
2739EFIAPI\r
2740HiiBlockToConfig (\r
2741 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2742 IN CONST EFI_STRING ConfigRequest,\r
2743 IN CONST UINT8 *Block,\r
2744 IN CONST UINTN BlockSize,\r
2745 OUT EFI_STRING *Config,\r
2746 OUT EFI_STRING *Progress\r
2747 )\r
2748{\r
84f9a9ec 2749 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2750 EFI_STRING StringPtr;\r
2751 UINTN Length;\r
2752 EFI_STATUS Status;\r
2753 EFI_STRING TmpPtr;\r
2754 UINT8 *TmpBuffer;\r
2755 UINTN Offset;\r
2756 UINTN Width;\r
2757 UINT8 *Value;\r
2758 EFI_STRING ValueStr;\r
2759 EFI_STRING ConfigElement;\r
63d55bb9
LG
2760 UINTN Index;\r
2761 UINT8 *TemBuffer;\r
2762 CHAR16 *TemString;\r
93e3992d 2763\r
2764 if (This == NULL || Progress == NULL || Config == NULL) {\r
2765 return EFI_INVALID_PARAMETER;\r
2766 }\r
2767\r
2768 if (Block == NULL || ConfigRequest == NULL) {\r
2769 *Progress = ConfigRequest;\r
2770 return EFI_INVALID_PARAMETER;\r
2771 }\r
2772\r
84f9a9ec
LG
2773\r
2774 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2775 ASSERT (Private != NULL);\r
2776\r
93e3992d 2777 StringPtr = ConfigRequest;\r
2778 ValueStr = NULL;\r
2779 Value = NULL;\r
2780 ConfigElement = NULL;\r
2781\r
2782 //\r
2783 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2784 // Results if this fix length is insufficient.\r
2785 //\r
2786 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2787 if (*Config == NULL) {\r
2788 return EFI_OUT_OF_RESOURCES;\r
2789 }\r
2790\r
2791 //\r
2792 // Jump <ConfigHdr>\r
2793 //\r
2794 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2795 *Progress = StringPtr;\r
2796 Status = EFI_INVALID_PARAMETER;\r
2797 goto Exit;\r
2798 }\r
2799 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
2800 StringPtr++;\r
2801 }\r
2802 if (*StringPtr == 0) {\r
76c24251 2803 *Progress = StringPtr - 1;\r
93e3992d 2804 Status = EFI_INVALID_PARAMETER;\r
2805 goto Exit;\r
2806 }\r
08e6463a 2807\r
2808 while (*StringPtr != L'&' && *StringPtr != 0) {\r
2809 StringPtr++;\r
2810 }\r
2811 if (*StringPtr == 0) {\r
76c24251 2812 *Progress = StringPtr - 1;\r
08e6463a 2813 Status = EFI_INVALID_PARAMETER;\r
2814 goto Exit;\r
2815 }\r
2816 //\r
2817 // Skip '&'\r
2818 //\r
2819 StringPtr++;\r
93e3992d 2820\r
2821 //\r
2822 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
2823 //\r
2824 Length = StringPtr - ConfigRequest;\r
2825 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
2826\r
2827 //\r
2828 // Parse each <RequestElement> if exists\r
2829 // Only <BlockName> format is supported by this help function.\r
2830 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
2831 //\r
2832 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
2833 //\r
2834 // Back up the header of one <BlockName>\r
2835 //\r
2836 TmpPtr = StringPtr;\r
2837\r
2838 StringPtr += StrLen (L"OFFSET=");\r
2839 //\r
2840 // Get Offset\r
2841 //\r
2842 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2843 if (Status == EFI_OUT_OF_RESOURCES) {\r
2844 *Progress = ConfigRequest;\r
2845 goto Exit;\r
2846 }\r
2847 Offset = 0;\r
2848 CopyMem (\r
2849 &Offset,\r
2850 TmpBuffer,\r
2851 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
2852 );\r
676df92c 2853 FreePool (TmpBuffer);\r
93e3992d 2854\r
2855 StringPtr += Length;\r
2856 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
2857 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
2858 Status = EFI_INVALID_PARAMETER;\r
2859 goto Exit;\r
2860 }\r
2861 StringPtr += StrLen (L"&WIDTH=");\r
2862\r
2863 //\r
2864 // Get Width\r
2865 //\r
2866 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2867 if (Status == EFI_OUT_OF_RESOURCES) {\r
2868 *Progress = ConfigRequest;\r
2869 goto Exit;\r
2870 }\r
2871 Width = 0;\r
2872 CopyMem (\r
2873 &Width,\r
2874 TmpBuffer,\r
2875 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
2876 );\r
676df92c 2877 FreePool (TmpBuffer);\r
93e3992d 2878\r
2879 StringPtr += Length;\r
2880 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2881 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
2882 Status = EFI_INVALID_PARAMETER;\r
2883 goto Exit;\r
2884 }\r
2885\r
2886 //\r
2887 // Calculate Value and convert it to hex string.\r
2888 //\r
2889 if (Offset + Width > BlockSize) {\r
2890 *Progress = StringPtr;\r
2891 Status = EFI_DEVICE_ERROR;\r
2892 goto Exit;\r
2893 }\r
2894\r
2895 Value = (UINT8 *) AllocateZeroPool (Width);\r
2896 if (Value == NULL) {\r
2897 *Progress = ConfigRequest;\r
2898 Status = EFI_OUT_OF_RESOURCES;\r
2899 goto Exit;\r
2900 }\r
2901\r
2902 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
2903\r
2904 Length = Width * 2 + 1;\r
2905 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
2906 if (ValueStr == NULL) {\r
2907 *Progress = ConfigRequest;\r
2908 Status = EFI_OUT_OF_RESOURCES;\r
2909 goto Exit;\r
2910 }\r
63d55bb9
LG
2911 \r
2912 TemString = ValueStr;\r
2913 TemBuffer = Value + Width - 1;\r
2914 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
2915 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
2916 }\r
813acf3a 2917\r
676df92c 2918 FreePool (Value);\r
93e3992d 2919 Value = NULL;\r
2920\r
2921 //\r
2922 // Build a ConfigElement\r
2923 //\r
2924 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
2925 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
2926 if (ConfigElement == NULL) {\r
2927 Status = EFI_OUT_OF_RESOURCES;\r
2928 goto Exit;\r
2929 }\r
2930 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
2931 if (*StringPtr == 0) {\r
2932 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
2933 }\r
2934 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
2935 StrCat (ConfigElement, L"VALUE=");\r
2936 StrCat (ConfigElement, ValueStr);\r
2937\r
2938 AppendToMultiString (Config, ConfigElement);\r
2939\r
676df92c 2940 FreePool (ConfigElement);\r
2941 FreePool (ValueStr);\r
93e3992d 2942 ConfigElement = NULL;\r
2943 ValueStr = NULL;\r
2944\r
2945 //\r
2946 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
2947 //\r
2948 if (*StringPtr == 0) {\r
2949 break;\r
2950 }\r
2951 AppendToMultiString (Config, L"&");\r
2952 StringPtr++;\r
2953\r
2954 }\r
2955\r
2956 if (*StringPtr != 0) {\r
2957 *Progress = StringPtr - 1;\r
2958 Status = EFI_INVALID_PARAMETER;\r
2959 goto Exit;\r
2960 }\r
84f9a9ec
LG
2961 \r
2962 HiiToLower (*Config);\r
93e3992d 2963 *Progress = StringPtr;\r
2964 return EFI_SUCCESS;\r
2965\r
2966Exit:\r
76c24251 2967 if (*Config != NULL) {\r
1f1cb2f2
LG
2968 FreePool (*Config);\r
2969 *Config = NULL;\r
76c24251 2970 }\r
676df92c 2971 if (ValueStr != NULL) {\r
2972 FreePool (ValueStr);\r
2973 }\r
2974 if (Value != NULL) {\r
2975 FreePool (Value);\r
2976 }\r
69367b5b 2977 if (ConfigElement != NULL) {\r
676df92c 2978 FreePool (ConfigElement);\r
2979 }\r
93e3992d 2980\r
2981 return Status;\r
2982\r
2983}\r
2984\r
2985\r
2986/**\r
2987 This helper function is to be called by drivers to map configuration strings\r
2988 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
2989\r
2990 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2991 instance.\r
2992 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
84f9a9ec 2993 format. It can be ConfigAltResp format string.\r
93e3992d 2994 @param Block A possibly null array of bytes representing the\r
2995 current block. Only bytes referenced in the\r
2996 ConfigResp string in the block are modified. If\r
2997 this parameter is null or if the *BlockSize\r
2998 parameter is (on input) shorter than required by\r
2999 the Configuration string, only the BlockSize\r
3000 parameter is updated and an appropriate status\r
3001 (see below) is returned.\r
3002 @param BlockSize The length of the Block in units of UINT8. On\r
3003 input, this is the size of the Block. On output,\r
3004 if successful, contains the index of the last\r
3005 modified byte in the Block.\r
3006 @param Progress On return, points to an element of the ConfigResp\r
3007 string filled in with the offset of the most\r
3008 recent '&' before the first failing name / value\r
3009 pair (or the beginning of the string if the\r
3010 failure is in the first name / value pair) or the\r
3011 terminating NULL if all was successful.\r
3012\r
3013 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
3014 terminator at the end of the ConfigResp string.\r
3015 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
3016 points to the first character of ConfigResp.\r
3017 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
3018 Block parameter would result in this type of\r
3019 error. Progress points to the first character of\r
3020 ConfigResp.\r
3021 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
3022 value pair. Block is left updated and\r
3023 Progress points at the '&' preceding the first\r
3024 non-<BlockName>.\r
3025\r
3026**/\r
3027EFI_STATUS\r
3028EFIAPI\r
3029HiiConfigToBlock (\r
3030 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3031 IN CONST EFI_STRING ConfigResp,\r
3032 IN OUT UINT8 *Block,\r
3033 IN OUT UINTN *BlockSize,\r
3034 OUT EFI_STRING *Progress\r
3035 )\r
3036{\r
3037 HII_DATABASE_PRIVATE_DATA *Private;\r
3038 EFI_STRING StringPtr;\r
3039 UINTN Length;\r
3040 EFI_STATUS Status;\r
3041 UINT8 *TmpBuffer;\r
3042 UINTN Offset;\r
3043 UINTN Width;\r
3044 UINT8 *Value;\r
3045 UINTN BufferSize;\r
3046\r
3047 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
3048 return EFI_INVALID_PARAMETER;\r
3049 }\r
3050\r
3051 if (ConfigResp == NULL || Block == NULL) {\r
3052 *Progress = ConfigResp;\r
3053 return EFI_INVALID_PARAMETER;\r
3054 }\r
3055\r
3056 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3057 ASSERT (Private != NULL);\r
3058\r
3059 StringPtr = ConfigResp;\r
3060 BufferSize = *BlockSize;\r
3061 Value = NULL;\r
3062\r
3063 //\r
3064 // Jump <ConfigHdr>\r
3065 //\r
3066 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3067 *Progress = StringPtr;\r
3068 Status = EFI_INVALID_PARAMETER;\r
3069 goto Exit;\r
3070 }\r
3071 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
3072 StringPtr++;\r
3073 }\r
3074 if (*StringPtr == 0) {\r
3075 *Progress = StringPtr;\r
3076 Status = EFI_INVALID_PARAMETER;\r
3077 goto Exit;\r
3078 }\r
08e6463a 3079\r
3080 while (*StringPtr != L'&' && *StringPtr != 0) {\r
3081 StringPtr++;\r
3082 }\r
3083 if (*StringPtr == 0) {\r
3084 *Progress = StringPtr;\r
3085 Status = EFI_INVALID_PARAMETER;\r
3086 goto Exit;\r
3087 }\r
3088 //\r
3089 // Skip '&'\r
3090 //\r
3091 StringPtr++;\r
93e3992d 3092\r
3093 //\r
3094 // Parse each <ConfigElement> if exists\r
3095 // Only <BlockConfig> format is supported by this help function.\r
3096 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
3097 //\r
3098 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
3099 StringPtr += StrLen (L"OFFSET=");\r
3100 //\r
3101 // Get Offset\r
3102 //\r
3103 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 3104 if (EFI_ERROR (Status)) {\r
93e3992d 3105 *Progress = ConfigResp;\r
3106 goto Exit;\r
3107 }\r
3108 Offset = 0;\r
3109 CopyMem (\r
3110 &Offset,\r
3111 TmpBuffer,\r
3112 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3113 );\r
676df92c 3114 FreePool (TmpBuffer);\r
93e3992d 3115\r
3116 StringPtr += Length;\r
3117 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3118 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
3119 Status = EFI_INVALID_PARAMETER;\r
3120 goto Exit;\r
3121 }\r
3122 StringPtr += StrLen (L"&WIDTH=");\r
3123\r
3124 //\r
3125 // Get Width\r
3126 //\r
3127 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3128 if (Status == EFI_OUT_OF_RESOURCES) {\r
3129 *Progress = ConfigResp;\r
3130 goto Exit;\r
3131 }\r
3132 Width = 0;\r
3133 CopyMem (\r
3134 &Width,\r
3135 TmpBuffer,\r
3136 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3137 );\r
676df92c 3138 FreePool (TmpBuffer);\r
93e3992d 3139\r
3140 StringPtr += Length;\r
3141 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
3142 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
3143 Status = EFI_INVALID_PARAMETER;\r
3144 goto Exit;\r
3145 }\r
3146 StringPtr += StrLen (L"&VALUE=");\r
3147\r
3148 //\r
3149 // Get Value\r
3150 //\r
3151 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 3152 if (EFI_ERROR (Status)) {\r
93e3992d 3153 *Progress = ConfigResp;\r
3154 goto Exit;\r
3155 }\r
3156\r
3157 StringPtr += Length;\r
3158 if (*StringPtr != 0 && *StringPtr != L'&') {\r
3159 *Progress = StringPtr - Length - 7;\r
3160 Status = EFI_INVALID_PARAMETER;\r
3161 goto Exit;\r
3162 }\r
3163\r
3164 //\r
3165 // Update the Block with configuration info\r
3166 //\r
3167\r
3168 if (Offset + Width > BufferSize) {\r
3169 return EFI_DEVICE_ERROR;\r
3170 }\r
3171\r
3172 CopyMem (Block + Offset, Value, Width);\r
3173 *BlockSize = Offset + Width - 1;\r
3174\r
676df92c 3175 FreePool (Value);\r
93e3992d 3176 Value = NULL;\r
3177\r
3178 //\r
3179 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
3180 //\r
3181 if (*StringPtr == 0) {\r
3182 break;\r
3183 }\r
3184\r
3185 StringPtr++;\r
3186 }\r
84f9a9ec
LG
3187 \r
3188 //\r
3189 // The input string is ConfigAltResp format.\r
3190 //\r
3191 if ((*StringPtr != 0) && (StrnCmp (StringPtr, L"&GUID=", StrLen (L"&GUID=")) != 0)) {\r
93e3992d 3192 *Progress = StringPtr - 1;\r
3193 Status = EFI_INVALID_PARAMETER;\r
3194 goto Exit;\r
3195 }\r
3196\r
3197 *Progress = StringPtr;\r
3198 return EFI_SUCCESS;\r
3199\r
3200Exit:\r
3201\r
676df92c 3202 if (Value != NULL) {\r
3203 FreePool (Value);\r
3204 }\r
93e3992d 3205 return Status;\r
3206}\r
3207\r
3208\r
3209/**\r
3210 This helper function is to be called by drivers to extract portions of\r
3211 a larger configuration string.\r
3212\r
3213 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3214 instance.\r
3215 @param Configuration A null-terminated Unicode string in\r
84f9a9ec 3216 <MultiConfigAltResp> format. It is <ConfigAltResp> format.\r
93e3992d 3217 @param Guid A pointer to the GUID value to search for in the\r
3218 routing portion of the ConfigResp string when\r
3219 retrieving the requested data. If Guid is NULL,\r
3220 then all GUID values will be searched for.\r
3221 @param Name A pointer to the NAME value to search for in the\r
3222 routing portion of the ConfigResp string when\r
3223 retrieving the requested data. If Name is NULL,\r
3224 then all Name values will be searched for.\r
3225 @param DevicePath A pointer to the PATH value to search for in the\r
3226 routing portion of the ConfigResp string when\r
3227 retrieving the requested data. If DevicePath is\r
3228 NULL, then all DevicePath values will be searched\r
3229 for.\r
3230 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
3231 routing portion of the ConfigResp string when\r
3232 retrieving the requested data. If this parameter\r
3233 is NULL, then the current setting will be\r
3234 retrieved.\r
3235 @param AltCfgResp A pointer to a buffer which will be allocated by\r
3236 the function which contains the retrieved string\r
3237 as requested. This buffer is only allocated if\r
84f9a9ec 3238 the call was successful. It is <ConfigResp> format.\r
93e3992d 3239\r
3240 @retval EFI_SUCCESS The request succeeded. The requested data was\r
3241 extracted and placed in the newly allocated\r
3242 AltCfgResp buffer.\r
3243 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
3244 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
3245 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
3246 found.\r
3247\r
3248**/\r
3249EFI_STATUS\r
3250EFIAPI\r
3251HiiGetAltCfg (\r
3252 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3253 IN CONST EFI_STRING Configuration,\r
3254 IN CONST EFI_GUID *Guid,\r
3255 IN CONST EFI_STRING Name,\r
3256 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
3257 IN CONST UINT16 *AltCfgId,\r
3258 OUT EFI_STRING *AltCfgResp\r
3259 )\r
3260{\r
93e3992d 3261 EFI_STATUS Status;\r
3262 EFI_STRING StringPtr;\r
e90b081a 3263 EFI_STRING HdrStart;\r
3264 EFI_STRING HdrEnd;\r
93e3992d 3265 EFI_STRING TmpPtr;\r
3266 UINTN Length;\r
e90b081a 3267 EFI_STRING GuidStr;\r
3268 EFI_STRING NameStr;\r
3269 EFI_STRING PathStr;\r
3270 EFI_STRING AltIdStr;\r
3271 EFI_STRING Result;\r
3272 BOOLEAN GuidFlag;\r
3273 BOOLEAN NameFlag;\r
3274 BOOLEAN PathFlag;\r
3275\r
3276 HdrStart = NULL;\r
3277 HdrEnd = NULL;\r
3278 GuidStr = NULL;\r
3279 NameStr = NULL;\r
3280 PathStr = NULL;\r
3281 AltIdStr = NULL;\r
3282 Result = NULL;\r
3283 GuidFlag = FALSE;\r
3284 NameFlag = FALSE;\r
3285 PathFlag = FALSE;\r
93e3992d 3286\r
3287 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
3288 return EFI_INVALID_PARAMETER;\r
3289 }\r
3290\r
3291 StringPtr = Configuration;\r
3292 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3293 return EFI_INVALID_PARAMETER;\r
3294 }\r
3295\r
3296 //\r
3297 // Generate the sub string for later matching.\r
3298 //\r
813acf3a 3299 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 3300 GenerateSubStr (\r
3301 L"PATH=",\r
3302 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 3303 (VOID *) DevicePath,\r
3304 1,\r
93e3992d 3305 &PathStr\r
3306 );\r
3307 if (AltCfgId != NULL) {\r
813acf3a 3308 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 3309 }\r
3310 if (Name != NULL) {\r
813acf3a 3311 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 3312 } else {\r
813acf3a 3313 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 3314 }\r
3315\r
3316 while (*StringPtr != 0) {\r
3317 //\r
3318 // Try to match the GUID\r
3319 //\r
3320 if (!GuidFlag) {\r
3321 TmpPtr = StrStr (StringPtr, GuidStr);\r
3322 if (TmpPtr == NULL) {\r
3323 Status = EFI_NOT_FOUND;\r
3324 goto Exit;\r
3325 }\r
3326 HdrStart = TmpPtr;\r
3327\r
3328 //\r
3329 // Jump to <NameHdr>\r
3330 //\r
3331 if (Guid != NULL) {\r
3332 StringPtr = TmpPtr + StrLen (GuidStr);\r
3333 } else {\r
3334 StringPtr = StrStr (TmpPtr, L"NAME=");\r
3335 if (StringPtr == NULL) {\r
3336 Status = EFI_NOT_FOUND;\r
3337 goto Exit;\r
3338 }\r
3339 }\r
3340 GuidFlag = TRUE;\r
3341 }\r
3342\r
3343 //\r
3344 // Try to match the NAME\r
3345 //\r
3346 if (GuidFlag && !NameFlag) {\r
3347 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
3348 GuidFlag = FALSE;\r
3349 } else {\r
3350 //\r
3351 // Jump to <PathHdr>\r
3352 //\r
3353 if (Name != NULL) {\r
3354 StringPtr += StrLen (NameStr);\r
3355 } else {\r
3356 StringPtr = StrStr (StringPtr, L"PATH=");\r
3357 if (StringPtr == NULL) {\r
3358 Status = EFI_NOT_FOUND;\r
3359 goto Exit;\r
3360 }\r
3361 }\r
3362 NameFlag = TRUE;\r
3363 }\r
3364 }\r
3365\r
3366 //\r
3367 // Try to match the DevicePath\r
3368 //\r
3369 if (GuidFlag && NameFlag && !PathFlag) {\r
3370 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
3371 GuidFlag = FALSE;\r
3372 NameFlag = FALSE;\r
3373 } else {\r
3374 //\r
3375 // Jump to '&' before <DescHdr> or <ConfigBody>\r
3376 //\r
3377 if (DevicePath != NULL) {\r
3378 StringPtr += StrLen (PathStr);\r
3379 } else {\r
3380 StringPtr = StrStr (StringPtr, L"&");\r
3381 if (StringPtr == NULL) {\r
3382 Status = EFI_NOT_FOUND;\r
3383 goto Exit;\r
3384 }\r
84f9a9ec 3385 StringPtr ++;\r
93e3992d 3386 }\r
3387 PathFlag = TRUE;\r
84f9a9ec 3388 HdrEnd = StringPtr;\r
93e3992d 3389 }\r
3390 }\r
3391\r
3392 //\r
3393 // Try to match the AltCfgId\r
3394 //\r
3395 if (GuidFlag && NameFlag && PathFlag) {\r
3396 if (AltCfgId == NULL) {\r
3397 //\r
3398 // Return Current Setting when AltCfgId is NULL.\r
3399 //\r
3400 Status = OutputConfigBody (StringPtr, &Result);\r
3401 goto Exit;\r
3402 }\r
3403 //\r
3404 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
3405 //\r
3406 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
3407 GuidFlag = FALSE;\r
3408 NameFlag = FALSE;\r
3409 PathFlag = FALSE;\r
3410 } else {\r
84f9a9ec
LG
3411 //\r
3412 // Skip AltIdStr and &\r
3413 //\r
3414 StringPtr = StringPtr + StrLen (AltIdStr);\r
3415 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 3416 goto Exit;\r
3417 }\r
3418 }\r
3419 }\r
3420\r
3421 Status = EFI_NOT_FOUND;\r
3422\r
3423Exit:\r
76c24251 3424 *AltCfgResp = NULL;\r
bc166db3 3425 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 3426 //\r
3427 // Copy the <ConfigHdr> and <ConfigBody>\r
3428 //\r
84f9a9ec 3429 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 3430 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
3431 if (*AltCfgResp == NULL) {\r
3432 Status = EFI_OUT_OF_RESOURCES;\r
3433 } else {\r
3434 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
3435 StrCat (*AltCfgResp, Result);\r
3436 Status = EFI_SUCCESS;\r
3437 }\r
3438 }\r
3439\r
676df92c 3440 if (GuidStr != NULL) {\r
3441 FreePool (GuidStr);\r
3442 }\r
3443 if (NameStr != NULL) {\r
3444 FreePool (NameStr);\r
3445 }\r
3446 if (PathStr != NULL) {\r
3447 FreePool (PathStr);\r
3448 }\r
3449 if (AltIdStr != NULL) {\r
3450 FreePool (AltIdStr);\r
3451 }\r
3452 if (Result != NULL) {\r
3453 FreePool (Result);\r
3454 }\r
93e3992d 3455\r
3456 return Status;\r
3457\r
93e3992d 3458}\r
3459\r
36fe40c2 3460\r