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