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