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