]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
Fix IA32 build failure.
[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
a7f87053 4Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
93e3992d 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
ae79d2f9 64 @param DevicePathData Binary of a UEFI device path.\r
93e3992d 65\r
ae79d2f9 66 @retval EFI_NOT_FOUND The device path is not invalid.\r
93e3992d 67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
69 @retval EFI_SUCCESS The device path is retrieved and translated to\r
70 binary format.\r
71\r
72**/\r
93e3992d 73EFI_STATUS\r
74GetDevicePath (\r
75 IN EFI_STRING String,\r
ae79d2f9 76 OUT UINT8 **DevicePathData\r
93e3992d 77 )\r
78{\r
ae79d2f9
LG
79 UINTN Length;\r
80 EFI_STRING PathHdr;\r
81 UINT8 *DevicePathBuffer;\r
82 CHAR16 TemStr[2];\r
83 UINTN Index;\r
84 UINT8 DigitUint8;\r
85 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
86\r
87\r
88 if (String == NULL || DevicePathData == NULL) {\r
93e3992d 89 return EFI_INVALID_PARAMETER;\r
90 }\r
91\r
92 //\r
93 // Find the 'PATH=' of <PathHdr> and skip it.\r
94 //\r
95 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
96 if (*String == 0) {\r
97 return EFI_INVALID_PARAMETER;\r
98 }\r
ae79d2f9
LG
99 //\r
100 // Check whether path data does exist.\r
101 //\r
93e3992d 102 String += StrLen (L"PATH=");\r
ae79d2f9
LG
103 if (*String == 0) {\r
104 return EFI_INVALID_PARAMETER;\r
105 }\r
93e3992d 106 PathHdr = String;\r
107\r
108 //\r
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
111 // of UEFI device path.\r
112 //\r
113 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
ae79d2f9
LG
114 //\r
115 // Check DevicePath Length\r
116 //\r
117 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
118 return EFI_NOT_FOUND;\r
93e3992d 119 }\r
ae79d2f9 120 \r
93e3992d 121 //\r
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
123 // as the device path resides in RAM memory.\r
124 // Translate the data into binary.\r
93e3992d 125 //\r
63d55bb9
LG
126 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
127 if (DevicePathBuffer == NULL) {\r
93e3992d 128 return EFI_OUT_OF_RESOURCES;\r
129 }\r
ae79d2f9
LG
130 \r
131 //\r
132 // Convert DevicePath\r
133 //\r
63d55bb9 134 ZeroMem (TemStr, sizeof (TemStr));\r
ae79d2f9
LG
135 for (Index = 0; Index < Length; Index ++) {\r
136 TemStr[0] = PathHdr[Index];\r
63d55bb9
LG
137 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
138 if ((Index & 1) == 0) {\r
139 DevicePathBuffer [Index/2] = DigitUint8;\r
140 } else {\r
141 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
142 }\r
143 }\r
63d55bb9 144 \r
ae79d2f9
LG
145 //\r
146 // Validate DevicePath\r
147 //\r
148 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;\r
149 while (!IsDevicePathEnd (DevicePath)) {\r
91a306ee 150 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {\r
ae79d2f9
LG
151 //\r
152 // Invalid device path\r
153 //\r
154 FreePool (DevicePathBuffer);\r
155 return EFI_NOT_FOUND;\r
156 }\r
157 DevicePath = NextDevicePathNode (DevicePath);\r
158 }\r
93e3992d 159\r
ae79d2f9
LG
160 //\r
161 // return the device path\r
162 //\r
163 *DevicePathData = DevicePathBuffer;\r
93e3992d 164 return EFI_SUCCESS;\r
93e3992d 165}\r
166\r
63d55bb9
LG
167/**\r
168 Converts the unicode character of the string from uppercase to lowercase.\r
169 This is a internal function.\r
170\r
aa75dfec 171 @param ConfigString String to be converted\r
63d55bb9
LG
172\r
173**/\r
174VOID\r
175EFIAPI\r
176HiiToLower (\r
84f9a9ec 177 IN EFI_STRING ConfigString\r
63d55bb9
LG
178 )\r
179{\r
84f9a9ec
LG
180 EFI_STRING String;\r
181 BOOLEAN Lower;\r
182\r
183 ASSERT (ConfigString != NULL);\r
184\r
185 //\r
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
187 //\r
188 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
189 if (*String == L'=') {\r
190 Lower = TRUE;\r
191 } else if (*String == L'&') {\r
192 Lower = FALSE;\r
193 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
194 *String = (CHAR16) (*String - L'A' + L'a');\r
63d55bb9
LG
195 }\r
196 }\r
84f9a9ec
LG
197\r
198 return;\r
63d55bb9 199}\r
93e3992d 200\r
93e3992d 201/**\r
202 Generate a sub string then output it.\r
203\r
e90b081a 204 This is a internal function.\r
205\r
93e3992d 206 @param String A constant string which is the prefix of the to be\r
207 generated string, e.g. GUID=\r
84f9a9ec 208\r
93e3992d 209 @param BufferLen The length of the Buffer in bytes.\r
84f9a9ec 210\r
813acf3a 211 @param Buffer Points to a buffer which will be converted to be the \r
84f9a9ec
LG
212 content of the generated string.\r
213\r
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in \r
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
216 if 3, the buffer contains other data.\r
217\r
93e3992d 218 @param SubStr Points to the output string. It's caller's\r
219 responsibility to free this buffer.\r
220\r
221\r
222**/\r
93e3992d 223VOID\r
224GenerateSubStr (\r
225 IN CONST EFI_STRING String,\r
226 IN UINTN BufferLen,\r
813acf3a 227 IN VOID *Buffer,\r
228 IN UINT8 Flag,\r
93e3992d 229 OUT EFI_STRING *SubStr\r
230 )\r
231{\r
232 UINTN Length;\r
233 EFI_STRING Str;\r
813acf3a 234 EFI_STRING StringHeader;\r
63d55bb9
LG
235 CHAR16 *TemString;\r
236 CHAR16 *TemName;\r
237 UINT8 *TemBuffer;\r
238 UINTN Index;\r
93e3992d 239\r
240 ASSERT (String != NULL && SubStr != NULL);\r
241\r
242 if (Buffer == NULL) {\r
243 *SubStr = AllocateCopyPool (StrSize (String), String);\r
244 ASSERT (*SubStr != NULL);\r
82e8c138 245 return;\r
93e3992d 246 }\r
84f9a9ec
LG
247 \r
248 //\r
249 // Header + Data + '&' + '\0'\r
250 //\r
813acf3a 251 Length = StrLen (String) + BufferLen * 2 + 1 + 1;\r
63d55bb9 252 Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
93e3992d 253 ASSERT (Str != NULL);\r
254\r
255 StrCpy (Str, String);\r
256 Length = (BufferLen * 2 + 1) * sizeof (CHAR16);\r
257\r
813acf3a 258 StringHeader = Str + StrLen (String);\r
63d55bb9 259 TemString = (CHAR16 *) StringHeader;\r
813acf3a 260\r
261 switch (Flag) {\r
262 case 1:\r
63d55bb9
LG
263 //\r
264 // Convert Buffer to Hex String in reverse order\r
265 //\r
266 TemBuffer = ((UINT8 *) Buffer);\r
267 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {\r
268 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
269 }\r
813acf3a 270 break;\r
271 case 2:\r
63d55bb9
LG
272 //\r
273 // Check buffer is enough\r
274 //\r
275 TemName = (CHAR16 *) Buffer;\r
84f9a9ec 276 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));\r
63d55bb9
LG
277 //\r
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
279 //\r
280 for (; *TemName != L'\0'; TemName++) {\r
281 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
282 }\r
813acf3a 283 break;\r
284 case 3:\r
813acf3a 285 //\r
63d55bb9 286 // Convert Buffer to Hex String\r
813acf3a 287 //\r
63d55bb9
LG
288 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;\r
289 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {\r
290 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
291 }\r
813acf3a 292 break;\r
293 default:\r
294 break;\r
295 }\r
93e3992d 296\r
63d55bb9
LG
297 //\r
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
299 //\r
84f9a9ec
LG
300 StrCat (Str, L"&"); \r
301 HiiToLower (Str);\r
93e3992d 302\r
303 *SubStr = Str;\r
304}\r
305\r
306\r
307/**\r
308 Retrieve the <ConfigBody> from String then output it.\r
309\r
e90b081a 310 This is a internal function.\r
311\r
93e3992d 312 @param String A sub string of a configuration string in\r
313 <MultiConfigAltResp> format.\r
314 @param ConfigBody Points to the output string. It's caller's\r
315 responsibility to free this buffer.\r
316\r
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.\r
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.\r
319 @retval EFI_SUCCESS All existing storage is exported.\r
320\r
321**/\r
93e3992d 322EFI_STATUS\r
323OutputConfigBody (\r
324 IN EFI_STRING String,\r
325 OUT EFI_STRING *ConfigBody\r
326 )\r
327{\r
328 EFI_STRING TmpPtr;\r
329 EFI_STRING Result;\r
330 UINTN Length;\r
331\r
332 if (String == NULL || ConfigBody == NULL) {\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
84f9a9ec
LG
335 \r
336 //\r
337 // The setting information should start OFFSET, not ALTCFG.\r
338 //\r
339 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {\r
340 return EFI_INVALID_PARAMETER;\r
341 }\r
93e3992d 342\r
343 TmpPtr = StrStr (String, L"GUID=");\r
344 if (TmpPtr == NULL) {\r
345 //\r
346 // It is the last <ConfigResp> of the incoming configuration string.\r
347 //\r
348 Result = AllocateCopyPool (StrSize (String), String);\r
349 if (Result == NULL) {\r
350 return EFI_OUT_OF_RESOURCES;\r
351 } else {\r
352 *ConfigBody = Result;\r
353 return EFI_SUCCESS;\r
354 }\r
355 }\r
356\r
357 Length = TmpPtr - String;\r
358 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
359 if (Result == NULL) {\r
360 return EFI_OUT_OF_RESOURCES;\r
361 }\r
362\r
363 *(Result + Length - 1) = 0;\r
364 *ConfigBody = Result;\r
365 return EFI_SUCCESS;\r
93e3992d 366}\r
367\r
93e3992d 368/**\r
369 Append a string to a multi-string format.\r
370\r
e90b081a 371 This is a internal function.\r
372\r
93e3992d 373 @param MultiString String in <MultiConfigRequest>,\r
374 <MultiConfigAltResp>, or <MultiConfigResp>. On\r
375 input, the buffer length of this string is\r
376 MAX_STRING_LENGTH. On output, the buffer length\r
377 might be updated.\r
378 @param AppendString NULL-terminated Unicode string.\r
379\r
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString\r
382\r
383**/\r
93e3992d 384EFI_STATUS\r
385AppendToMultiString (\r
386 IN OUT EFI_STRING *MultiString,\r
387 IN EFI_STRING AppendString\r
388 )\r
389{\r
390 UINTN AppendStringSize;\r
391 UINTN MultiStringSize;\r
392\r
393 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
394 return EFI_INVALID_PARAMETER;\r
395 }\r
84f9a9ec
LG
396\r
397 AppendStringSize = StrSize (AppendString);\r
398 MultiStringSize = StrSize (*MultiString);\r
399\r
400 //\r
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
402 //\r
403 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
404 MultiStringSize > MAX_STRING_LENGTH) {\r
405 *MultiString = (EFI_STRING) ReallocatePool (\r
406 MultiStringSize,\r
407 MultiStringSize + AppendStringSize,\r
408 (VOID *) (*MultiString)\r
409 );\r
410 ASSERT (*MultiString != NULL);\r
411 }\r
412 //\r
413 // Append the incoming string\r
414 //\r
415 StrCat (*MultiString, AppendString);\r
416\r
417 return EFI_SUCCESS;\r
418}\r
419\r
420\r
421/**\r
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
423 or WIDTH or VALUE.\r
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
425\r
426 This is a internal function.\r
427\r
428 @param StringPtr String in <BlockConfig> format and points to the\r
429 first character of <Number>.\r
430 @param Number The output value. Caller takes the responsibility\r
431 to free memory.\r
432 @param Len Length of the <Number>, in characters.\r
433\r
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
435 structures.\r
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
437 successfully.\r
438\r
439**/\r
440EFI_STATUS\r
441GetValueOfNumber (\r
442 IN EFI_STRING StringPtr,\r
443 OUT UINT8 **Number,\r
444 OUT UINTN *Len\r
445 )\r
446{\r
447 EFI_STRING TmpPtr;\r
448 UINTN Length;\r
449 EFI_STRING Str;\r
450 UINT8 *Buf;\r
451 EFI_STATUS Status;\r
452 UINT8 DigitUint8;\r
453 UINTN Index;\r
454 CHAR16 TemStr[2];\r
455\r
3a530010
ED
456 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {\r
457 return EFI_INVALID_PARAMETER;\r
458 }\r
84f9a9ec
LG
459\r
460 Buf = NULL;\r
461\r
462 TmpPtr = StringPtr;\r
463 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
464 StringPtr++;\r
465 }\r
466 *Len = StringPtr - TmpPtr;\r
467 Length = *Len + 1;\r
468\r
469 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
470 if (Str == NULL) {\r
471 Status = EFI_OUT_OF_RESOURCES;\r
472 goto Exit;\r
473 }\r
474 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
475 *(Str + *Len) = L'\0';\r
476\r
477 Length = (Length + 1) / 2;\r
478 Buf = (UINT8 *) AllocateZeroPool (Length);\r
479 if (Buf == NULL) {\r
480 Status = EFI_OUT_OF_RESOURCES;\r
481 goto Exit;\r
482 }\r
483 \r
484 Length = *Len;\r
485 ZeroMem (TemStr, sizeof (TemStr));\r
486 for (Index = 0; Index < Length; Index ++) {\r
487 TemStr[0] = Str[Length - Index - 1];\r
488 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
489 if ((Index & 1) == 0) {\r
490 Buf [Index/2] = DigitUint8;\r
491 } else {\r
492 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
493 }\r
494 }\r
495\r
496 *Number = Buf;\r
497 Status = EFI_SUCCESS;\r
498\r
499Exit:\r
500 if (Str != NULL) {\r
501 FreePool (Str);\r
502 }\r
503\r
504 return Status;\r
505}\r
506\r
507/**\r
508 This function merges DefaultAltCfgResp string into AltCfgResp string for\r
509 the missing AltCfgId in AltCfgResq.\r
510\r
511 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
512 <ConfigAltResp> format. The default value string \r
513 will be merged into it. \r
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
515 <MultiConfigAltResp> format. The default value \r
516 string may contain more than one ConfigAltResp\r
517 string for the different varstore buffer.\r
518\r
519 @retval EFI_SUCCESS The merged string returns.\r
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.\r
521**/\r
522EFI_STATUS\r
523EFIAPI\r
524MergeDefaultString (\r
525 IN OUT EFI_STRING *AltCfgResp,\r
526 IN EFI_STRING DefaultAltCfgResp\r
527 )\r
528{\r
529 EFI_STRING StringPtrDefault;\r
530 EFI_STRING StringPtrEnd;\r
531 CHAR16 TempChar;\r
532 EFI_STRING StringPtr;\r
533 EFI_STRING AltConfigHdr;\r
534 UINTN HeaderLength;\r
535 UINTN SizeAltCfgResp;\r
536 \r
537 if (*AltCfgResp == NULL) {\r
538 return EFI_INVALID_PARAMETER;\r
539 }\r
540 \r
541 //\r
542 // Get the requestr ConfigHdr\r
543 //\r
544 SizeAltCfgResp = 0;\r
545 StringPtr = *AltCfgResp;\r
546 \r
547 //\r
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
549 //\r
550 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
551 return EFI_INVALID_PARAMETER;\r
552 }\r
553 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
554 StringPtr++;\r
555 }\r
556 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
557 StringPtr++;\r
558 }\r
559 if (*StringPtr == L'\0') {\r
560 return EFI_INVALID_PARAMETER;\r
561 }\r
562 StringPtr += StrLen (L"&PATH=");\r
563 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
564 StringPtr ++;\r
565 }\r
566 HeaderLength = StringPtr - *AltCfgResp;\r
567\r
568 //\r
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"\r
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |\r
571 //\r
572 AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));\r
573 if (AltConfigHdr == NULL) {\r
574 return EFI_OUT_OF_RESOURCES;\r
575 }\r
576 StrCpy (AltConfigHdr, L"&");\r
577 StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);\r
578 StrCat (AltConfigHdr, L"&ALTCFG=");\r
579 HeaderLength = StrLen (AltConfigHdr);\r
580 \r
581 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
582 while (StringPtrDefault != NULL) {\r
583 //\r
584 // Get AltCfg Name\r
585 //\r
586 StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);\r
587 StringPtr = StrStr (*AltCfgResp, AltConfigHdr); \r
588 \r
589 //\r
590 // Append the found default value string to the input AltCfgResp\r
591 // \r
592 if (StringPtr == NULL) {\r
593 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");\r
594 SizeAltCfgResp = StrSize (*AltCfgResp);\r
595 if (StringPtrEnd == NULL) {\r
596 //\r
597 // No more default string is found.\r
598 //\r
599 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
600 SizeAltCfgResp,\r
601 SizeAltCfgResp + StrSize (StringPtrDefault),\r
602 (VOID *) (*AltCfgResp)\r
603 );\r
8567300a
LG
604 if (*AltCfgResp == NULL) {\r
605 FreePool (AltConfigHdr);\r
606 return EFI_OUT_OF_RESOURCES;\r
607 }\r
84f9a9ec
LG
608 StrCat (*AltCfgResp, StringPtrDefault);\r
609 break;\r
610 } else {\r
611 TempChar = *StringPtrEnd;\r
612 *StringPtrEnd = L'\0';\r
613 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
614 SizeAltCfgResp,\r
615 SizeAltCfgResp + StrSize (StringPtrDefault),\r
616 (VOID *) (*AltCfgResp)\r
617 );\r
6e3f5b2a
LG
618 if (*AltCfgResp == NULL) {\r
619 FreePool (AltConfigHdr);\r
620 return EFI_OUT_OF_RESOURCES;\r
621 }\r
84f9a9ec
LG
622 StrCat (*AltCfgResp, StringPtrDefault);\r
623 *StringPtrEnd = TempChar;\r
624 }\r
625 }\r
626 \r
627 //\r
628 // Find next AltCfg String\r
8567300a 629 //\r
84f9a9ec 630 *(AltConfigHdr + HeaderLength) = L'\0';\r
82e8c138 631 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);\r
84f9a9ec 632 }\r
8567300a
LG
633 \r
634 FreePool (AltConfigHdr);\r
84f9a9ec
LG
635 return EFI_SUCCESS; \r
636}\r
637\r
84f9a9ec
LG
638/**\r
639 This function inserts new DefaultValueData into the BlockData DefaultValue array.\r
640\r
641 @param BlockData The BlockData is updated to add new default value.\r
642 @param DefaultValueData The DefaultValue is added.\r
643\r
644**/\r
645VOID\r
646InsertDefaultValue (\r
647 IN IFR_BLOCK_DATA *BlockData,\r
648 IN IFR_DEFAULT_DATA *DefaultValueData\r
649 )\r
650{\r
651 LIST_ENTRY *Link;\r
82e8c138
ED
652 IFR_DEFAULT_DATA *DefaultValueArray; \r
653 LIST_ENTRY *DefaultLink;\r
654 \r
655 DefaultLink = &BlockData->DefaultValueEntry;\r
84f9a9ec 656\r
82e8c138 657 for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {\r
84f9a9ec
LG
658 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
659 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {\r
ef40f0f6
ED
660 //\r
661 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.\r
662 //\r
663 if (DefaultValueData->Type > DefaultValueArray->Type) {\r
6e3f5b2a
LG
664 //\r
665 // Update the default value array in BlockData.\r
666 //\r
e7fd76d1 667 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
ef40f0f6
ED
668 DefaultValueArray->Type = DefaultValueData->Type;\r
669 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;\r
6e3f5b2a 670 }\r
84f9a9ec 671 return;\r
ef40f0f6 672 } \r
84f9a9ec
LG
673 }\r
674\r
675 //\r
676 // Insert new default value data in tail.\r
677 //\r
ef40f0f6
ED
678 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
679 ASSERT (DefaultValueArray != NULL);\r
680 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));\r
681 InsertTailList (Link, &DefaultValueArray->Entry);\r
84f9a9ec
LG
682}\r
683\r
684/**\r
685 This function inserts new BlockData into the block link\r
686\r
82e8c138
ED
687 @param BlockLink The list entry points to block array.\r
688 @param BlockData The point to BlockData is added.\r
84f9a9ec
LG
689 \r
690**/\r
691VOID\r
692InsertBlockData (\r
693 IN LIST_ENTRY *BlockLink,\r
694 IN IFR_BLOCK_DATA **BlockData\r
695 )\r
696{\r
82e8c138
ED
697 LIST_ENTRY *Link;\r
698 IFR_BLOCK_DATA *BlockArray;\r
699 IFR_BLOCK_DATA *BlockSingleData;\r
84f9a9ec
LG
700\r
701 BlockSingleData = *BlockData;\r
82e8c138
ED
702\r
703 if (BlockSingleData->Name != NULL) {\r
704 InsertTailList (BlockLink, &BlockSingleData->Entry);\r
705 return;\r
706 }\r
707\r
84f9a9ec
LG
708 //\r
709 // Insert block data in its Offset and Width order.\r
710 //\r
711 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
712 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
713 if (BlockArray->Offset == BlockSingleData->Offset) {\r
714 if (BlockArray->Width > BlockSingleData->Width) {\r
715 //\r
716 // Insert this block data in the front of block array\r
717 //\r
718 InsertTailList (Link, &BlockSingleData->Entry);\r
719 return;\r
720 }\r
721\r
722 if (BlockArray->Width == BlockSingleData->Width) {\r
723 //\r
724 // The same block array has been added.\r
725 //\r
82e8c138
ED
726 if (BlockSingleData != BlockArray) {\r
727 FreePool (BlockSingleData);\r
728 *BlockData = BlockArray;\r
729 }\r
84f9a9ec
LG
730 return;\r
731 }\r
732 } else if (BlockArray->Offset > BlockSingleData->Offset) {\r
733 //\r
734 // Insert new block data in the front of block array \r
735 //\r
736 InsertTailList (Link, &BlockSingleData->Entry);\r
737 return;\r
738 }\r
739 }\r
740 \r
741 //\r
742 // Add new block data into the tail.\r
743 //\r
82e8c138
ED
744 InsertTailList (Link, &BlockSingleData->Entry); \r
745}\r
746\r
747/**\r
748 Retrieves a pointer to the a Null-terminated ASCII string containing the list \r
749 of languages that an HII handle in the HII Database supports. The returned \r
750 string is allocated using AllocatePool(). The caller is responsible for freeing\r
751 the returned string using FreePool(). The format of the returned string follows\r
752 the language format assumed the HII Database.\r
753 \r
754 If HiiHandle is NULL, then ASSERT().\r
755\r
756 @param[in] HiiHandle A handle that was previously registered in the HII Database.\r
757\r
758 @retval NULL HiiHandle is not registered in the HII database\r
759 @retval NULL There are not enough resources available to retrieve the suported \r
760 languages.\r
761 @retval NULL The list of suported languages could not be retrieved.\r
762 @retval Other A pointer to the Null-terminated ASCII string of supported languages.\r
763\r
764**/\r
765CHAR8 *\r
766GetSupportedLanguages (\r
767 IN EFI_HII_HANDLE HiiHandle\r
768 )\r
769{\r
770 EFI_STATUS Status;\r
771 UINTN LanguageSize;\r
772 CHAR8 TempSupportedLanguages;\r
773 CHAR8 *SupportedLanguages;\r
774\r
775 ASSERT (HiiHandle != NULL);\r
776\r
777 //\r
778 // Retrieve the size required for the supported languages buffer.\r
779 //\r
780 LanguageSize = 0;\r
781 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);\r
782\r
783 //\r
784 // If GetLanguages() returns EFI_SUCCESS for a zero size, \r
785 // then there are no supported languages registered for HiiHandle. If GetLanguages() \r
786 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present\r
787 // in the HII Database\r
788 //\r
789 if (Status != EFI_BUFFER_TOO_SMALL) {\r
790 //\r
791 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database\r
792 //\r
793 return NULL;\r
794 }\r
795\r
796 //\r
797 // Allocate the supported languages buffer.\r
798 //\r
799 SupportedLanguages = AllocateZeroPool (LanguageSize);\r
800 if (SupportedLanguages == NULL) {\r
801 //\r
802 // Return NULL if allocation fails.\r
803 //\r
804 return NULL;\r
805 }\r
806\r
807 //\r
808 // Retrieve the supported languages string\r
809 //\r
810 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);\r
811 if (EFI_ERROR (Status)) {\r
812 //\r
813 // Free the buffer and return NULL if the supported languages can not be retrieved.\r
814 //\r
815 FreePool (SupportedLanguages);\r
816 return NULL;\r
817 }\r
818\r
819 //\r
820 // Return the Null-terminated ASCII string of supported languages\r
821 //\r
822 return SupportedLanguages;\r
823}\r
824\r
825/**\r
826 Retrieves a string from a string package.\r
827 \r
828 If HiiHandle is NULL, then ASSERT().\r
829 If StringId is 0, then ASSET.\r
830\r
831 @param[in] HiiHandle A handle that was previously registered in the HII Database.\r
832 @param[in] StringId The identifier of the string to retrieved from the string \r
833 package associated with HiiHandle.\r
834\r
835 @retval NULL The string specified by StringId is not present in the string package.\r
836 @retval Other The string was returned.\r
837\r
838**/\r
839EFI_STRING\r
840InternalGetString (\r
841 IN EFI_HII_HANDLE HiiHandle,\r
842 IN EFI_STRING_ID StringId\r
843 )\r
844{\r
845 EFI_STATUS Status;\r
846 UINTN StringSize;\r
847 CHAR16 TempString;\r
848 EFI_STRING String;\r
849 CHAR8 *SupportedLanguages;\r
850 CHAR8 *PlatformLanguage;\r
851 CHAR8 *BestLanguage;\r
852 CHAR8 *Language;\r
853\r
854 ASSERT (HiiHandle != NULL);\r
855 ASSERT (StringId != 0);\r
856\r
857 //\r
858 // Initialize all allocated buffers to NULL\r
859 // \r
860 SupportedLanguages = NULL;\r
861 PlatformLanguage = NULL;\r
862 BestLanguage = NULL;\r
863 String = NULL;\r
864 Language = "";\r
865\r
866 //\r
867 // Get the languages that the package specified by HiiHandle supports\r
868 //\r
869 SupportedLanguages = GetSupportedLanguages (HiiHandle);\r
870 if (SupportedLanguages == NULL) {\r
871 goto Error;\r
872 }\r
873\r
874 //\r
875 // Get the current platform language setting\r
876 //\r
877 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);\r
878\r
879 //\r
880 // Get the best matching language from SupportedLanguages\r
881 //\r
882 BestLanguage = GetBestLanguage (\r
883 SupportedLanguages, \r
884 FALSE, // RFC 4646 mode\r
885 Language, // Highest priority \r
886 PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority\r
887 SupportedLanguages, // Lowest priority \r
888 NULL\r
889 );\r
890 if (BestLanguage == NULL) {\r
891 goto Error;\r
892 }\r
893\r
894 //\r
895 // Retrieve the size of the string in the string package for the BestLanguage\r
896 //\r
897 StringSize = 0;\r
898 Status = mPrivate.HiiString.GetString (\r
899 &mPrivate.HiiString,\r
900 BestLanguage,\r
901 HiiHandle,\r
902 StringId,\r
903 &TempString,\r
904 &StringSize,\r
905 NULL\r
906 );\r
907 //\r
908 // If GetString() returns EFI_SUCCESS for a zero size, \r
909 // then there are no supported languages registered for HiiHandle. If GetString() \r
910 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present\r
911 // in the HII Database\r
912 //\r
913 if (Status != EFI_BUFFER_TOO_SMALL) {\r
914 goto Error;\r
915 }\r
916\r
917 //\r
918 // Allocate a buffer for the return string\r
919 //\r
920 String = AllocateZeroPool (StringSize);\r
921 if (String == NULL) {\r
922 goto Error;\r
923 }\r
924\r
925 //\r
926 // Retrieve the string from the string package\r
927 //\r
928 Status = mPrivate.HiiString.GetString (\r
929 &mPrivate.HiiString,\r
930 BestLanguage,\r
931 HiiHandle,\r
932 StringId,\r
933 String,\r
934 &StringSize,\r
935 NULL\r
936 );\r
937 if (EFI_ERROR (Status)) {\r
938 //\r
939 // Free the buffer and return NULL if the supported languages can not be retrieved.\r
940 //\r
941 FreePool (String);\r
942 String = NULL;\r
943 }\r
944\r
945Error:\r
946 //\r
947 // Free allocated buffers\r
948 //\r
949 if (SupportedLanguages != NULL) {\r
950 FreePool (SupportedLanguages);\r
951 }\r
952 if (PlatformLanguage != NULL) {\r
953 FreePool (PlatformLanguage);\r
954 }\r
955 if (BestLanguage != NULL) {\r
956 FreePool (BestLanguage);\r
957 }\r
958\r
959 //\r
960 // Return the Null-terminated Unicode string\r
961 //\r
962 return String;\r
84f9a9ec
LG
963}\r
964\r
965/**\r
966 This function checks VarOffset and VarWidth is in the block range.\r
967\r
aa75dfec 968 @param RequestBlockArray The block array is to be checked. \r
84f9a9ec
LG
969 @param VarOffset Offset of var to the structure\r
970 @param VarWidth Width of var.\r
82e8c138
ED
971 @param IsNameValueType Whether this varstore is name/value varstore or not.\r
972 @param HiiHandle Hii handle for this hii package.\r
84f9a9ec
LG
973 \r
974 @retval TRUE This Var is in the block range.\r
975 @retval FALSE This Var is not in the block range.\r
976**/\r
977BOOLEAN\r
978BlockArrayCheck (\r
979 IN IFR_BLOCK_DATA *RequestBlockArray,\r
980 IN UINT16 VarOffset,\r
82e8c138
ED
981 IN UINT16 VarWidth,\r
982 IN BOOLEAN IsNameValueType,\r
983 IN EFI_HII_HANDLE HiiHandle\r
84f9a9ec
LG
984 )\r
985{\r
986 LIST_ENTRY *Link;\r
987 IFR_BLOCK_DATA *BlockData;\r
82e8c138
ED
988 EFI_STRING Name;\r
989\r
84f9a9ec
LG
990 //\r
991 // No Request Block array, all vars are got.\r
992 //\r
993 if (RequestBlockArray == NULL) {\r
994 return TRUE;\r
995 }\r
82e8c138 996\r
84f9a9ec
LG
997 //\r
998 // Check the input var is in the request block range.\r
999 //\r
1000 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {\r
1001 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
82e8c138
ED
1002\r
1003 if (IsNameValueType) {\r
1004 Name = InternalGetString (HiiHandle, VarOffset);\r
1005 ASSERT (Name != NULL);\r
1006\r
1007 if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {\r
1008 FreePool (Name);\r
1009 return TRUE;\r
1010 }\r
1011 FreePool (Name);\r
1012 } else {\r
1013 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
1014 return TRUE;\r
1015 }\r
84f9a9ec
LG
1016 }\r
1017 }\r
1018\r
1019 return FALSE;\r
1020}\r
1021\r
cce6230f
ED
1022/**\r
1023 Get form package data from data base.\r
1024\r
1025 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
1026 @param HiiFormPackage The buffer saves the package data.\r
1027 @param PackageSize The buffer size of the package data.\r
1028\r
1029**/\r
1030EFI_STATUS\r
1031GetFormPackageData (\r
1032 IN HII_DATABASE_RECORD *DataBaseRecord,\r
1033 IN OUT UINT8 **HiiFormPackage,\r
1034 OUT UINTN *PackageSize\r
1035 )\r
1036{\r
1037 EFI_STATUS Status;\r
1038 UINTN Size;\r
1039 UINTN ResultSize;\r
1040\r
1041 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {\r
1042 return EFI_INVALID_PARAMETER;\r
1043 }\r
1044\r
1045 Size = 0;\r
1046 ResultSize = 0;\r
1047 //\r
1048 // 0. Get Hii Form Package by HiiHandle\r
1049 //\r
1050 Status = ExportFormPackages (\r
1051 &mPrivate, \r
1052 DataBaseRecord->Handle, \r
1053 DataBaseRecord->PackageList, \r
1054 0, \r
1055 Size, \r
1056 HiiFormPackage,\r
1057 &ResultSize\r
1058 );\r
1059 if (EFI_ERROR (Status)) {\r
1060 return Status;\r
1061 }\r
1062 \r
1063 (*HiiFormPackage) = AllocatePool (ResultSize);\r
1064 if (*HiiFormPackage == NULL) {\r
1065 Status = EFI_OUT_OF_RESOURCES;\r
1066 return Status;\r
1067 }\r
1068\r
1069 //\r
1070 // Get HiiFormPackage by HiiHandle\r
1071 //\r
1072 Size = ResultSize;\r
1073 ResultSize = 0;\r
1074 Status = ExportFormPackages (\r
1075 &mPrivate, \r
1076 DataBaseRecord->Handle, \r
1077 DataBaseRecord->PackageList, \r
1078 0,\r
1079 Size, \r
1080 *HiiFormPackage,\r
1081 &ResultSize\r
1082 );\r
1083 if (EFI_ERROR (Status)) {\r
1084 FreePool (*HiiFormPackage);\r
1085 }\r
1086 \r
1087 *PackageSize = Size;\r
1088\r
1089 return Status;\r
1090}\r
1091\r
1092\r
1093/**\r
1094 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.\r
1095\r
1096 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
1097 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
1098 the first found varstore will be as ConfigHdr.\r
1099 @param IsEfiVarstore Whether the request storage type is efi varstore type.\r
1100 @param EfiVarStore The efi varstore info which will return.\r
1101**/ \r
1102EFI_STATUS\r
1103GetVarStoreType (\r
1104 IN HII_DATABASE_RECORD *DataBaseRecord,\r
1105 IN EFI_STRING ConfigHdr,\r
1106 OUT BOOLEAN *IsEfiVarstore,\r
1107 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore\r
cce6230f
ED
1108 )\r
1109{\r
1110 EFI_STATUS Status;\r
1111 UINTN IfrOffset;\r
1112 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1113 CHAR16 *VarStoreName;\r
1114 EFI_STRING GuidStr;\r
1115 EFI_STRING NameStr;\r
1116 EFI_STRING TempStr;\r
1117 UINTN LengthString; \r
1118 UINT8 *HiiFormPackage;\r
1119 UINTN PackageSize;\r
1120 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
1121 \r
1122 HiiFormPackage = NULL;\r
1123 LengthString = 0;\r
1124 Status = EFI_SUCCESS;\r
1125 GuidStr = NULL;\r
1126 NameStr = NULL;\r
1127 TempStr = NULL;\r
1128\r
1129 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);\r
1130 if (EFI_ERROR (Status)) {\r
1131 return Status;\r
1132 }\r
1133\r
1134 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1135 while (IfrOffset < PackageSize) {\r
1136 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset); \r
1137 IfrOffset += IfrOpHdr->Length;\r
1138\r
1139 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {\r
1140 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1141 //\r
1142 // If the length is small than the structure, this is from old efi \r
1143 // varstore definition. Old efi varstore get config directly from \r
1144 // GetVariable function.\r
1145 //\r
1146 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
1147 continue;\r
1148 }\r
1149\r
1150 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
1151 if (VarStoreName == NULL) {\r
1152 Status = EFI_OUT_OF_RESOURCES;\r
1153 goto Done;\r
1154 }\r
1155 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);\r
1156\r
1157 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);\r
1158 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
1159 LengthString = StrLen (GuidStr);\r
1160 LengthString = LengthString + StrLen (NameStr) + 1;\r
1161 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
1162 if (TempStr == NULL) {\r
1163 FreePool (GuidStr);\r
1164 FreePool (NameStr);\r
1165 FreePool (VarStoreName);\r
1166 Status = EFI_OUT_OF_RESOURCES;\r
1167 goto Done;\r
1168 }\r
1169 StrCpy (TempStr, GuidStr);\r
1170 StrCat (TempStr, NameStr);\r
1171 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
1172 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);\r
1173 if (*EfiVarStore == NULL) {\r
1174 FreePool (VarStoreName);\r
1175 FreePool (GuidStr);\r
1176 FreePool (NameStr);\r
1177 FreePool (TempStr);\r
1178 Status = EFI_OUT_OF_RESOURCES;\r
1179 goto Done;\r
1180 }\r
1181 *IsEfiVarstore = TRUE;\r
1182 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);\r
1183 } \r
1184 \r
1185 //\r
1186 // Free alllocated temp string.\r
1187 //\r
1188 FreePool (VarStoreName);\r
1189 FreePool (GuidStr);\r
1190 FreePool (NameStr);\r
1191 FreePool (TempStr);\r
1192 }\r
1193 }\r
1194Done:\r
1195 if (HiiFormPackage != NULL) {\r
1196 FreePool (HiiFormPackage);\r
1197 }\r
1198\r
1199 return Status;\r
1200}\r
1201\r
82e8c138
ED
1202/**\r
1203 Check whether the ConfigRequest string has the request elements.\r
1204 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.\r
1205 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.\r
1206\r
1207 @param ConfigRequest The input config request string.\r
1208\r
1209 @retval TRUE The input include config request elements.\r
1210 @retval FALSE The input string not includes.\r
1211\r
1212**/\r
1213BOOLEAN\r
1214GetElementsFromRequest (\r
1215 IN EFI_STRING ConfigRequest\r
1216 )\r
1217{\r
1218 EFI_STRING TmpRequest;\r
1219\r
1220 TmpRequest = StrStr (ConfigRequest, L"PATH=");\r
1221 ASSERT (TmpRequest != NULL);\r
1222\r
1223 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {\r
1224 return TRUE;\r
1225 }\r
1226\r
1227 return FALSE;\r
1228}\r
1229\r
1230/**\r
1231 Check whether the this varstore is the request varstore.\r
1232\r
1233 @param VarstoreGuid Varstore guid.\r
1234 @param Name Varstore name.\r
1235 @param ConfigHdr Current configRequest info.\r
1236\r
1237 @retval TRUE This varstore is the requst one.\r
1238 @retval FALSE This varstore is not the requst one.\r
1239 \r
1240**/\r
1241BOOLEAN\r
1242IsThisVarstore (\r
1243 IN EFI_GUID *VarstoreGuid,\r
1244 IN CHAR16 *Name,\r
1245 IN CHAR16 *ConfigHdr\r
1246 )\r
1247{\r
1248 EFI_STRING GuidStr;\r
1249 EFI_STRING NameStr;\r
1250 EFI_STRING TempStr;\r
1251 UINTN LengthString;\r
1252 BOOLEAN RetVal;\r
1253\r
1254 RetVal = FALSE;\r
1255 GuidStr = NULL;\r
1256 TempStr = NULL;\r
1257\r
1258 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);\r
1259 if (Name != NULL) {\r
1260 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);\r
1261 } else {\r
1262 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
1263 }\r
1264 LengthString = StrLen (GuidStr);\r
1265 LengthString = LengthString + StrLen (NameStr) + 1;\r
1266 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
1267 if (TempStr == NULL) {\r
1268 goto Done;\r
1269 }\r
1270\r
1271 StrCpy (TempStr, GuidStr);\r
1272 StrCat (TempStr, NameStr);\r
1273\r
1274 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
1275 RetVal = TRUE;\r
1276 }\r
1277\r
1278Done:\r
1279 if (GuidStr != NULL) {\r
1280 FreePool (GuidStr); \r
1281 }\r
1282\r
1283 if (NameStr != NULL) {\r
1284 FreePool (NameStr);\r
1285 }\r
1286\r
1287 if (TempStr != NULL) {\r
1288 FreePool (TempStr);\r
1289 }\r
1290\r
1291 return RetVal;\r
1292}\r
1293\r
1294/**\r
1295 Check whether the this op code is required.\r
1296\r
1297 @param RequestBlockArray The array includes all the request info or NULL.\r
1298 @param HiiHandle The hii handle for this form package.\r
1299 @param VarStorageData The varstore data strucure.\r
1300 @param IfrOpHdr Ifr opcode header for this opcode.\r
1301 @param VarWidth The buffer width for this opcode.\r
1302 @param ReturnData The data block added for this opcode.\r
1303\r
1304 @retval EFI_SUCCESS This opcode is required.\r
1305 @retval Others This opcode is not required or error occur.\r
1306 \r
1307**/\r
1308EFI_STATUS\r
1309IsThisOpcodeRequired (\r
1310 IN IFR_BLOCK_DATA *RequestBlockArray,\r
1311 IN EFI_HII_HANDLE HiiHandle,\r
1312 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
1313 IN EFI_IFR_OP_HEADER *IfrOpHdr,\r
1314 IN UINT16 VarWidth,\r
1315 OUT IFR_BLOCK_DATA **ReturnData\r
1316 )\r
1317{\r
1318 IFR_BLOCK_DATA *BlockData;\r
1319 UINT16 VarOffset;\r
1320 EFI_STRING_ID NameId;\r
1321 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;\r
1322\r
1323 NameId = 0;\r
1324 VarOffset = 0;\r
1325 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));\r
1326\r
1327 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
1328 NameId = IfrQuestionHdr->VarStoreInfo.VarName;\r
1329\r
1330 //\r
1331 // Check whether this question is in requested block array.\r
1332 //\r
1333 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {\r
1334 //\r
1335 // This question is not in the requested string. Skip it.\r
1336 //\r
1337 return EFI_SUCCESS;\r
1338 }\r
1339 } else {\r
1340 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
1341 \r
1342 //\r
1343 // Check whether this question is in requested block array.\r
1344 //\r
1345 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {\r
1346 //\r
1347 // This question is not in the requested string. Skip it.\r
1348 //\r
1349 return EFI_SUCCESS;\r
1350 }\r
1351\r
1352 //\r
1353 // Check this var question is in the var storage \r
1354 //\r
1355 if (((VarOffset + VarWidth) > VarStorageData->Size)) {\r
1356 return EFI_INVALID_PARAMETER;\r
1357 }\r
1358 }\r
1359\r
1360 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1361 if (BlockData == NULL) {\r
1362 return EFI_OUT_OF_RESOURCES;\r
1363 }\r
1364\r
1365 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
1366 BlockData->Name = InternalGetString(HiiHandle, NameId);\r
1367 } else {\r
1368 BlockData->Offset = VarOffset;\r
1369 }\r
1370\r
1371 BlockData->Width = VarWidth;\r
1372 BlockData->QuestionId = IfrQuestionHdr->QuestionId;\r
1373 BlockData->OpCode = IfrOpHdr->OpCode;\r
1374 BlockData->Scope = IfrOpHdr->Scope;\r
1375 InitializeListHead (&BlockData->DefaultValueEntry);\r
1376 //\r
1377 // Add Block Data into VarStorageData BlockEntry\r
1378 //\r
1379 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1380 *ReturnData = BlockData;\r
1381\r
1382 return EFI_SUCCESS;\r
1383}\r
1384\r
84f9a9ec
LG
1385/**\r
1386 This function parses Form Package to get the block array and the default\r
1387 value array according to the request ConfigHdr.\r
1388\r
82e8c138 1389 @param HiiHandle Hii Handle for this hii package.\r
84f9a9ec
LG
1390 @param Package Pointer to the form package data.\r
1391 @param PackageLength Length of the pacakge.\r
1392 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
1393 the first found varstore will be as ConfigHdr.\r
1394 @param RequestBlockArray The block array is retrieved from the request string.\r
1395 @param VarStorageData VarStorage structure contains the got block and default value.\r
82e8c138 1396 @param DefaultIdArray Point to the got default id and default name array.\r
84f9a9ec
LG
1397\r
1398 @retval EFI_SUCCESS The block array and the default value array are got.\r
1399 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges\r
1400 are conflicted. \r
1401 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
1402**/\r
1403EFI_STATUS\r
1404EFIAPI\r
1405ParseIfrData (\r
82e8c138 1406 IN EFI_HII_HANDLE HiiHandle,\r
84f9a9ec 1407 IN UINT8 *Package,\r
aa75dfec 1408 IN UINT32 PackageLength,\r
84f9a9ec
LG
1409 IN EFI_STRING ConfigHdr,\r
1410 IN IFR_BLOCK_DATA *RequestBlockArray,\r
1411 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
8567300a 1412 OUT IFR_DEFAULT_DATA *DefaultIdArray\r
84f9a9ec
LG
1413 )\r
1414{\r
1415 EFI_STATUS Status;\r
1416 UINTN IfrOffset;\r
1417 EFI_IFR_VARSTORE *IfrVarStore;\r
cce6230f 1418 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
84f9a9ec
LG
1419 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1420 EFI_IFR_ONE_OF *IfrOneOf;\r
e7fd76d1 1421 EFI_IFR_REF4 *IfrRef;\r
84f9a9ec
LG
1422 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
1423 EFI_IFR_DEFAULT *IfrDefault;\r
1424 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
1425 EFI_IFR_CHECKBOX *IfrCheckBox;\r
1426 EFI_IFR_PASSWORD *IfrPassword;\r
1427 EFI_IFR_STRING *IfrString;\r
d9bbabfd
ED
1428 EFI_IFR_DATE *IfrDate;\r
1429 EFI_IFR_TIME *IfrTime;\r
ef40f0f6
ED
1430 IFR_DEFAULT_DATA DefaultData;\r
1431 IFR_DEFAULT_DATA *DefaultDataPtr;\r
84f9a9ec 1432 IFR_BLOCK_DATA *BlockData;\r
270e8dfd
OM
1433 CHAR16 *VarStoreName;
1434 UINT16 VarWidth;
1435 UINT16 VarDefaultId;
1436 BOOLEAN FirstOneOfOption;
1437 LIST_ENTRY *LinkData;
1438 LIST_ENTRY *LinkDefault;
1439 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1440
1441 Status = EFI_SUCCESS;
1442 BlockData = NULL;
1443 DefaultDataPtr = NULL;
1444 FirstOneOfOption = FALSE;
ef40f0f6 1445 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
84f9a9ec
LG
1446\r
1447 //\r
1448 // Go through the form package to parse OpCode one by one.\r
1449 //\r
1450 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
aa75dfec 1451 while (IfrOffset < PackageLength) {\r
84f9a9ec 1452 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
84f9a9ec
LG
1453 switch (IfrOpHdr->OpCode) {\r
1454 case EFI_IFR_VARSTORE_OP:\r
1455 //\r
1456 // VarStore is found. Don't need to search any more.\r
1457 //\r
82e8c138 1458 if (VarStorageData->VarStoreId != 0) {\r
84f9a9ec
LG
1459 break;\r
1460 }\r
1461\r
84f9a9ec 1462 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
82e8c138 1463\r
f8920f0d 1464 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
84f9a9ec
LG
1465 if (VarStoreName == NULL) {\r
1466 Status = EFI_OUT_OF_RESOURCES;\r
1467 goto Done;\r
1468 }\r
f8920f0d 1469 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);\r
84f9a9ec 1470\r
82e8c138 1471 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
84f9a9ec
LG
1472 //\r
1473 // Find the matched VarStore\r
1474 //\r
1475 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
1476 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
1477 VarStorageData->Size = IfrVarStore->Size;\r
1478 VarStorageData->Name = VarStoreName;\r
82e8c138 1479 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;\r
84f9a9ec 1480 }\r
84f9a9ec
LG
1481 break;\r
1482\r
cce6230f
ED
1483 case EFI_IFR_VARSTORE_EFI_OP:\r
1484 //\r
1485 // VarStore is found. Don't need to search any more.\r
1486 //\r
82e8c138 1487 if (VarStorageData->VarStoreId != 0) {\r
cce6230f
ED
1488 break;\r
1489 }\r
1490\r
cce6230f
ED
1491 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1492\r
1493 //\r
1494 // If the length is small than the structure, this is from old efi \r
1495 // varstore definition. Old efi varstore get config directly from \r
1496 // GetVariable function.\r
1497 // \r
1498 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
1499 break;\r
1500 }\r
1501\r
f8920f0d 1502 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
cce6230f
ED
1503 if (VarStoreName == NULL) {\r
1504 Status = EFI_OUT_OF_RESOURCES;\r
1505 goto Done;\r
1506 }\r
f8920f0d 1507 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);\r
cce6230f 1508\r
82e8c138 1509 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
cce6230f
ED
1510 //\r
1511 // Find the matched VarStore\r
1512 //\r
1513 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);\r
1514 VarStorageData->VarStoreId = IfrEfiVarStore->VarStoreId;\r
1515 VarStorageData->Size = IfrEfiVarStore->Size;\r
1516 VarStorageData->Name = VarStoreName;\r
82e8c138 1517 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;\r
cce6230f 1518 }\r
cce6230f
ED
1519 break;\r
1520\r
82e8c138 1521 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
84f9a9ec 1522 //\r
82e8c138
ED
1523 // VarStore is found. Don't need to search any more.\r
1524 //\r
1525 if (VarStorageData->VarStoreId != 0) {\r
1526 break;\r
1527 }\r
1528\r
1529 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
1530\r
1531 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
1532 //\r
1533 // Find the matched VarStore\r
1534 //\r
1535 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);\r
1536 VarStorageData->VarStoreId = IfrNameValueVarStore->VarStoreId;\r
1537 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
1538 }\r
1539 break;\r
1540\r
1541 case EFI_IFR_DEFAULTSTORE_OP:\r
1542 //\r
1543 // Add new the map between default id and default name.\r
84f9a9ec 1544 //\r
ef40f0f6
ED
1545 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1546 if (DefaultDataPtr == NULL) {\r
84f9a9ec
LG
1547 Status = EFI_OUT_OF_RESOURCES;\r
1548 goto Done;\r
1549 }\r
ef40f0f6
ED
1550 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
1551 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
1552 DefaultDataPtr = NULL;\r
84f9a9ec
LG
1553 break;\r
1554\r
1555 case EFI_IFR_FORM_OP:\r
2573712e 1556 case EFI_IFR_FORM_MAP_OP:\r
84f9a9ec
LG
1557 //\r
1558 // No matched varstore is found and directly return.\r
1559 //\r
82e8c138 1560 if (VarStorageData->VarStoreId == 0) {\r
84f9a9ec
LG
1561 Status = EFI_SUCCESS;\r
1562 goto Done;\r
1563 }\r
1564 break;\r
1565\r
e7fd76d1
ED
1566 case EFI_IFR_REF_OP:\r
1567 //\r
1568 // Ref question is not in IFR Form. This IFR form is not valid. \r
1569 //\r
82e8c138 1570 if (VarStorageData->VarStoreId == 0) {\r
e7fd76d1
ED
1571 Status = EFI_INVALID_PARAMETER;\r
1572 goto Done;\r
1573 }\r
1574 //\r
1575 // Check whether this question is for the requested varstore.\r
1576 //\r
1577 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;\r
1578 if (IfrRef->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1579 break;\r
1580 }\r
e7fd76d1 1581 VarWidth = (UINT16) (sizeof (EFI_HII_REF));\r
e7fd76d1 1582\r
82e8c138
ED
1583 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1584 if (EFI_ERROR (Status)) {\r
e7fd76d1
ED
1585 goto Done;\r
1586 }\r
e7fd76d1
ED
1587 break;\r
1588\r
84f9a9ec
LG
1589 case EFI_IFR_ONE_OF_OP:\r
1590 case EFI_IFR_NUMERIC_OP:\r
1591 //\r
1592 // Numeric and OneOf has the same opcode structure.\r
1593 //\r
1594\r
8567300a
LG
1595 //\r
1596 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
1597 //\r
82e8c138 1598 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1599 Status = EFI_INVALID_PARAMETER;\r
1600 goto Done;\r
1601 }\r
84f9a9ec
LG
1602 //\r
1603 // Check whether this question is for the requested varstore.\r
1604 //\r
1605 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
1606 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1607 break;\r
1608 }\r
84f9a9ec 1609 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
84f9a9ec 1610\r
82e8c138
ED
1611 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1612 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1613 goto Done;\r
1614 }\r
82e8c138 1615\r
84f9a9ec 1616 if (BlockData == NULL) {\r
82e8c138
ED
1617 //\r
1618 // BlockData == NULL means this opcode is not in the requst array.\r
1619 //\r
1620 break;\r
84f9a9ec 1621 }\r
82e8c138 1622\r
cf4c5a42
LG
1623 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
1624 //\r
1625 // Set this flag to TRUE for the first oneof option.\r
1626 //\r
1627 FirstOneOfOption = TRUE;\r
1628 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
1629 //\r
1630 // Numeric minimum value will be used as default value when no default is specified. \r
1631 //\r
eb5e7d3e 1632 DefaultData.Type = DefaultValueFromDefault;\r
cf4c5a42
LG
1633 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1634 case EFI_IFR_NUMERIC_SIZE_1:\r
e7fd76d1 1635 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
cf4c5a42 1636 break;\r
82e8c138 1637\r
cf4c5a42 1638 case EFI_IFR_NUMERIC_SIZE_2:\r
e7fd76d1 1639 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
cf4c5a42 1640 break;\r
82e8c138 1641\r
cf4c5a42 1642 case EFI_IFR_NUMERIC_SIZE_4:\r
e7fd76d1 1643 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
cf4c5a42 1644 break;\r
82e8c138 1645\r
cf4c5a42 1646 case EFI_IFR_NUMERIC_SIZE_8:\r
e7fd76d1 1647 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
cf4c5a42 1648 break;\r
82e8c138
ED
1649\r
1650 default:\r
1651 Status = EFI_INVALID_PARAMETER;\r
1652 goto Done;\r
cf4c5a42
LG
1653 }\r
1654 //\r
ef40f0f6
ED
1655 // Set default value base on the DefaultId list get from IFR data.\r
1656 // \r
1657 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
82e8c138 1658 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
ef40f0f6
ED
1659 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
1660 InsertDefaultValue (BlockData, &DefaultData);\r
1661 }\r
cf4c5a42 1662 }\r
84f9a9ec
LG
1663 break;\r
1664\r
1665 case EFI_IFR_ORDERED_LIST_OP:\r
1666 //\r
1667 // offset by question header\r
1668 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
1669 // no default value and default id, how to define its default value?\r
1670 //\r
8567300a
LG
1671\r
1672 //\r
1673 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
1674 //\r
82e8c138 1675 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1676 Status = EFI_INVALID_PARAMETER;\r
1677 goto Done;\r
1678 }\r
84f9a9ec
LG
1679 //\r
1680 // Check whether this question is for the requested varstore.\r
1681 //\r
1682 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
1683 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
ff28420b 1684 BlockData = NULL;\r
84f9a9ec
LG
1685 break;\r
1686 }\r
84f9a9ec 1687 VarWidth = IfrOrderedList->MaxContainers;\r
82e8c138
ED
1688 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1689 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1690 goto Done;\r
1691 }\r
84f9a9ec
LG
1692 break;\r
1693\r
1694 case EFI_IFR_CHECKBOX_OP:\r
1695 //\r
1696 // EFI_IFR_DEFAULT_OP\r
1697 // offset by question header\r
1698 // width is 1 sizeof (BOOLEAN)\r
1699 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1700 // value by DefaultOption\r
1701 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1702 // \r
1703\r
8567300a
LG
1704 //\r
1705 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1706 //\r
82e8c138 1707 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1708 Status = EFI_INVALID_PARAMETER;\r
1709 goto Done;\r
1710 }\r
84f9a9ec
LG
1711 //\r
1712 // Check whether this question is for the requested varstore.\r
1713 //\r
1714 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1715 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1716 break;\r
1717 }\r
c9325700 1718 VarWidth = (UINT16) sizeof (BOOLEAN);\r
82e8c138
ED
1719 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1720 if (EFI_ERROR (Status)) {\r
1721 goto Done;\r
1722 }\r
84f9a9ec 1723\r
82e8c138 1724 if (BlockData == NULL) {\r
84f9a9ec 1725 //\r
82e8c138 1726 // BlockData == NULL means this opcode is not in the requst array.\r
84f9a9ec
LG
1727 //\r
1728 break;\r
1729 }\r
1730\r
84f9a9ec 1731 //\r
e9668a60 1732 // Add default value for standard ID by CheckBox Flag\r
84f9a9ec 1733 //\r
e9668a60
LG
1734 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1735 //\r
1736 // Prepare new DefaultValue\r
1737 //\r
ef40f0f6 1738 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1739 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1740 //\r
e9668a60 1741 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1742 //\r
e7fd76d1
ED
1743 DefaultData.Type = DefaultValueFromFlag;\r
1744 DefaultData.Value.b = TRUE;\r
e9668a60 1745 } else {\r
84f9a9ec 1746 //\r
e9668a60 1747 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1748 //\r
e7fd76d1
ED
1749 DefaultData.Type = DefaultValueFromDefault;\r
1750 DefaultData.Value.b = FALSE;\r
84f9a9ec 1751 }\r
e9668a60
LG
1752 //\r
1753 // Add DefaultValue into current BlockData\r
1754 //\r
ef40f0f6 1755 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 1756\r
e9668a60
LG
1757 //\r
1758 // Add default value for Manufacture ID by CheckBox Flag\r
1759 //\r
1760 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1761 //\r
1762 // Prepare new DefaultValue\r
1763 //\r
ef40f0f6 1764 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1765 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1766 //\r
e9668a60 1767 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1768 //\r
e7fd76d1
ED
1769 DefaultData.Type = DefaultValueFromFlag;\r
1770 DefaultData.Value.b = TRUE;\r
e9668a60 1771 } else {\r
84f9a9ec 1772 //\r
e9668a60 1773 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1774 //\r
82e8c138 1775 DefaultData.Type = DefaultValueFromDefault;\r
e7fd76d1 1776 DefaultData.Value.b = FALSE;\r
84f9a9ec 1777 }\r
e9668a60
LG
1778 //\r
1779 // Add DefaultValue into current BlockData\r
1780 //\r
ef40f0f6 1781 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec
LG
1782 break;\r
1783\r
d9bbabfd
ED
1784 case EFI_IFR_DATE_OP:\r
1785 //\r
1786 // offset by question header\r
1787 // width MaxSize * sizeof (CHAR16)\r
1788 // no default value, only block array\r
1789 //\r
1790\r
1791 //\r
1792 // Date question is not in IFR Form. This IFR form is not valid. \r
1793 //\r
82e8c138 1794 if (VarStorageData->VarStoreId == 0) {\r
d9bbabfd
ED
1795 Status = EFI_INVALID_PARAMETER;\r
1796 goto Done;\r
1797 }\r
1798 //\r
1799 // Check whether this question is for the requested varstore.\r
1800 //\r
1801 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;\r
1802 if (IfrDate->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1803 break;\r
1804 }\r
1805\r
d9bbabfd 1806 VarWidth = (UINT16) sizeof (EFI_HII_DATE);\r
82e8c138
ED
1807 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1808 if (EFI_ERROR (Status)) {\r
d9bbabfd
ED
1809 goto Done;\r
1810 }\r
d9bbabfd
ED
1811 break;\r
1812\r
1813 case EFI_IFR_TIME_OP:\r
1814 //\r
1815 // offset by question header\r
1816 // width MaxSize * sizeof (CHAR16)\r
1817 // no default value, only block array\r
1818 //\r
1819\r
1820 //\r
1821 // Time question is not in IFR Form. This IFR form is not valid. \r
1822 //\r
82e8c138 1823 if (VarStorageData->VarStoreId == 0) {\r
d9bbabfd
ED
1824 Status = EFI_INVALID_PARAMETER;\r
1825 goto Done;\r
1826 }\r
1827 //\r
1828 // Check whether this question is for the requested varstore.\r
1829 //\r
1830 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;\r
1831 if (IfrTime->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1832 break;\r
1833 }\r
1834\r
d9bbabfd 1835 VarWidth = (UINT16) sizeof (EFI_HII_TIME);\r
82e8c138
ED
1836 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1837 if (EFI_ERROR (Status)) {\r
d9bbabfd
ED
1838 goto Done;\r
1839 }\r
d9bbabfd
ED
1840 break;\r
1841\r
84f9a9ec
LG
1842 case EFI_IFR_STRING_OP:\r
1843 //\r
1844 // offset by question header\r
1845 // width MaxSize * sizeof (CHAR16)\r
1846 // no default value, only block array\r
1847 //\r
1848\r
8567300a
LG
1849 //\r
1850 // String question is not in IFR Form. This IFR form is not valid. \r
1851 //\r
82e8c138 1852 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1853 Status = EFI_INVALID_PARAMETER;\r
1854 goto Done;\r
1855 }\r
84f9a9ec
LG
1856 //\r
1857 // Check whether this question is for the requested varstore.\r
1858 //\r
1859 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1860 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1861 break;\r
1862 }\r
84f9a9ec 1863\r
82e8c138
ED
1864 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1865 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1866 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1867 goto Done;\r
1868 }\r
82e8c138 1869\r
84f9a9ec
LG
1870 //\r
1871 // No default value for string.\r
1872 //\r
1873 BlockData = NULL;\r
1874 break;\r
1875\r
1876 case EFI_IFR_PASSWORD_OP:\r
1877 //\r
1878 // offset by question header\r
1879 // width MaxSize * sizeof (CHAR16)\r
1880 // no default value, only block array\r
1881 //\r
1882\r
8567300a
LG
1883 //\r
1884 // Password question is not in IFR Form. This IFR form is not valid. \r
1885 //\r
82e8c138 1886 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1887 Status = EFI_INVALID_PARAMETER;\r
1888 goto Done;\r
1889 }\r
84f9a9ec
LG
1890 //\r
1891 // Check whether this question is for the requested varstore.\r
1892 //\r
1893 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
1894 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1895 break;\r
1896 }\r
84f9a9ec 1897\r
82e8c138
ED
1898 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
1899 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1900 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1901 goto Done;\r
1902 }\r
82e8c138 1903\r
84f9a9ec
LG
1904 //\r
1905 // No default value for string.\r
1906 //\r
1907 BlockData = NULL;\r
1908 break;\r
1909\r
1910 case EFI_IFR_ONE_OF_OPTION_OP:\r
1911 //\r
1912 // No matched block data is ignored.\r
1913 //\r
1914 if (BlockData == NULL || BlockData->Scope == 0) {\r
1915 break;\r
1916 }\r
82e8c138 1917\r
84f9a9ec
LG
1918 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1919 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1920 //\r
1921 // Get ordered list option data type.\r
1922 //\r
1923 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
1924 VarWidth = 1;\r
1925 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1926 VarWidth = 2;\r
1927 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1928 VarWidth = 4;\r
1929 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1930 VarWidth = 8;\r
1931 } else {\r
1932 //\r
1933 // Invalid ordered list option data type.\r
1934 //\r
1935 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
1936 if (BlockData->Name != NULL) {\r
1937 FreePool (BlockData->Name);\r
1938 }\r
ff28420b 1939 FreePool (BlockData);\r
84f9a9ec
LG
1940 goto Done;\r
1941 }\r
ff28420b 1942\r
84f9a9ec
LG
1943 //\r
1944 // Calculate Ordered list QuestionId width.\r
1945 //\r
1946 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
ff28420b
LG
1947 //\r
1948 // Check whether this question is in requested block array.\r
1949 //\r
70066a82 1950 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {\r
ff28420b
LG
1951 //\r
1952 // This question is not in the requested string. Skip it.\r
1953 //\r
82e8c138
ED
1954 if (BlockData->Name != NULL) {\r
1955 FreePool (BlockData->Name);\r
1956 }\r
ff28420b
LG
1957 FreePool (BlockData);\r
1958 BlockData = NULL;\r
1959 break;\r
1960 }\r
1961 //\r
1962 // Check this var question is in the var storage \r
1963 //\r
82e8c138 1964 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {\r
ff28420b 1965 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
1966 if (BlockData->Name != NULL) {\r
1967 FreePool (BlockData->Name);\r
1968 }\r
ff28420b
LG
1969 FreePool (BlockData);\r
1970 goto Done;\r
1971 }\r
1972 //\r
1973 // Add Block Data into VarStorageData BlockEntry\r
1974 //\r
1975 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1976 //\r
1977 // No default data for OrderedList.\r
1978 //\r
84f9a9ec
LG
1979 BlockData = NULL;\r
1980 break;\r
1981 }\r
1982\r
ef40f0f6
ED
1983 //\r
1984 // 1. Set default value for OneOf option when flag field has default attribute.\r
1985 //\r
cf4c5a42 1986 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
ef40f0f6 1987 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {\r
cf4c5a42
LG
1988 //\r
1989 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
1990 // The first oneof option value will be used as default value when no default value is specified. \r
1991 //\r
1992 FirstOneOfOption = FALSE;\r
ef40f0f6 1993 \r
84f9a9ec
LG
1994 // Prepare new DefaultValue\r
1995 //\r
82e8c138 1996 DefaultData.Type = DefaultValueFromFlag;\r
a7f87053 1997 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
1998 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
1999 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2000 InsertDefaultValue (BlockData, &DefaultData);\r
2001 } \r
2002 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
2003 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2004 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 2005 }\r
ef40f0f6 2006 }\r
82e8c138 2007\r
ef40f0f6
ED
2008 //\r
2009 // 2. Set as the default value when this is the first option.\r
2010 // The first oneof option value will be used as default value when no default value is specified. \r
2011 //\r
2012 if (FirstOneOfOption) {\r
2013 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2014 FirstOneOfOption = FALSE;\r
2015 \r
84f9a9ec
LG
2016 //\r
2017 // Prepare new DefaultValue\r
ef40f0f6 2018 // \r
82e8c138 2019 DefaultData.Type = DefaultValueFromDefault;\r
a7f87053 2020 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
2021 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2022 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry); \r
2023 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2024 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 2025 }\r
84f9a9ec
LG
2026 }\r
2027 break;\r
2028\r
2029 case EFI_IFR_DEFAULT_OP:\r
2030 //\r
2031 // Update Current BlockData to the default value.\r
2032 //\r
2033 if (BlockData == NULL || BlockData->Scope == 0) {\r
2034 //\r
82e8c138 2035 // No matched block data is ignored.\r
84f9a9ec
LG
2036 //\r
2037 break;\r
2038 }\r
2039\r
2040 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
2041 //\r
2042 // OrderedList Opcode is no default value.\r
2043 //\r
2044 break;\r
2045 }\r
2046 //\r
81b618fe 2047 // Get the DefaultId\r
84f9a9ec
LG
2048 //\r
2049 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
2050 VarDefaultId = IfrDefault->DefaultId;\r
84f9a9ec
LG
2051 //\r
2052 // Prepare new DefaultValue\r
2053 //\r
eb5e7d3e 2054 DefaultData.Type = DefaultValueFromOpcode;\r
ef40f0f6 2055 DefaultData.DefaultId = VarDefaultId;\r
23fe74dc 2056 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
82e8c138 2057\r
ef40f0f6
ED
2058 // If the value field is expression, set the cleaned flag.\r
2059 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
2060 DefaultData.Cleaned = TRUE;\r
84f9a9ec 2061 }\r
84f9a9ec
LG
2062 //\r
2063 // Add DefaultValue into current BlockData\r
2064 //\r
ef40f0f6 2065 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 2066\r
ef40f0f6
ED
2067 //\r
2068 // After insert the default value, reset the cleaned value for next \r
2069 // time used. If not set here, need to set the value before everytime \r
2070 // use it.\r
2071 //\r
2072 DefaultData.Cleaned = FALSE;\r
84f9a9ec 2073 break;\r
82e8c138 2074\r
84f9a9ec
LG
2075 case EFI_IFR_END_OP:\r
2076 //\r
8567300a 2077 // End Opcode is for Var question.\r
84f9a9ec
LG
2078 //\r
2079 if (BlockData != NULL && BlockData->Scope > 0) {\r
2080 BlockData->Scope--;\r
2081 }\r
2082 break;\r
82e8c138 2083\r
84f9a9ec
LG
2084 default:\r
2085 if (BlockData != NULL && BlockData->Scope > 0) {\r
2086 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
2087 }\r
2088 break;\r
2089 }\r
2090\r
2091 IfrOffset += IfrOpHdr->Length;\r
2092 }\r
2093\r
2094Done:\r
ef40f0f6
ED
2095 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2096 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2097 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
2098 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2099 LinkDefault = LinkDefault->ForwardLink;\r
2100 if (DefaultDataPtr->Cleaned == TRUE) {\r
2101 RemoveEntryList (&DefaultDataPtr->Entry);\r
2102 FreePool (DefaultDataPtr);\r
2103 }\r
2104 }\r
2105 }\r
2106\r
82e8c138 2107 return Status;\r
84f9a9ec
LG
2108}\r
2109\r
2110/**\r
82e8c138 2111 parse the configrequest string, get the elements.\r
84f9a9ec 2112\r
82e8c138
ED
2113 @param ConfigRequest The input configrequest string.\r
2114 @param Progress Return the progress data.\r
2115\r
2116 @retval Block data pointer.\r
2117**/\r
2118IFR_BLOCK_DATA *\r
2119GetBlockElement (\r
2120 IN EFI_STRING ConfigRequest,\r
2121 OUT EFI_STRING *Progress\r
2122 )\r
2123{\r
2124 EFI_STRING StringPtr;\r
2125 IFR_BLOCK_DATA *BlockData;\r
2126 IFR_BLOCK_DATA *RequestBlockArray;\r
2127 EFI_STATUS Status;\r
2128 UINT8 *TmpBuffer;\r
2129 UINT16 Offset;\r
2130 UINT16 Width;\r
2131 LIST_ENTRY *Link;\r
2132 IFR_BLOCK_DATA *NextBlockData;\r
2133 UINTN Length;\r
2134\r
2135 //\r
2136 // Init RequestBlockArray\r
2137 //\r
2138 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2139 if (RequestBlockArray == NULL) {\r
2140 goto Done;\r
2141 }\r
2142 InitializeListHead (&RequestBlockArray->Entry);\r
2143\r
2144 //\r
2145 // Get the request Block array from the request string\r
2146 // Offset and Width\r
2147 //\r
2148\r
2149 //\r
2150 // Parse each <RequestElement> if exists\r
2151 // Only <BlockName> format is supported by this help function.\r
2152 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
2153 //\r
2154 StringPtr = ConfigRequest;\r
2155 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
2156 //\r
2157 // Skip the OFFSET string\r
2158 //\r
2159 *Progress = StringPtr;\r
2160 StringPtr += StrLen (L"&OFFSET=");\r
2161 //\r
2162 // Get Offset\r
2163 //\r
2164 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2165 if (EFI_ERROR (Status)) {\r
2166 goto Done;\r
2167 }\r
2168 Offset = 0;\r
2169 CopyMem (\r
2170 &Offset,\r
2171 TmpBuffer,\r
2172 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2173 );\r
2174 FreePool (TmpBuffer);\r
2175\r
2176 StringPtr += Length;\r
2177 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
2178 goto Done;\r
2179 }\r
2180 StringPtr += StrLen (L"&WIDTH=");\r
2181\r
2182 //\r
2183 // Get Width\r
2184 //\r
2185 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2186 if (EFI_ERROR (Status)) {\r
2187 goto Done;\r
2188 }\r
2189 Width = 0;\r
2190 CopyMem (\r
2191 &Width,\r
2192 TmpBuffer,\r
2193 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2194 );\r
2195 FreePool (TmpBuffer);\r
2196\r
2197 StringPtr += Length;\r
2198 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2199 goto Done;\r
2200 }\r
2201 \r
2202 //\r
2203 // Set Block Data\r
2204 //\r
2205 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2206 if (BlockData == NULL) {\r
2207 goto Done;\r
2208 }\r
2209 BlockData->Offset = Offset;\r
2210 BlockData->Width = Width;\r
2211 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2212\r
2213 //\r
2214 // Skip &VALUE string if &VALUE does exists.\r
2215 //\r
2216 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
2217 StringPtr += StrLen (L"&VALUE=");\r
2218\r
2219 //\r
2220 // Get Value\r
2221 //\r
2222 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2223 if (EFI_ERROR (Status)) {\r
2224 goto Done;\r
2225 }\r
2226\r
2227 StringPtr += Length;\r
2228 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2229 goto Done;\r
2230 }\r
2231 }\r
2232 //\r
2233 // If '\0', parsing is finished. \r
2234 //\r
2235 if (*StringPtr == 0) {\r
2236 break;\r
2237 }\r
2238 }\r
2239\r
2240 //\r
2241 // Merge the requested block data.\r
2242 //\r
2243 Link = RequestBlockArray->Entry.ForwardLink;\r
2244 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
2245 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2246 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
2247 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
2248 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
2249 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
2250 }\r
2251 RemoveEntryList (Link->ForwardLink);\r
2252 FreePool (NextBlockData);\r
2253 continue;\r
2254 }\r
2255 Link = Link->ForwardLink;\r
2256 }\r
2257\r
2258 return RequestBlockArray;\r
2259\r
2260Done:\r
2261 if (RequestBlockArray != NULL) {\r
2262 //\r
2263 // Free Link Array RequestBlockArray\r
2264 //\r
2265 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2266 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2267 RemoveEntryList (&BlockData->Entry);\r
2268 FreePool (BlockData);\r
2269 }\r
2270\r
2271 FreePool (RequestBlockArray);\r
2272 }\r
2273\r
2274 return NULL;\r
2275}\r
2276\r
2277/**\r
2278 parse the configrequest string, get the elements.\r
2279\r
2280 @param ConfigRequest The input config request string.\r
2281 @param Progress Return the progress data.\r
2282\r
2283 @retval return data block array.\r
2284**/\r
2285IFR_BLOCK_DATA *\r
2286GetNameElement (\r
2287 IN EFI_STRING ConfigRequest,\r
2288 OUT EFI_STRING *Progress\r
2289 )\r
2290{\r
2291 EFI_STRING StringPtr;\r
2292 EFI_STRING NextTag;\r
2293 IFR_BLOCK_DATA *BlockData;\r
2294 IFR_BLOCK_DATA *RequestBlockArray;\r
2295 BOOLEAN HasValue;\r
2296\r
2297 StringPtr = ConfigRequest;\r
2298\r
2299 //\r
2300 // Init RequestBlockArray\r
2301 //\r
2302 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2303 if (RequestBlockArray == NULL) {\r
2304 goto Done;\r
2305 }\r
2306 InitializeListHead (&RequestBlockArray->Entry);\r
2307\r
2308 //\r
2309 // Get the request Block array from the request string\r
2310 //\r
2311\r
2312 //\r
2313 // Parse each <RequestElement> if exists\r
2314 // Only <BlockName> format is supported by this help function.\r
2315 // <BlockName> ::= &'Name***=***\r
2316 //\r
2317 while (StringPtr != NULL && *StringPtr == L'&') {\r
2318\r
2319 *Progress = StringPtr;\r
2320 //\r
2321 // Skip the L"&" string\r
2322 //\r
2323 StringPtr += 1;\r
2324\r
2325 HasValue = FALSE;\r
2326 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
2327 *NextTag = L'\0';\r
2328 HasValue = TRUE;\r
2329 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
2330 *NextTag = L'\0';\r
2331 }\r
2332\r
2333 //\r
2334 // Set Block Data\r
2335 //\r
2336 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2337 if (BlockData == NULL) {\r
2338 goto Done;\r
2339 }\r
2340\r
2341 //\r
2342 // Get Name\r
2343 //\r
2344 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);\r
2345 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2346\r
2347 if (HasValue) {\r
2348 //\r
2349 // If has value, skip the value.\r
2350 // \r
2351 StringPtr = NextTag + 1;\r
2352 *NextTag = L'=';\r
2353 StringPtr = StrStr (StringPtr, L"&");\r
2354 } else if (NextTag != NULL) {\r
2355 //\r
2356 // restore the '&' text.\r
2357 //\r
2358 StringPtr = NextTag;\r
2359 *NextTag = L'&';\r
2360 }\r
2361 }\r
2362\r
2363 return RequestBlockArray;\r
2364\r
2365Done:\r
2366 if (RequestBlockArray != NULL) {\r
2367 //\r
2368 // Free Link Array RequestBlockArray\r
2369 //\r
2370 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2371 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2372 RemoveEntryList (&BlockData->Entry);\r
2373 if (BlockData->Name != NULL) {\r
2374 FreePool (BlockData->Name);\r
2375 }\r
2376 FreePool (BlockData);\r
2377 }\r
2378\r
2379 FreePool (RequestBlockArray);\r
2380 }\r
2381\r
2382 return NULL;\r
2383}\r
2384\r
2385/**\r
2386 Generate ConfigRequest string base on the varstore info.\r
2387\r
2388 @param ConfigHdr The config header for this varstore.\r
2389 @param VarStorageData The varstore info.\r
2390 @param Status Return Status.\r
2391 @param ConfigRequest The ConfigRequest info may be return.\r
2392\r
2393 @retval TRUE Need to continue\r
2394 @retval Others NO need to continue or error occur.\r
2395**/\r
2396BOOLEAN\r
2397GenerateConfigRequest (\r
2398 IN CHAR16 *ConfigHdr,\r
2399 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2400 OUT EFI_STATUS *Status,\r
2401 IN OUT EFI_STRING *ConfigRequest\r
2402 )\r
2403{\r
2404 BOOLEAN DataExist;\r
2405 UINTN Length;\r
2406 LIST_ENTRY *Link;\r
2407 CHAR16 *FullConfigRequest;\r
2408 CHAR16 *StringPtr;\r
2409 IFR_BLOCK_DATA *BlockData;\r
2410\r
2411 //\r
2412 // Append VarStorageData BlockEntry into *Request string\r
2413 // Now support only one varstore in a form package.\r
2414 //\r
2415 \r
2416 //\r
2417 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
2418 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
2419 //\r
2420 \r
2421 //\r
2422 // Compute the length of the entire request starting with <ConfigHdr> and a \r
2423 // Null-terminator\r
2424 //\r
2425 DataExist = FALSE;\r
2426 Length = StrLen (ConfigHdr) + 1;\r
2427\r
2428 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2429 DataExist = TRUE;\r
2430 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2431 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2432 //\r
2433 // Add <BlockName> length for each Name\r
2434 //\r
2435 // <BlockName> ::= &Name1&Name2&... \r
2436 // |1| StrLen(Name1)\r
2437 //\r
2438 Length = Length + (1 + StrLen (BlockData->Name));\r
2439 } else {\r
2440 //\r
2441 // Add <BlockName> length for each Offset/Width pair\r
2442 //\r
2443 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
2444 // | 8 | 4 | 7 | 4 |\r
2445 //\r
2446 Length = Length + (8 + 4 + 7 + 4);\r
2447 }\r
2448 }\r
2449 //\r
2450 // No any request block data is found. The request string can't be constructed.\r
2451 //\r
2452 if (!DataExist) {\r
2453 *Status = EFI_SUCCESS;\r
2454 return FALSE;\r
2455 }\r
2456\r
2457 //\r
2458 // Allocate buffer for the entire <ConfigRequest>\r
2459 //\r
2460 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
2461 if (FullConfigRequest == NULL) {\r
2462 *Status = EFI_OUT_OF_RESOURCES;\r
2463 return FALSE;\r
2464 }\r
2465 StringPtr = FullConfigRequest;\r
2466\r
2467 //\r
2468 // Start with <ConfigHdr>\r
2469 //\r
2470 StrCpy (StringPtr, ConfigHdr);\r
2471 StringPtr += StrLen (StringPtr);\r
2472\r
2473 //\r
2474 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
2475 //\r
2476 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2477 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2478 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2479 //\r
2480 // Append &Name1\0\r
2481 //\r
2482 UnicodeSPrint (\r
2483 StringPtr,\r
2484 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
2485 L"&%s",\r
2486 BlockData->Name\r
2487 );\r
2488 } else {\r
2489 //\r
2490 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
2491 //\r
2492 UnicodeSPrint (\r
2493 StringPtr, \r
2494 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
2495 L"&OFFSET=%04X&WIDTH=%04X", \r
2496 BlockData->Offset, \r
2497 BlockData->Width\r
2498 );\r
2499 }\r
2500 StringPtr += StrLen (StringPtr);\r
2501 }\r
2502 //\r
2503 // Set to the got full request string.\r
2504 //\r
2505 HiiToLower (FullConfigRequest);\r
2506\r
2507 if (*ConfigRequest != NULL) {\r
2508 FreePool (*ConfigRequest);\r
2509 }\r
2510 *ConfigRequest = FullConfigRequest;\r
2511\r
2512 return TRUE;\r
2513}\r
2514\r
2515/**\r
2516 Generate ConfigRequest Header base on the varstore info.\r
2517\r
2518 @param VarStorageData The varstore info.\r
2519 @param DevicePath Device path for this varstore.\r
2520 @param ConfigHdr The config header for this varstore.\r
2521\r
2522 @retval EFI_SUCCESS Generate the header success.\r
2523 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
2524**/\r
2525EFI_STATUS\r
2526GenerateHdr (\r
2527 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2528 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2529 OUT EFI_STRING *ConfigHdr\r
2530 )\r
2531{\r
2532 EFI_STRING GuidStr;\r
2533 EFI_STRING NameStr;\r
2534 EFI_STRING PathStr;\r
2535 UINTN Length;\r
2536 EFI_STATUS Status;\r
2537\r
2538 Status = EFI_SUCCESS;\r
2539 NameStr = NULL;\r
2540 GuidStr = NULL;\r
2541 PathStr = NULL;\r
2542\r
2543 //\r
2544 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
2545 //\r
2546 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
2547 if (VarStorageData->Name != NULL) {\r
2548 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
2549 } else {\r
2550 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
2551 }\r
2552 GenerateSubStr (\r
2553 L"PATH=",\r
2554 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
2555 (VOID *) DevicePath,\r
2556 1,\r
2557 &PathStr\r
2558 );\r
2559 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
2560 if (VarStorageData->Name == NULL) {\r
2561 Length += 1;\r
2562 }\r
2563\r
2564 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
2565 if (*ConfigHdr == NULL) {\r
2566 Status = EFI_OUT_OF_RESOURCES;\r
2567 goto Done;\r
2568 }\r
2569 StrCpy (*ConfigHdr, GuidStr);\r
2570 StrCat (*ConfigHdr, NameStr);\r
2571 if (VarStorageData->Name == NULL) {\r
2572 StrCat (*ConfigHdr, L"&");\r
2573 }\r
2574 StrCat (*ConfigHdr, PathStr);\r
2575\r
2576 //\r
2577 // Remove the last character L'&'\r
2578 //\r
2579 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
2580\r
2581Done:\r
2582 if (GuidStr != NULL) {\r
2583 FreePool (GuidStr);\r
2584 }\r
2585\r
2586 if (NameStr != NULL) {\r
2587 FreePool (NameStr);\r
2588 }\r
2589\r
2590 if (PathStr != NULL) {\r
2591 FreePool (PathStr);\r
2592 }\r
2593\r
2594 return Status;\r
2595}\r
2596\r
2597/**\r
2598 Get Data buffer size based on data type.\r
2599\r
2600 @param ValueType The input data type.\r
2601\r
2602 @retval The data buffer size for the input type.\r
2603**/\r
2604UINT16\r
2605GetStorageWidth (\r
2606 IN UINT8 ValueType\r
2607 )\r
2608{\r
2609 UINT16 StorageWidth;\r
2610\r
2611 switch (ValueType) {\r
2612 case EFI_IFR_NUMERIC_SIZE_1:\r
2613 case EFI_IFR_TYPE_BOOLEAN:\r
2614 StorageWidth = (UINT16) sizeof (UINT8);\r
2615 break;\r
2616\r
2617 case EFI_IFR_NUMERIC_SIZE_2:\r
2618 StorageWidth = (UINT16) sizeof (UINT16);\r
2619 break;\r
2620\r
2621 case EFI_IFR_NUMERIC_SIZE_4:\r
2622 StorageWidth = (UINT16) sizeof (UINT32);\r
2623 break;\r
2624\r
2625 case EFI_IFR_NUMERIC_SIZE_8:\r
2626 StorageWidth = (UINT16) sizeof (UINT64);\r
2627 break;\r
2628\r
2629 case EFI_IFR_TYPE_TIME:\r
2630 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);\r
2631 break;\r
2632\r
2633 case EFI_IFR_TYPE_DATE:\r
2634 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);\r
2635 break;\r
2636\r
2637 default:\r
2638 StorageWidth = 0;\r
2639 break;\r
2640 }\r
2641\r
2642 return StorageWidth;\r
2643}\r
2644\r
2645/**\r
2646 Generate ConfigAltResp string base on the varstore info.\r
2647\r
2648 @param ConfigHdr The config header for this varstore.\r
2649 @param VarStorageData The varstore info.\r
2650 @param DefaultIdArray The Default id array.\r
2651 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
2652\r
2653 @retval TRUE Need to continue\r
2654 @retval Others NO need to continue or error occur.\r
2655**/\r
2656EFI_STATUS\r
2657GenerateAltConfigResp (\r
2658 IN CHAR16 *ConfigHdr,\r
2659 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2660 IN IFR_DEFAULT_DATA *DefaultIdArray,\r
2661 IN OUT EFI_STRING *DefaultAltCfgResp\r
2662 )\r
2663{\r
2664 BOOLEAN DataExist;\r
2665 UINTN Length;\r
2666 LIST_ENTRY *Link;\r
2667 LIST_ENTRY *LinkData;\r
2668 LIST_ENTRY *LinkDefault;\r
2669 LIST_ENTRY *ListEntry;\r
2670 CHAR16 *StringPtr;\r
2671 IFR_BLOCK_DATA *BlockData;\r
2672 IFR_DEFAULT_DATA *DefaultId;\r
2673 IFR_DEFAULT_DATA *DefaultValueData;\r
2674 UINTN Width;\r
2675 UINT8 *TmpBuffer;\r
2676\r
2677 BlockData = NULL;\r
2678 DataExist = FALSE;\r
2679\r
2680 //\r
2681 // Add length for <ConfigHdr> + '\0'\r
2682 //\r
2683 Length = StrLen (ConfigHdr) + 1;\r
2684\r
2685 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2686 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2687 //\r
2688 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
2689 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2690 //\r
2691 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
2692 \r
2693 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2694 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2695 ListEntry = &BlockData->DefaultValueEntry;\r
2696 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2697 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2698 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2699 continue;\r
2700 }\r
2701 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2702 //\r
2703 // Add length for "&Name1=zzzzzzzzzzzz"\r
2704 // |1|Name|1|Value|\r
2705 //\r
2706 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
2707 } else {\r
2708 //\r
2709 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
2710 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
2711 //\r
2712 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
2713 }\r
2714 DataExist = TRUE;\r
2715 }\r
2716 }\r
2717 }\r
2718 \r
2719 //\r
2720 // No default value is found. The default string doesn't exist.\r
2721 //\r
2722 if (!DataExist) {\r
2723 return EFI_SUCCESS;\r
2724 }\r
2725\r
2726 //\r
2727 // Allocate buffer for the entire <DefaultAltCfgResp>\r
2728 //\r
2729 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
2730 if (*DefaultAltCfgResp == NULL) {\r
2731 return EFI_OUT_OF_RESOURCES;\r
2732 }\r
2733 StringPtr = *DefaultAltCfgResp;\r
2734\r
2735 //\r
2736 // Start with <ConfigHdr>\r
2737 //\r
2738 StrCpy (StringPtr, ConfigHdr);\r
2739 StringPtr += StrLen (StringPtr);\r
2740\r
2741 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2742 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2743 //\r
2744 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
2745 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2746 //\r
2747 UnicodeSPrint (\r
2748 StringPtr, \r
2749 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
2750 L"&%s&ALTCFG=%04X", \r
2751 ConfigHdr, \r
2752 DefaultId->DefaultId\r
2753 );\r
2754 StringPtr += StrLen (StringPtr);\r
2755\r
2756 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2757 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2758 ListEntry = &BlockData->DefaultValueEntry;\r
2759 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2760 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2761 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2762 continue;\r
2763 }\r
2764 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2765 UnicodeSPrint (\r
2766 StringPtr, \r
2767 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16), \r
2768 L"&%s=", \r
2769 BlockData->Name\r
2770 );\r
2771 StringPtr += StrLen (StringPtr);\r
2772 } else {\r
2773 //\r
2774 // Add <BlockConfig>\r
2775 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
2776 //\r
2777 UnicodeSPrint (\r
2778 StringPtr, \r
2779 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
2780 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
2781 BlockData->Offset, \r
2782 BlockData->Width\r
2783 );\r
2784 StringPtr += StrLen (StringPtr);\r
2785 }\r
2786 Width = BlockData->Width;\r
2787 //\r
2788 // Convert Value to a hex string in "%x" format\r
2789 // NOTE: This is in the opposite byte that GUID and PATH use\r
2790 //\r
2791 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
2792 for (; Width > 0; Width--) {\r
2793 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
2794 }\r
2795 }\r
2796 }\r
2797 }\r
2798\r
2799 HiiToLower (*DefaultAltCfgResp);\r
2800\r
2801 return EFI_SUCCESS;\r
2802}\r
2803\r
2804/**\r
2805 This function gets the full request string and full default value string by \r
2806 parsing IFR data in HII form packages. \r
2807 \r
2808 When Request points to NULL string, the request string and default value string \r
2809 for each varstore in form package will return. \r
2810\r
2811 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
2812 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
2813 @param Request Pointer to a null-terminated Unicode string in\r
2814 <ConfigRequest> format. When it doesn't contain\r
2815 any RequestElement, it will be updated to return \r
2816 the full RequestElement retrieved from IFR data.\r
2817 If it points to NULL, the request string for the first\r
2818 varstore in form package will be merged into a\r
2819 <MultiConfigRequest> format string and return. \r
2820 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
2821 <ConfigAltResp> format. When the pointer is to NULL,\r
2822 the full default value string retrieved from IFR data\r
2823 will return. When the pinter is to a string, the\r
2824 full default value string retrieved from IFR data\r
2825 will be merged into the input string and return.\r
2826 When Request points to NULL, the default value string \r
2827 for each varstore in form package will be merged into \r
2828 a <MultiConfigAltResp> format string and return.\r
2829 @param PointerProgress Optional parameter, it can be be NULL. \r
2830 When it is not NULL, if Request is NULL, it returns NULL. \r
2831 On return, points to a character in the Request\r
2832 string. Points to the string's null terminator if\r
2833 request was successful. Points to the most recent\r
2834 & before the first failing name / value pair (or\r
ae79d2f9
LG
2835 the beginning of the string if the failure is in\r
2836 the first name / value pair) if the request was\r
2837 not successful.\r
84f9a9ec
LG
2838 @retval EFI_SUCCESS The Results string is set to the full request string.\r
2839 And AltCfgResp contains all default value string.\r
2840 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
2841 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
2842 can't be found in Form package.\r
2843 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 2844 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
2845\r
2846**/\r
2847EFI_STATUS\r
2848EFIAPI\r
2849GetFullStringFromHiiFormPackages (\r
8567300a 2850 IN HII_DATABASE_RECORD *DataBaseRecord,\r
84f9a9ec
LG
2851 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2852 IN OUT EFI_STRING *Request,\r
ae79d2f9
LG
2853 IN OUT EFI_STRING *AltCfgResp,\r
2854 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
2855 )\r
2856{\r
2857 EFI_STATUS Status;\r
8567300a
LG
2858 UINT8 *HiiFormPackage;\r
2859 UINTN PackageSize;\r
84f9a9ec
LG
2860 IFR_BLOCK_DATA *RequestBlockArray;\r
2861 IFR_BLOCK_DATA *BlockData;\r
84f9a9ec
LG
2862 IFR_DEFAULT_DATA *DefaultValueData;\r
2863 IFR_DEFAULT_DATA *DefaultId;\r
2864 IFR_DEFAULT_DATA *DefaultIdArray;\r
84f9a9ec
LG
2865 IFR_VARSTORAGE_DATA *VarStorageData;\r
2866 EFI_STRING DefaultAltCfgResp;\r
270e8dfd
OM
2867 EFI_STRING ConfigHdr;
2868 EFI_STRING StringPtr;
2869 EFI_STRING Progress;
2870
2871 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
2872 return EFI_INVALID_PARAMETER;
ae79d2f9
LG
2873 }\r
2874\r
84f9a9ec
LG
2875 //\r
2876 // Initialize the local variables.\r
2877 //\r
2878 RequestBlockArray = NULL;\r
8567300a 2879 DefaultIdArray = NULL;\r
84f9a9ec
LG
2880 VarStorageData = NULL;\r
2881 DefaultAltCfgResp = NULL;\r
270e8dfd
OM
2882 ConfigHdr = NULL;
2883 HiiFormPackage = NULL;
2884 PackageSize = 0;
2885 Progress = *Request;
2886
2887 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
84f9a9ec 2888 if (EFI_ERROR (Status)) {\r
cce6230f 2889 return Status;\r
84f9a9ec
LG
2890 }\r
2891\r
2892 //\r
8567300a 2893 // 1. Get the request block array by Request String when Request string containts the block array.\r
84f9a9ec
LG
2894 //\r
2895 StringPtr = NULL;\r
2896 if (*Request != NULL) {\r
ae79d2f9
LG
2897 StringPtr = *Request;\r
2898 //\r
2899 // Jump <ConfigHdr>\r
2900 //\r
2901 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2902 Status = EFI_INVALID_PARAMETER;\r
2903 goto Done;\r
2904 }\r
2905 StringPtr += StrLen (L"GUID=");\r
2906 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
2907 StringPtr++;\r
2908 }\r
2909 if (*StringPtr == L'\0') {\r
2910 Status = EFI_INVALID_PARAMETER;\r
2911 goto Done;\r
2912 }\r
2913 StringPtr += StrLen (L"&NAME=");\r
82e8c138
ED
2914 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
2915 StringPtr++;\r
6e3f5b2a 2916 }\r
82e8c138
ED
2917 if (*StringPtr == L'\0') {\r
2918 Status = EFI_INVALID_PARAMETER;\r
84f9a9ec
LG
2919 goto Done;\r
2920 }\r
82e8c138
ED
2921 StringPtr += StrLen (L"&PATH=");\r
2922 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2923 StringPtr ++;\r
2924 }\r
84f9a9ec 2925\r
82e8c138 2926 if (*StringPtr == L'\0') {\r
84f9a9ec 2927 //\r
82e8c138 2928 // No request block is found.\r
84f9a9ec 2929 //\r
82e8c138 2930 StringPtr = NULL;\r
84f9a9ec 2931 }\r
84f9a9ec 2932 }\r
82e8c138 2933\r
93e3992d 2934 //\r
82e8c138 2935 // If StringPtr != NULL, get the request elements.\r
93e3992d 2936 //\r
82e8c138
ED
2937 if (StringPtr != NULL) {\r
2938 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {\r
2939 RequestBlockArray = GetBlockElement(StringPtr, &Progress);\r
2940 } else {\r
2941 RequestBlockArray = GetNameElement(StringPtr, &Progress);\r
2942 }\r
2943\r
2944 if (RequestBlockArray == NULL) {\r
2945 Status = EFI_INVALID_PARAMETER;\r
2946 goto Done;\r
84f9a9ec 2947 }\r
93e3992d 2948 }\r
82e8c138 2949\r
6e3f5b2a 2950 //\r
82e8c138 2951 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
6e3f5b2a 2952 //\r
82e8c138
ED
2953 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
2954 if (DefaultIdArray == NULL) {\r
2955 Status = EFI_OUT_OF_RESOURCES;\r
6e3f5b2a
LG
2956 goto Done;\r
2957 }\r
82e8c138 2958 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 2959\r
93e3992d 2960 //\r
82e8c138 2961 // Initialize VarStorageData to store the var store Block and Default value information.\r
93e3992d 2962 //\r
82e8c138
ED
2963 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
2964 if (VarStorageData == NULL) {\r
6e3f5b2a 2965 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
2966 goto Done;\r
2967 }\r
82e8c138
ED
2968 InitializeListHead (&VarStorageData->Entry);\r
2969 InitializeListHead (&VarStorageData->BlockEntry);\r
93e3992d 2970\r
84f9a9ec 2971 //\r
82e8c138 2972 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 2973 //\r
93e3992d 2974\r
82e8c138
ED
2975 //\r
2976 // Parse the opcode in form pacakge to get the default setting.\r
2977 //\r
2978 Status = ParseIfrData (DataBaseRecord->Handle,\r
2979 HiiFormPackage,\r
2980 (UINT32) PackageSize,\r
2981 *Request,\r
2982 RequestBlockArray,\r
2983 VarStorageData,\r
2984 DefaultIdArray);\r
2985 if (EFI_ERROR (Status)) {\r
2986 goto Done;\r
2987 }\r
84f9a9ec 2988\r
82e8c138
ED
2989 //\r
2990 // No requested varstore in IFR data and directly return\r
2991 //\r
2992 if (VarStorageData->VarStoreId == 0) {\r
2993 Status = EFI_SUCCESS;\r
2994 goto Done;\r
2995 }\r
2996\r
2997 //\r
2998 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
2999 //\r
3000 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);\r
3001 if (EFI_ERROR (Status)) {\r
3002 goto Done;\r
3003 }\r
3004\r
3005 if (RequestBlockArray == NULL) {\r
3006 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {\r
3007 goto Done;\r
84f9a9ec 3008 }\r
93e3992d 3009 }\r
82e8c138
ED
3010\r
3011 //\r
3012 // 4. Construct Default Value string in AltResp according to request element.\r
3013 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
3014 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
3015 //\r
3016 Status = GenerateAltConfigResp (ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);\r
3017 if (EFI_ERROR (Status)) {\r
3018 goto Done;\r
3019 }\r
93e3992d 3020\r
84f9a9ec
LG
3021 //\r
3022 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
3023 //\r
6e3f5b2a 3024 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
84f9a9ec
LG
3025 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
3026 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
3027 } else if (*AltCfgResp == NULL) {\r
3028 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 3029 }\r
93e3992d 3030\r
84f9a9ec
LG
3031Done:\r
3032 if (RequestBlockArray != NULL) {\r
3033 //\r
3034 // Free Link Array RequestBlockArray\r
3035 //\r
3036 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3037 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3038 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
3039 if (BlockData->Name != NULL) {\r
3040 FreePool (BlockData->Name);\r
3041 }\r
84f9a9ec
LG
3042 FreePool (BlockData);\r
3043 }\r
3044\r
3045 FreePool (RequestBlockArray);\r
93e3992d 3046 }\r
82e8c138 3047\r
84f9a9ec
LG
3048 if (VarStorageData != NULL) {\r
3049 //\r
3050 // Free link array VarStorageData\r
3051 //\r
3052 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
3053 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3054 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
3055 if (BlockData->Name != NULL) {\r
3056 FreePool (BlockData->Name);\r
3057 }\r
84f9a9ec
LG
3058 //\r
3059 // Free default value link array\r
3060 //\r
3061 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
3062 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3063 RemoveEntryList (&DefaultValueData->Entry);\r
3064 FreePool (DefaultValueData);\r
3065 }\r
3066 FreePool (BlockData);\r
63d55bb9 3067 }\r
84f9a9ec 3068 FreePool (VarStorageData);\r
93e3992d 3069 }\r
3070\r
84f9a9ec
LG
3071 if (DefaultIdArray != NULL) {\r
3072 //\r
3073 // Free DefaultId Array\r
3074 //\r
3075 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
3076 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3077 RemoveEntryList (&DefaultId->Entry);\r
3078 FreePool (DefaultId);\r
3079 }\r
3080 FreePool (DefaultIdArray);\r
3081 }\r
82e8c138 3082\r
84f9a9ec
LG
3083 //\r
3084 // Free the allocated string \r
3085 //\r
84f9a9ec
LG
3086 if (ConfigHdr != NULL) {\r
3087 FreePool (ConfigHdr);\r
3088 }\r
93e3992d 3089\r
84f9a9ec
LG
3090 //\r
3091 // Free Pacakge data\r
3092 //\r
8567300a
LG
3093 if (HiiFormPackage != NULL) {\r
3094 FreePool (HiiFormPackage);\r
676df92c 3095 }\r
63d55bb9 3096\r
ae79d2f9
LG
3097 if (PointerProgress != NULL) {\r
3098 if (*Request == NULL) {\r
3099 *PointerProgress = NULL;\r
3100 } else if (EFI_ERROR (Status)) {\r
82e8c138 3101 *PointerProgress = *Request;\r
ae79d2f9
LG
3102 } else {\r
3103 *PointerProgress = *Request + StrLen (*Request);\r
3104 }\r
3105 }\r
3106\r
93e3992d 3107 return Status;\r
3108}\r
3109\r
cce6230f
ED
3110/**\r
3111 This function gets the full request resp string by \r
3112 parsing IFR data in HII form packages.\r
3113\r
3114 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3115 instance.\r
3116 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3117 varstore data structure. \r
3118 @param Request Pointer to a null-terminated Unicode string in\r
3119 <ConfigRequest> format.\r
3120 @param RequestResp Pointer to a null-terminated Unicode string in\r
3121 <ConfigResp> format.\r
3122 @param AccessProgress On return, points to a character in the Request\r
3123 string. Points to the string's null terminator if\r
3124 request was successful. Points to the most recent\r
3125 & before the first failing name / value pair (or\r
3126 the beginning of the string if the failure is in\r
3127 the first name / value pair) if the request was\r
3128 not successful.\r
3129\r
3130 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3131 And AltCfgResp contains all default value string.\r
3132 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3133 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3134\r
3135**/\r
3136EFI_STATUS\r
3137GetConfigRespFromEfiVarStore (\r
3138 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3139 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3140 IN EFI_STRING Request,\r
3141 OUT EFI_STRING *RequestResp,\r
3142 OUT EFI_STRING *AccessProgress\r
3143 )\r
3144{\r
3145 EFI_STATUS Status;\r
3146 EFI_STRING VarStoreName;\r
3147 UINT8 *VarStore;\r
3148 UINTN BufferSize;\r
3149\r
3150 Status = EFI_SUCCESS;\r
3151 BufferSize = 0;\r
3152 VarStore = NULL;\r
3153 VarStoreName = NULL;\r
3154 \r
3155 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3156 if (VarStoreName == NULL) {\r
3157 Status = EFI_OUT_OF_RESOURCES;\r
3158 goto Done;\r
3159 }\r
3160 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3161 \r
3162 \r
3163 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3164 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3165 goto Done;\r
3166 }\r
3167\r
3168 VarStore = AllocateZeroPool (BufferSize);\r
3169 ASSERT (VarStore != NULL);\r
3170 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3171 if (EFI_ERROR (Status)) {\r
3172 goto Done;\r
3173 }\r
3174\r
3175 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
3176 if (EFI_ERROR (Status)) {\r
3177 goto Done;\r
3178 }\r
3179\r
3180Done:\r
3181 if (VarStoreName != NULL) {\r
3182 FreePool (VarStoreName);\r
3183 }\r
3184\r
3185 if (VarStore != NULL) {\r
3186 FreePool (VarStore);\r
3187 }\r
3188\r
3189 return Status;\r
3190}\r
3191\r
3192\r
3193/**\r
3194 This function route the full request resp string for efi varstore. \r
3195\r
3196 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3197 instance.\r
3198 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3199 varstore data structure. \r
3200 @param RequestResp Pointer to a null-terminated Unicode string in\r
3201 <ConfigResp> format.\r
3202 @param Result Pointer to a null-terminated Unicode string in\r
3203 <ConfigResp> format.\r
3204 \r
3205 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3206 And AltCfgResp contains all default value string.\r
3207 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3208 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3209\r
3210**/\r
3211EFI_STATUS\r
3212RouteConfigRespForEfiVarStore (\r
3213 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3214 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3215 IN EFI_STRING RequestResp,\r
3216 OUT EFI_STRING *Result\r
3217 )\r
3218{\r
3219 EFI_STATUS Status;\r
3220 EFI_STRING VarStoreName;\r
f26b6a9c 3221 UINT8 *VarStore;\r
cce6230f
ED
3222 UINTN BufferSize;\r
3223 UINTN BlockSize;\r
3224\r
3225 Status = EFI_SUCCESS;\r
3226 BufferSize = 0;\r
3227 VarStore = NULL;\r
3228 VarStoreName = NULL;\r
3229\r
3230 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3231 if (VarStoreName == NULL) {\r
3232 Status = EFI_OUT_OF_RESOURCES;\r
3233 goto Done;\r
3234 }\r
3235 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3236 \r
3237 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3238 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3239 goto Done;\r
3240 }\r
3241\r
3242 BlockSize = BufferSize;\r
3243 VarStore = AllocateZeroPool (BufferSize);\r
3244 ASSERT (VarStore != NULL);\r
3245 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3246 if (EFI_ERROR (Status)) {\r
3247 goto Done;\r
3248 }\r
3249\r
3250 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);\r
3251 if (EFI_ERROR (Status)) {\r
3252 goto Done;\r
3253 }\r
3254\r
3255 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
3256 if (EFI_ERROR (Status)) {\r
3257 goto Done;\r
3258 }\r
3259\r
3260Done:\r
3261 if (VarStoreName != NULL) {\r
3262 FreePool (VarStoreName);\r
3263 }\r
3264\r
3265 if (VarStore != NULL) {\r
3266 FreePool (VarStore);\r
3267 }\r
3268\r
3269 return Status;\r
3270}\r
3271\r
82e8c138
ED
3272/**\r
3273 Validate the config request elements.\r
3274\r
3275 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3276 without configHdr field.\r
3277\r
3278 @retval CHAR16 * THE first Name/value pair not correct.\r
3279 @retval NULL Success parse the name/value pair\r
3280**/\r
3281CHAR16 *\r
3282OffsetWidthValidate (\r
3283 CHAR16 *ConfigElements\r
3284 )\r
3285{\r
3286 CHAR16 *StringPtr;\r
3287 CHAR16 *RetVal;\r
3288\r
3289 StringPtr = ConfigElements;\r
3290\r
3291 while (1) {\r
3292 RetVal = StringPtr;\r
3293 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3294 return RetVal;\r
3295 }\r
3296\r
3297 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3298 StringPtr++;\r
3299 }\r
3300 if (*StringPtr == L'\0') {\r
3301 return RetVal;\r
3302 }\r
3303\r
3304 StringPtr += StrLen (L"&WIDTH=");\r
3305 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3306 StringPtr ++;\r
3307 }\r
3308\r
3309 if (*StringPtr == L'\0') {\r
3310 return NULL;\r
3311 }\r
3312 }\r
3313}\r
3314\r
3315/**\r
3316 Validate the config request elements.\r
3317\r
3318 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3319 without configHdr field.\r
3320\r
3321 @retval CHAR16 * THE first Name/value pair not correct.\r
3322 @retval NULL Success parse the name/value pair\r
3323\r
3324**/\r
3325CHAR16 *\r
3326NameValueValidate (\r
3327 CHAR16 *ConfigElements\r
3328 )\r
3329{\r
3330 CHAR16 *StringPtr;\r
3331 CHAR16 *RetVal;\r
3332\r
3333 StringPtr = ConfigElements;\r
3334\r
3335 while (1) {\r
3336 RetVal = StringPtr;\r
3337 if (*StringPtr != L'&') {\r
3338 return RetVal;\r
3339 }\r
3340 StringPtr += 1;\r
3341\r
3342 StringPtr = StrStr (StringPtr, L"&");\r
3343 \r
3344 if (StringPtr == NULL) {\r
3345 return NULL;\r
3346 }\r
3347 }\r
3348}\r
3349\r
3350/**\r
3351 Validate the config request string.\r
3352\r
3353 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.\r
3354\r
3355 @retval CHAR16 * THE first element not correct.\r
3356 @retval NULL Success parse the name/value pair\r
3357\r
3358**/\r
3359CHAR16 *\r
3360ConfigRequestValidate (\r
3361 CHAR16 *ConfigRequest\r
3362 )\r
3363{\r
3364 BOOLEAN HasNameField;\r
3365 CHAR16 *StringPtr;\r
3366\r
3367 HasNameField = TRUE;\r
3368 StringPtr = ConfigRequest;\r
3369\r
3370 //\r
3371 // Check <ConfigHdr>\r
3372 //\r
3373 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3374 return ConfigRequest;\r
3375 }\r
3376 StringPtr += StrLen (L"GUID=");\r
3377 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
3378 StringPtr++;\r
3379 }\r
3380 if (*StringPtr == L'\0') {\r
3381 return ConfigRequest;\r
3382 }\r
3383 StringPtr += StrLen (L"&NAME=");\r
3384 if (*StringPtr == L'&') {\r
3385 HasNameField = FALSE;\r
3386 }\r
3387 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
3388 StringPtr++;\r
3389 }\r
3390 if (*StringPtr == L'\0') {\r
3391 return ConfigRequest;\r
3392 }\r
3393 StringPtr += StrLen (L"&PATH=");\r
3394 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
3395 StringPtr ++;\r
3396 }\r
3397\r
3398 if (*StringPtr == L'\0') {\r
3399 return NULL;\r
3400 }\r
3401\r
3402 if (HasNameField) {\r
3403 //\r
3404 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.\r
3405 //\r
3406 return OffsetWidthValidate(StringPtr);\r
3407 } else {\r
3408 //\r
3409 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.\r
3410 //\r
3411 return NameValueValidate(StringPtr);\r
3412 }\r
3413}\r
3414\r
93e3992d 3415/**\r
3416 This function allows a caller to extract the current configuration\r
3417 for one or more named elements from one or more drivers.\r
3418\r
3419 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3420 instance.\r
3421 @param Request A null-terminated Unicode string in\r
3422 <MultiConfigRequest> format.\r
3423 @param Progress On return, points to a character in the Request\r
3424 string. Points to the string's null terminator if\r
3425 request was successful. Points to the most recent\r
3426 & before the first failing name / value pair (or\r
3427 the beginning of the string if the failure is in\r
3428 the first name / value pair) if the request was\r
3429 not successful.\r
3430 @param Results Null-terminated Unicode string in\r
3431 <MultiConfigAltResp> format which has all values\r
3432 filled in for the names in the Request string.\r
3433 String to be allocated by the called function.\r
3434\r
3435 @retval EFI_SUCCESS The Results string is filled with the values\r
3436 corresponding to all requested names.\r
3437 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3438 results that must be stored awaiting possible\r
3439 future protocols.\r
3440 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
3441 Progress set to the "G" in "GUID" of the routing\r
3442 header that doesn't match. Note: There is no\r
3443 requirement that all routing data be validated\r
3444 before any configuration extraction.\r
3445 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
3446 parameter would result in this type of error. The\r
3447 Progress parameter is set to NULL.\r
3448 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
3449 before the error or the beginning of the string.\r
3450 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
3451 name in question.\r
3452\r
3453**/\r
3454EFI_STATUS\r
3455EFIAPI\r
3456HiiConfigRoutingExtractConfig (\r
3457 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3458 IN CONST EFI_STRING Request,\r
3459 OUT EFI_STRING *Progress,\r
3460 OUT EFI_STRING *Results\r
3461 )\r
3462{\r
84f9a9ec 3463 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 3464 EFI_STRING StringPtr;\r
3465 EFI_STRING ConfigRequest;\r
3466 UINTN Length;\r
3467 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 3468 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 3469 EFI_STATUS Status;\r
84f9a9ec
LG
3470 LIST_ENTRY *Link;\r
3471 HII_DATABASE_RECORD *Database;\r
3472 UINT8 *DevicePathPkg;\r
3473 UINT8 *CurrentDevicePath;\r
93e3992d 3474 EFI_HANDLE DriverHandle;\r
84f9a9ec 3475 EFI_HII_HANDLE HiiHandle;\r
93e3992d 3476 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3477 EFI_STRING AccessProgress;\r
3478 EFI_STRING AccessResults;\r
84f9a9ec 3479 EFI_STRING DefaultResults;\r
8d00a0f1 3480 BOOLEAN FirstElement;\r
6e3f5b2a 3481 BOOLEAN IfrDataParsedFlag;\r
cce6230f 3482 BOOLEAN IsEfiVarStore;\r
82e8c138
ED
3483 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
3484 EFI_STRING ErrorPtr;\r
93e3992d 3485\r
3486 if (This == NULL || Progress == NULL || Results == NULL) {\r
3487 return EFI_INVALID_PARAMETER;\r
3488 }\r
3489\r
3490 if (Request == NULL) {\r
3491 *Progress = NULL;\r
3492 return EFI_INVALID_PARAMETER;\r
3493 }\r
3494\r
84f9a9ec 3495 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 3496 StringPtr = Request;\r
3497 *Progress = StringPtr;\r
84f9a9ec
LG
3498 DefaultResults = NULL;\r
3499 ConfigRequest = NULL;\r
3500 Status = EFI_SUCCESS;\r
3501 AccessResults = NULL;\r
cce6230f 3502 AccessProgress = NULL;\r
84f9a9ec 3503 DevicePath = NULL;\r
6e3f5b2a 3504 IfrDataParsedFlag = FALSE;\r
cce6230f
ED
3505 IsEfiVarStore = FALSE;\r
3506 EfiVarStoreInfo = NULL;\r
93e3992d 3507\r
3508 //\r
3509 // The first element of <MultiConfigRequest> should be\r
3510 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
3511 //\r
3512 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3513 return EFI_INVALID_PARAMETER;\r
3514 }\r
3515\r
8d00a0f1 3516 FirstElement = TRUE;\r
3517\r
93e3992d 3518 //\r
3519 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3520 // Results if this fix length is insufficient.\r
3521 //\r
3522 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3523 if (*Results == NULL) {\r
3524 return EFI_OUT_OF_RESOURCES;\r
3525 }\r
3526\r
3527 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
3528 //\r
3529 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
3530 // or most recent & before the error.\r
3531 //\r
3532 if (StringPtr == Request) {\r
3533 *Progress = StringPtr;\r
3534 } else {\r
3535 *Progress = StringPtr - 1;\r
3536 }\r
3537\r
3538 //\r
3539 // Process each <ConfigRequest> of <MultiConfigRequest>\r
3540 //\r
3541 Length = CalculateConfigStringLen (StringPtr);\r
3542 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
3543 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
3544 Status = EFI_OUT_OF_RESOURCES;\r
3545 goto Done;\r
93e3992d 3546 }\r
3547 *(ConfigRequest + Length) = 0;\r
3548\r
3549 //\r
3550 // Get the UEFI device path\r
3551 //\r
3552 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
3553 if (EFI_ERROR (Status)) {\r
84f9a9ec 3554 goto Done;\r
93e3992d 3555 }\r
3556\r
3557 //\r
84f9a9ec
LG
3558 // Find driver which matches the routing data.\r
3559 //\r
3560 DriverHandle = NULL;\r
3561 HiiHandle = NULL;\r
8567300a 3562 Database = NULL;\r
84f9a9ec
LG
3563 for (Link = Private->DatabaseList.ForwardLink;\r
3564 Link != &Private->DatabaseList;\r
3565 Link = Link->ForwardLink\r
3566 ) {\r
3567 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
3568 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3569 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 3570 if (CompareMem (\r
84f9a9ec
LG
3571 DevicePath,\r
3572 CurrentDevicePath,\r
6e3f5b2a
LG
3573 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
3574 ) == 0) {\r
84f9a9ec
LG
3575 DriverHandle = Database->DriverHandle;\r
3576 HiiHandle = Database->Handle;\r
3577 break;\r
3578 }\r
3579 }\r
3580 }\r
3581 \r
3582 //\r
3583 // Try to find driver handle by device path.\r
93e3992d 3584 //\r
84f9a9ec
LG
3585 if (DriverHandle == NULL) {\r
3586 TempDevicePath = DevicePath;\r
3587 Status = gBS->LocateDevicePath (\r
3588 &gEfiDevicePathProtocolGuid,\r
3589 &TempDevicePath,\r
3590 &DriverHandle\r
3591 );\r
3592 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
3593 //\r
3594 // Routing data does not match any known driver.\r
3595 // Set Progress to the 'G' in "GUID" of the routing header.\r
3596 //\r
3597 *Progress = StringPtr;\r
3598 Status = EFI_NOT_FOUND;\r
3599 goto Done;\r
3600 }\r
3601 }\r
82e8c138
ED
3602\r
3603 //\r
3604 // Validate ConfigRequest String.\r
3605 //\r
3606 ErrorPtr = ConfigRequestValidate(ConfigRequest);\r
3607 if (ErrorPtr != NULL) {\r
3608 *Progress = StrStr (StringPtr, ErrorPtr);\r
3609 Status = EFI_INVALID_PARAMETER;\r
3610 goto Done;\r
3611 }\r
3612\r
84f9a9ec 3613 //\r
82e8c138 3614 // Check whether ConfigRequest contains request string.\r
84f9a9ec 3615 //\r
6e3f5b2a 3616 IfrDataParsedFlag = FALSE;\r
82e8c138 3617 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {\r
93e3992d 3618 //\r
84f9a9ec 3619 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 3620 //\r
6e3f5b2a 3621 IfrDataParsedFlag = TRUE;\r
ae79d2f9 3622 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 3623 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
3624 //\r
3625 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3626 // Map it to the progress on <MultiConfigRequest> then return it.\r
3627 //\r
82e8c138 3628 ASSERT (AccessProgress != NULL);\r
ae79d2f9 3629 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
3630 goto Done;\r
3631 }\r
1f1cb2f2
LG
3632 //\r
3633 // Not any request block is found.\r
3634 //\r
82e8c138 3635 if (!GetElementsFromRequest(ConfigRequest)) {\r
76c24251 3636 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
3637 goto NextConfigString;\r
3638 }\r
93e3992d 3639 }\r
3640\r
3641 //\r
cce6230f 3642 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 3643 //\r
cce6230f
ED
3644 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
3645 if (EFI_ERROR (Status)) {\r
3646 goto Done;\r
3647 }\r
3648 \r
3649 if (IsEfiVarStore) {\r
3650 //\r
3651 // Call the GetVariable function to extract settings.\r
3652 //\r
3653 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
82e8c138 3654 FreePool (EfiVarStoreInfo);\r
cce6230f
ED
3655 } else {\r
3656 //\r
3657 // Call corresponding ConfigAccess protocol to extract settings\r
3658 //\r
3659 Status = gBS->HandleProtocol (\r
3660 DriverHandle,\r
3661 &gEfiHiiConfigAccessProtocolGuid,\r
3662 (VOID **) &ConfigAccess\r
3663 );\r
3664 ASSERT_EFI_ERROR (Status);\r
93e3992d 3665\r
cce6230f
ED
3666 Status = ConfigAccess->ExtractConfig (\r
3667 ConfigAccess,\r
3668 ConfigRequest,\r
3669 &AccessProgress,\r
3670 &AccessResults\r
3671 );\r
3672 }\r
93e3992d 3673 if (EFI_ERROR (Status)) {\r
3674 //\r
3675 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3676 // Map it to the progress on <MultiConfigRequest> then return it.\r
3677 //\r
8d00a0f1 3678 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 3679 goto Done;\r
93e3992d 3680 }\r
3681\r
3682 //\r
8d00a0f1 3683 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3684 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 3685 //\r
3686 ASSERT (*AccessProgress == 0);\r
8d00a0f1 3687\r
84f9a9ec
LG
3688 //\r
3689 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3690 //\r
ae79d2f9
LG
3691 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
3692 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3693 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 3694 }\r
ae79d2f9 3695\r
84f9a9ec
LG
3696 FreePool (DevicePath);\r
3697 DevicePath = NULL;\r
84f9a9ec 3698\r
ae79d2f9
LG
3699 if (DefaultResults != NULL) {\r
3700 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3701 ASSERT_EFI_ERROR (Status);\r
3702 FreePool (DefaultResults);\r
3703 DefaultResults = NULL;\r
3704 }\r
3705 \r
82e8c138 3706NextConfigString:\r
8d00a0f1 3707 if (!FirstElement) {\r
3708 Status = AppendToMultiString (Results, L"&");\r
3709 ASSERT_EFI_ERROR (Status);\r
3710 }\r
3711 \r
93e3992d 3712 Status = AppendToMultiString (Results, AccessResults);\r
3713 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 3714\r
3715 FirstElement = FALSE;\r
84f9a9ec 3716\r
676df92c 3717 FreePool (AccessResults);\r
93e3992d 3718 AccessResults = NULL;\r
676df92c 3719 FreePool (ConfigRequest);\r
93e3992d 3720 ConfigRequest = NULL;\r
3721\r
3722 //\r
3723 // Go to next <ConfigRequest> (skip '&').\r
3724 //\r
3725 StringPtr += Length;\r
3726 if (*StringPtr == 0) {\r
3727 *Progress = StringPtr;\r
3728 break;\r
3729 }\r
3730\r
3731 StringPtr++;\r
93e3992d 3732 }\r
3733\r
84f9a9ec
LG
3734Done:\r
3735 if (EFI_ERROR (Status)) {\r
3736 FreePool (*Results);\r
6e3f5b2a 3737 *Results = NULL;\r
84f9a9ec
LG
3738 }\r
3739 \r
3740 if (ConfigRequest != NULL) {\r
3741 FreePool (ConfigRequest);\r
3742 }\r
3743 \r
3744 if (AccessResults != NULL) {\r
3745 FreePool (AccessResults);\r
3746 }\r
3747 \r
3748 if (DefaultResults != NULL) {\r
3749 FreePool (DefaultResults);\r
3750 }\r
3751 \r
3752 if (DevicePath != NULL) {\r
3753 FreePool (DevicePath);\r
3754 } \r
93e3992d 3755\r
84f9a9ec 3756 return Status;\r
93e3992d 3757}\r
3758\r
3759\r
3760/**\r
3761 This function allows the caller to request the current configuration for the\r
3762 entirety of the current HII database and returns the data in a\r
3763 null-terminated Unicode string.\r
3764\r
3765 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3766 instance.\r
3767 @param Results Null-terminated Unicode string in\r
3768 <MultiConfigAltResp> format which has all values\r
3769 filled in for the names in the Request string.\r
3770 String to be allocated by the called function.\r
3771 De-allocation is up to the caller.\r
3772\r
3773 @retval EFI_SUCCESS The Results string is filled with the values\r
3774 corresponding to all requested names.\r
3775 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3776 results that must be stored awaiting possible\r
3777 future protocols.\r
3778 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
3779 parameter would result in this type of error.\r
3780\r
3781**/\r
3782EFI_STATUS\r
3783EFIAPI\r
3784HiiConfigRoutingExportConfig (\r
3785 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3786 OUT EFI_STRING *Results\r
3787 )\r
3788{\r
93e3992d 3789 EFI_STATUS Status;\r
93e3992d 3790 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
3791 EFI_STRING AccessResults;\r
3792 EFI_STRING Progress;\r
6e3f5b2a 3793 EFI_STRING StringPtr;\r
ae79d2f9 3794 EFI_STRING ConfigRequest;\r
8d00a0f1 3795 UINTN Index;\r
3796 EFI_HANDLE *ConfigAccessHandles;\r
3797 UINTN NumberConfigAccessHandles;\r
3798 BOOLEAN FirstElement;\r
84f9a9ec
LG
3799 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3800 EFI_HII_HANDLE HiiHandle;\r
3801 EFI_STRING DefaultResults;\r
3802 HII_DATABASE_PRIVATE_DATA *Private;\r
3803 LIST_ENTRY *Link;\r
3804 HII_DATABASE_RECORD *Database;\r
3805 UINT8 *DevicePathPkg;\r
3806 UINT8 *CurrentDevicePath;\r
ae79d2f9 3807 BOOLEAN IfrDataParsedFlag;\r
93e3992d 3808\r
3809 if (This == NULL || Results == NULL) {\r
3810 return EFI_INVALID_PARAMETER;\r
3811 }\r
3812\r
84f9a9ec
LG
3813 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3814\r
93e3992d 3815 //\r
3816 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3817 // Results if this fix length is insufficient.\r
3818 //\r
3819 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3820 if (*Results == NULL) {\r
3821 return EFI_OUT_OF_RESOURCES;\r
3822 }\r
3823\r
8d00a0f1 3824 NumberConfigAccessHandles = 0;\r
3825 Status = gBS->LocateHandleBuffer (\r
3826 ByProtocol,\r
3827 &gEfiHiiConfigAccessProtocolGuid,\r
3828 NULL,\r
3829 &NumberConfigAccessHandles,\r
3830 &ConfigAccessHandles\r
3831 );\r
3832 if (EFI_ERROR (Status)) {\r
3833 return Status;\r
3834 }\r
93e3992d 3835\r
8d00a0f1 3836 FirstElement = TRUE;\r
93e3992d 3837\r
8d00a0f1 3838 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 3839 Status = gBS->HandleProtocol (\r
8d00a0f1 3840 ConfigAccessHandles[Index],\r
93e3992d 3841 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 3842 (VOID **) &ConfigAccess\r
93e3992d 3843 );\r
8d00a0f1 3844 if (EFI_ERROR (Status)) {\r
3845 continue;\r
3846 }\r
93e3992d 3847\r
84f9a9ec
LG
3848 //\r
3849 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
3850 //\r
ae79d2f9 3851 IfrDataParsedFlag = FALSE;\r
84f9a9ec
LG
3852 Progress = NULL;\r
3853 HiiHandle = NULL;\r
84f9a9ec 3854 DefaultResults = NULL;\r
8567300a 3855 Database = NULL;\r
ae79d2f9 3856 ConfigRequest = NULL;\r
84f9a9ec 3857 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
3858 if (DevicePath != NULL) {\r
3859 for (Link = Private->DatabaseList.ForwardLink;\r
3860 Link != &Private->DatabaseList;\r
3861 Link = Link->ForwardLink\r
3862 ) {\r
3863 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3864 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3865 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 3866 if (CompareMem (\r
84f9a9ec
LG
3867 DevicePath,\r
3868 CurrentDevicePath,\r
6e3f5b2a
LG
3869 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
3870 ) == 0) {\r
84f9a9ec
LG
3871 HiiHandle = Database->Handle;\r
3872 break;\r
3873 }\r
3874 }\r
3875 }\r
3876 }\r
3877\r
93e3992d 3878 Status = ConfigAccess->ExtractConfig (\r
3879 ConfigAccess,\r
6e3f5b2a 3880 NULL,\r
84f9a9ec 3881 &Progress,\r
93e3992d 3882 &AccessResults\r
3883 );\r
ae79d2f9 3884 if (EFI_ERROR (Status)) {\r
6e3f5b2a
LG
3885 //\r
3886 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3887 //\r
3888 if (HiiHandle != NULL && DevicePath != NULL) {\r
ae79d2f9
LG
3889 IfrDataParsedFlag = TRUE;\r
3890 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3891 //\r
3892 // Get the full request string to get the Current setting again.\r
3893 //\r
3894 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
3895 Status = ConfigAccess->ExtractConfig (\r
3896 ConfigAccess,\r
3897 ConfigRequest,\r
3898 &Progress,\r
3899 &AccessResults\r
3900 );\r
3901 FreePool (ConfigRequest);\r
3902 } else {\r
3903 Status = EFI_NOT_FOUND;\r
3904 }\r
3905 }\r
3906 }\r
3907\r
3908 if (!EFI_ERROR (Status)) {\r
3909 //\r
3910 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3911 //\r
3912 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
6e3f5b2a
LG
3913 StringPtr = StrStr (AccessResults, L"&GUID=");\r
3914 if (StringPtr != NULL) {\r
3915 *StringPtr = 0;\r
3916 }\r
82e8c138 3917 if (GetElementsFromRequest (AccessResults)) {\r
ae79d2f9
LG
3918 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
3919 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a
LG
3920 }\r
3921 if (StringPtr != NULL) {\r
3922 *StringPtr = L'&';\r
3923 }\r
3924 }\r
84f9a9ec
LG
3925 //\r
3926 // Merge the default sting from IFR code into the got setting from driver.\r
3927 //\r
3928 if (DefaultResults != NULL) {\r
8567300a
LG
3929 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3930 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 3931 FreePool (DefaultResults);\r
8567300a 3932 DefaultResults = NULL;\r
84f9a9ec
LG
3933 }\r
3934 \r
8d00a0f1 3935 //\r
3936 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3937 // which seperates the first <ConfigAltResp> and the following ones. \r
3938 //\r
3939 if (!FirstElement) {\r
3940 Status = AppendToMultiString (Results, L"&");\r
3941 ASSERT_EFI_ERROR (Status);\r
676df92c 3942 }\r
8d00a0f1 3943 \r
3944 Status = AppendToMultiString (Results, AccessResults);\r
3945 ASSERT_EFI_ERROR (Status);\r
93e3992d 3946\r
8d00a0f1 3947 FirstElement = FALSE;\r
3948 \r
3949 FreePool (AccessResults);\r
3950 AccessResults = NULL;\r
3951 }\r
93e3992d 3952 }\r
f4113e1f 3953 FreePool (ConfigAccessHandles);\r
93e3992d 3954\r
8d00a0f1 3955 return EFI_SUCCESS; \r
93e3992d 3956}\r
3957\r
3958\r
3959/**\r
3960 This function processes the results of processing forms and routes it to the\r
3961 appropriate handlers or storage.\r
3962\r
3963 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3964 instance.\r
3965 @param Configuration A null-terminated Unicode string in\r
3966 <MulltiConfigResp> format.\r
3967 @param Progress A pointer to a string filled in with the offset of\r
3968 the most recent & before the first failing name /\r
3969 value pair (or the beginning of the string if the\r
3970 failure is in the first name / value pair) or the\r
3971 terminating NULL if all was successful.\r
3972\r
3973 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
3974 distribution.\r
3975 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3976 results that must be stored awaiting possible\r
3977 future protocols.\r
3978 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
3979 would result in this type of error.\r
3980 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
3981 found.\r
3982\r
3983**/\r
3984EFI_STATUS\r
3985EFIAPI\r
813acf3a 3986HiiConfigRoutingRouteConfig (\r
93e3992d 3987 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3988 IN CONST EFI_STRING Configuration,\r
3989 OUT EFI_STRING *Progress\r
3990 )\r
3991{\r
84f9a9ec 3992 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 3993 EFI_STRING StringPtr;\r
3994 EFI_STRING ConfigResp;\r
3995 UINTN Length;\r
3996 EFI_STATUS Status;\r
3997 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 3998 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
3999 LIST_ENTRY *Link;\r
4000 HII_DATABASE_RECORD *Database;\r
4001 UINT8 *DevicePathPkg;\r
4002 UINT8 *CurrentDevicePath;\r
93e3992d 4003 EFI_HANDLE DriverHandle;\r
4004 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4005 EFI_STRING AccessProgress;\r
cce6230f
ED
4006 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
4007 BOOLEAN IsEfiVarstore;\r
93e3992d 4008\r
4009 if (This == NULL || Progress == NULL) {\r
4010 return EFI_INVALID_PARAMETER;\r
4011 }\r
4012\r
4013 if (Configuration == NULL) {\r
4014 *Progress = NULL;\r
4015 return EFI_INVALID_PARAMETER;\r
4016 }\r
4017\r
84f9a9ec 4018 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 4019 StringPtr = Configuration;\r
4020 *Progress = StringPtr;\r
cce6230f
ED
4021 Database = NULL;\r
4022 AccessProgress = NULL;\r
4023 EfiVarStoreInfo= NULL;\r
4024 IsEfiVarstore = FALSE;\r
93e3992d 4025\r
4026 //\r
4027 // The first element of <MultiConfigResp> should be\r
4028 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
4029 //\r
4030 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4031 return EFI_INVALID_PARAMETER;\r
4032 }\r
4033\r
4034 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
4035 //\r
4036 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
4037 // or most recent & before the error.\r
4038 //\r
4039 if (StringPtr == Configuration) {\r
4040 *Progress = StringPtr;\r
4041 } else {\r
4042 *Progress = StringPtr - 1;\r
4043 }\r
4044\r
4045 //\r
4046 // Process each <ConfigResp> of <MultiConfigResp>\r
4047 //\r
4048 Length = CalculateConfigStringLen (StringPtr);\r
4049 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
4050 if (ConfigResp == NULL) {\r
4051 return EFI_OUT_OF_RESOURCES;\r
4052 }\r
4053 //\r
4054 // Append '\0' to the end of ConfigRequest\r
4055 //\r
4056 *(ConfigResp + Length) = 0;\r
4057\r
4058 //\r
4059 // Get the UEFI device path\r
4060 //\r
4061 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
4062 if (EFI_ERROR (Status)) {\r
676df92c 4063 FreePool (ConfigResp);\r
93e3992d 4064 return Status;\r
4065 }\r
4066\r
4067 //\r
84f9a9ec
LG
4068 // Find driver which matches the routing data.\r
4069 //\r
4070 DriverHandle = NULL;\r
84f9a9ec
LG
4071 for (Link = Private->DatabaseList.ForwardLink;\r
4072 Link != &Private->DatabaseList;\r
4073 Link = Link->ForwardLink\r
4074 ) {\r
4075 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4076\r
4077 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4078 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 4079 if (CompareMem (\r
84f9a9ec
LG
4080 DevicePath,\r
4081 CurrentDevicePath,\r
6e3f5b2a
LG
4082 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
4083 ) == 0) {\r
84f9a9ec
LG
4084 DriverHandle = Database->DriverHandle;\r
4085 break;\r
4086 }\r
4087 }\r
4088 }\r
93e3992d 4089\r
84f9a9ec
LG
4090 //\r
4091 // Try to find driver handle by device path.\r
4092 //\r
4093 if (DriverHandle == NULL) {\r
4094 TempDevicePath = DevicePath;\r
4095 Status = gBS->LocateDevicePath (\r
4096 &gEfiDevicePathProtocolGuid,\r
4097 &TempDevicePath,\r
4098 &DriverHandle\r
4099 );\r
4100 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
4101 //\r
4102 // Routing data does not match any known driver.\r
4103 // Set Progress to the 'G' in "GUID" of the routing header.\r
4104 //\r
4105 FreePool (DevicePath);\r
4106 *Progress = StringPtr;\r
4107 FreePool (ConfigResp);\r
4108 return EFI_NOT_FOUND;\r
4109 }\r
93e3992d 4110 }\r
4111\r
84f9a9ec
LG
4112 FreePool (DevicePath);\r
4113\r
93e3992d 4114 //\r
cce6230f 4115 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 4116 //\r
cce6230f
ED
4117 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
4118 if (EFI_ERROR (Status)) {\r
4119 return Status;\r
4120 }\r
93e3992d 4121\r
cce6230f
ED
4122 if (IsEfiVarstore) {\r
4123 //\r
4124 // Call the SetVariable function to route settings.\r
4125 // \r
4126 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
4127 FreePool (EfiVarStoreInfo);\r
4128 } else {\r
4129 //\r
4130 // Call corresponding ConfigAccess protocol to route settings\r
4131 //\r
4132 Status = gBS->HandleProtocol (\r
4133 DriverHandle,\r
4134 &gEfiHiiConfigAccessProtocolGuid,\r
4135 (VOID **) &ConfigAccess\r
4136 );\r
4137 ASSERT_EFI_ERROR (Status);\r
93e3992d 4138\r
cce6230f
ED
4139 Status = ConfigAccess->RouteConfig (\r
4140 ConfigAccess,\r
4141 ConfigResp,\r
4142 &AccessProgress\r
4143 );\r
4144 }\r
93e3992d 4145 if (EFI_ERROR (Status)) {\r
4146 //\r
4147 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
4148 // Map it to the progress on <MultiConfigResp> then return it.\r
4149 //\r
8d00a0f1 4150 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 4151\r
676df92c 4152 FreePool (ConfigResp);\r
93e3992d 4153 return Status;\r
4154 }\r
4155\r
676df92c 4156 FreePool (ConfigResp);\r
93e3992d 4157 ConfigResp = NULL;\r
4158\r
4159 //\r
4160 // Go to next <ConfigResp> (skip '&').\r
4161 //\r
4162 StringPtr += Length;\r
4163 if (*StringPtr == 0) {\r
4164 *Progress = StringPtr;\r
4165 break;\r
4166 }\r
4167\r
4168 StringPtr++;\r
4169\r
4170 }\r
4171\r
4172 return EFI_SUCCESS;\r
93e3992d 4173}\r
4174\r
4175\r
4176/**\r
4177 This helper function is to be called by drivers to map configuration data\r
4178 stored in byte array ("block") formats such as UEFI Variables into current\r
4179 configuration strings.\r
4180\r
4181 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4182 instance.\r
4183 @param ConfigRequest A null-terminated Unicode string in\r
4184 <ConfigRequest> format.\r
4185 @param Block Array of bytes defining the block's configuration.\r
4186 @param BlockSize Length in bytes of Block.\r
4187 @param Config Filled-in configuration string. String allocated\r
4188 by the function. Returned only if call is\r
84f9a9ec 4189 successful. It is <ConfigResp> string format.\r
93e3992d 4190 @param Progress A pointer to a string filled in with the offset of\r
4191 the most recent & before the first failing\r
4192 name/value pair (or the beginning of the string if\r
4193 the failure is in the first name / value pair) or\r
4194 the terminating NULL if all was successful.\r
4195\r
4196 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4197 terminator at the end of the ConfigRequest\r
4198 string.\r
4199 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4200 points to the first character of ConfigRequest.\r
4201 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
4202 Block parameter would result in this type of\r
4203 error. Progress points to the first character of\r
4204 ConfigRequest.\r
4205 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
4206 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
4207 Block is left updated and Progress points at\r
4208 the "&" preceding the first non-<BlockName>.\r
4209\r
4210**/\r
4211EFI_STATUS\r
4212EFIAPI\r
4213HiiBlockToConfig (\r
4214 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4215 IN CONST EFI_STRING ConfigRequest,\r
4216 IN CONST UINT8 *Block,\r
4217 IN CONST UINTN BlockSize,\r
4218 OUT EFI_STRING *Config,\r
4219 OUT EFI_STRING *Progress\r
4220 )\r
4221{\r
84f9a9ec 4222 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 4223 EFI_STRING StringPtr;\r
4224 UINTN Length;\r
4225 EFI_STATUS Status;\r
4226 EFI_STRING TmpPtr;\r
4227 UINT8 *TmpBuffer;\r
4228 UINTN Offset;\r
4229 UINTN Width;\r
4230 UINT8 *Value;\r
4231 EFI_STRING ValueStr;\r
4232 EFI_STRING ConfigElement;\r
63d55bb9
LG
4233 UINTN Index;\r
4234 UINT8 *TemBuffer;\r
4235 CHAR16 *TemString;\r
41ff10dc 4236 CHAR16 TemChar;\r
93e3992d 4237\r
4238 if (This == NULL || Progress == NULL || Config == NULL) {\r
4239 return EFI_INVALID_PARAMETER;\r
4240 }\r
4241\r
4242 if (Block == NULL || ConfigRequest == NULL) {\r
4243 *Progress = ConfigRequest;\r
4244 return EFI_INVALID_PARAMETER;\r
4245 }\r
4246\r
84f9a9ec
LG
4247\r
4248 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4249 ASSERT (Private != NULL);\r
4250\r
93e3992d 4251 StringPtr = ConfigRequest;\r
4252 ValueStr = NULL;\r
4253 Value = NULL;\r
4254 ConfigElement = NULL;\r
4255\r
4256 //\r
4257 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4258 // Results if this fix length is insufficient.\r
4259 //\r
4260 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
4261 if (*Config == NULL) {\r
4262 return EFI_OUT_OF_RESOURCES;\r
4263 }\r
4264\r
4265 //\r
4266 // Jump <ConfigHdr>\r
4267 //\r
4268 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4269 *Progress = StringPtr;\r
4270 Status = EFI_INVALID_PARAMETER;\r
4271 goto Exit;\r
4272 }\r
4273 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4274 StringPtr++;\r
4275 }\r
4276 if (*StringPtr == 0) {\r
76c24251 4277 *Progress = StringPtr - 1;\r
93e3992d 4278 Status = EFI_INVALID_PARAMETER;\r
4279 goto Exit;\r
4280 }\r
08e6463a 4281\r
4282 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4283 StringPtr++;\r
4284 }\r
4285 if (*StringPtr == 0) {\r
41ff10dc
ED
4286 *Progress = StringPtr;\r
4287 Status = EFI_SUCCESS;\r
4288\r
4289 AppendToMultiString(Config, ConfigRequest);\r
4290 HiiToLower (*Config);\r
4291\r
08e6463a 4292 goto Exit;\r
4293 }\r
4294 //\r
4295 // Skip '&'\r
4296 //\r
4297 StringPtr++;\r
93e3992d 4298\r
4299 //\r
4300 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
4301 //\r
41ff10dc
ED
4302 TemChar = *StringPtr;\r
4303 *StringPtr = '\0';\r
4304 AppendToMultiString(Config, ConfigRequest);\r
4305 *StringPtr = TemChar;\r
93e3992d 4306\r
4307 //\r
4308 // Parse each <RequestElement> if exists\r
4309 // Only <BlockName> format is supported by this help function.\r
4310 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
4311 //\r
4312 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
4313 //\r
4314 // Back up the header of one <BlockName>\r
4315 //\r
4316 TmpPtr = StringPtr;\r
4317\r
4318 StringPtr += StrLen (L"OFFSET=");\r
4319 //\r
4320 // Get Offset\r
4321 //\r
4322 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4323 if (EFI_ERROR (Status)) {\r
93e3992d 4324 *Progress = ConfigRequest;\r
4325 goto Exit;\r
4326 }\r
4327 Offset = 0;\r
4328 CopyMem (\r
4329 &Offset,\r
4330 TmpBuffer,\r
4331 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4332 );\r
676df92c 4333 FreePool (TmpBuffer);\r
93e3992d 4334\r
4335 StringPtr += Length;\r
4336 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
4337 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
4338 Status = EFI_INVALID_PARAMETER;\r
4339 goto Exit;\r
4340 }\r
4341 StringPtr += StrLen (L"&WIDTH=");\r
4342\r
4343 //\r
4344 // Get Width\r
4345 //\r
4346 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4347 if (EFI_ERROR (Status)) {\r
93e3992d 4348 *Progress = ConfigRequest;\r
4349 goto Exit;\r
4350 }\r
4351 Width = 0;\r
4352 CopyMem (\r
4353 &Width,\r
4354 TmpBuffer,\r
4355 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4356 );\r
676df92c 4357 FreePool (TmpBuffer);\r
93e3992d 4358\r
4359 StringPtr += Length;\r
4360 if (*StringPtr != 0 && *StringPtr != L'&') {\r
4361 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
4362 Status = EFI_INVALID_PARAMETER;\r
4363 goto Exit;\r
4364 }\r
4365\r
4366 //\r
4367 // Calculate Value and convert it to hex string.\r
4368 //\r
4369 if (Offset + Width > BlockSize) {\r
4370 *Progress = StringPtr;\r
4371 Status = EFI_DEVICE_ERROR;\r
4372 goto Exit;\r
4373 }\r
4374\r
4375 Value = (UINT8 *) AllocateZeroPool (Width);\r
4376 if (Value == NULL) {\r
4377 *Progress = ConfigRequest;\r
4378 Status = EFI_OUT_OF_RESOURCES;\r
4379 goto Exit;\r
4380 }\r
4381\r
4382 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
4383\r
4384 Length = Width * 2 + 1;\r
4385 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4386 if (ValueStr == NULL) {\r
4387 *Progress = ConfigRequest;\r
4388 Status = EFI_OUT_OF_RESOURCES;\r
4389 goto Exit;\r
4390 }\r
63d55bb9
LG
4391 \r
4392 TemString = ValueStr;\r
4393 TemBuffer = Value + Width - 1;\r
4394 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
4395 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
4396 }\r
813acf3a 4397\r
676df92c 4398 FreePool (Value);\r
93e3992d 4399 Value = NULL;\r
4400\r
4401 //\r
4402 // Build a ConfigElement\r
4403 //\r
4404 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
4405 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4406 if (ConfigElement == NULL) {\r
4407 Status = EFI_OUT_OF_RESOURCES;\r
4408 goto Exit;\r
4409 }\r
4410 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
4411 if (*StringPtr == 0) {\r
4412 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
4413 }\r
4414 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
4415 StrCat (ConfigElement, L"VALUE=");\r
4416 StrCat (ConfigElement, ValueStr);\r
4417\r
4418 AppendToMultiString (Config, ConfigElement);\r
4419\r
676df92c 4420 FreePool (ConfigElement);\r
4421 FreePool (ValueStr);\r
93e3992d 4422 ConfigElement = NULL;\r
4423 ValueStr = NULL;\r
4424\r
4425 //\r
4426 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
4427 //\r
4428 if (*StringPtr == 0) {\r
4429 break;\r
4430 }\r
4431 AppendToMultiString (Config, L"&");\r
4432 StringPtr++;\r
4433\r
4434 }\r
4435\r
4436 if (*StringPtr != 0) {\r
4437 *Progress = StringPtr - 1;\r
4438 Status = EFI_INVALID_PARAMETER;\r
4439 goto Exit;\r
4440 }\r
84f9a9ec
LG
4441 \r
4442 HiiToLower (*Config);\r
93e3992d 4443 *Progress = StringPtr;\r
4444 return EFI_SUCCESS;\r
4445\r
4446Exit:\r
76c24251 4447 if (*Config != NULL) {\r
1f1cb2f2
LG
4448 FreePool (*Config);\r
4449 *Config = NULL;\r
76c24251 4450 }\r
676df92c 4451 if (ValueStr != NULL) {\r
4452 FreePool (ValueStr);\r
4453 }\r
4454 if (Value != NULL) {\r
4455 FreePool (Value);\r
4456 }\r
69367b5b 4457 if (ConfigElement != NULL) {\r
676df92c 4458 FreePool (ConfigElement);\r
4459 }\r
93e3992d 4460\r
4461 return Status;\r
4462\r
4463}\r
4464\r
4465\r
4466/**\r
4467 This helper function is to be called by drivers to map configuration strings\r
4468 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
4469\r
4470 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4471 instance.\r
4472 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
771ececd 4473 format.\r
93e3992d 4474 @param Block A possibly null array of bytes representing the\r
4475 current block. Only bytes referenced in the\r
4476 ConfigResp string in the block are modified. If\r
4477 this parameter is null or if the *BlockSize\r
4478 parameter is (on input) shorter than required by\r
4479 the Configuration string, only the BlockSize\r
4480 parameter is updated and an appropriate status\r
4481 (see below) is returned.\r
4482 @param BlockSize The length of the Block in units of UINT8. On\r
4483 input, this is the size of the Block. On output,\r
4484 if successful, contains the index of the last\r
4485 modified byte in the Block.\r
4486 @param Progress On return, points to an element of the ConfigResp\r
4487 string filled in with the offset of the most\r
4488 recent '&' before the first failing name / value\r
4489 pair (or the beginning of the string if the\r
4490 failure is in the first name / value pair) or the\r
4491 terminating NULL if all was successful.\r
4492\r
4493 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4494 terminator at the end of the ConfigResp string.\r
4495 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4496 points to the first character of ConfigResp.\r
4497 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
4498 Block parameter would result in this type of\r
4499 error. Progress points to the first character of\r
4500 ConfigResp.\r
4501 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
4502 value pair. Block is left updated and\r
4503 Progress points at the '&' preceding the first\r
4504 non-<BlockName>.\r
09b79417
LG
4505 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
4506 @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
4507 Progress points to the "G" in "GUID" of the errant\r
4508 routing data.\r
93e3992d 4509\r
4510**/\r
4511EFI_STATUS\r
4512EFIAPI\r
4513HiiConfigToBlock (\r
4514 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4515 IN CONST EFI_STRING ConfigResp,\r
4516 IN OUT UINT8 *Block,\r
4517 IN OUT UINTN *BlockSize,\r
4518 OUT EFI_STRING *Progress\r
4519 )\r
4520{\r
4521 HII_DATABASE_PRIVATE_DATA *Private;\r
4522 EFI_STRING StringPtr;\r
4523 UINTN Length;\r
4524 EFI_STATUS Status;\r
4525 UINT8 *TmpBuffer;\r
4526 UINTN Offset;\r
4527 UINTN Width;\r
4528 UINT8 *Value;\r
4529 UINTN BufferSize;\r
09b79417 4530 UINTN MaxBlockSize;\r
93e3992d 4531\r
4532 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
4533 return EFI_INVALID_PARAMETER;\r
4534 }\r
4535\r
09b79417
LG
4536 *Progress = ConfigResp;\r
4537 if (ConfigResp == NULL) {\r
93e3992d 4538 return EFI_INVALID_PARAMETER;\r
4539 }\r
4540\r
4541 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4542 ASSERT (Private != NULL);\r
4543\r
4544 StringPtr = ConfigResp;\r
4545 BufferSize = *BlockSize;\r
4546 Value = NULL;\r
09b79417 4547 MaxBlockSize = 0;\r
93e3992d 4548\r
4549 //\r
4550 // Jump <ConfigHdr>\r
4551 //\r
4552 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4553 *Progress = StringPtr;\r
4554 Status = EFI_INVALID_PARAMETER;\r
4555 goto Exit;\r
4556 }\r
4557 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4558 StringPtr++;\r
4559 }\r
4560 if (*StringPtr == 0) {\r
4561 *Progress = StringPtr;\r
4562 Status = EFI_INVALID_PARAMETER;\r
4563 goto Exit;\r
4564 }\r
08e6463a 4565\r
4566 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4567 StringPtr++;\r
4568 }\r
4569 if (*StringPtr == 0) {\r
4570 *Progress = StringPtr;\r
4571 Status = EFI_INVALID_PARAMETER;\r
4572 goto Exit;\r
4573 }\r
93e3992d 4574\r
4575 //\r
4576 // Parse each <ConfigElement> if exists\r
edae8d2d 4577 // Only '&'<BlockConfig> format is supported by this help function.\r
93e3992d 4578 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
4579 //\r
edae8d2d
ED
4580 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
4581 StringPtr += StrLen (L"&OFFSET=");\r
93e3992d 4582 //\r
4583 // Get Offset\r
4584 //\r
4585 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 4586 if (EFI_ERROR (Status)) {\r
93e3992d 4587 *Progress = ConfigResp;\r
4588 goto Exit;\r
4589 }\r
4590 Offset = 0;\r
4591 CopyMem (\r
4592 &Offset,\r
4593 TmpBuffer,\r
4594 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4595 );\r
676df92c 4596 FreePool (TmpBuffer);\r
93e3992d 4597\r
4598 StringPtr += Length;\r
4599 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
edae8d2d 4600 *Progress = StringPtr - Length - StrLen (L"&OFFSET=");\r
93e3992d 4601 Status = EFI_INVALID_PARAMETER;\r
4602 goto Exit;\r
4603 }\r
4604 StringPtr += StrLen (L"&WIDTH=");\r
4605\r
4606 //\r
4607 // Get Width\r
4608 //\r
4609 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4610 if (EFI_ERROR (Status)) {\r
93e3992d 4611 *Progress = ConfigResp;\r
4612 goto Exit;\r
4613 }\r
4614 Width = 0;\r
4615 CopyMem (\r
4616 &Width,\r
4617 TmpBuffer,\r
4618 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4619 );\r
676df92c 4620 FreePool (TmpBuffer);\r
93e3992d 4621\r
4622 StringPtr += Length;\r
4623 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
4624 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
4625 Status = EFI_INVALID_PARAMETER;\r
4626 goto Exit;\r
4627 }\r
4628 StringPtr += StrLen (L"&VALUE=");\r
4629\r
4630 //\r
4631 // Get Value\r
4632 //\r
4633 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 4634 if (EFI_ERROR (Status)) {\r
93e3992d 4635 *Progress = ConfigResp;\r
4636 goto Exit;\r
4637 }\r
4638\r
4639 StringPtr += Length;\r
4640 if (*StringPtr != 0 && *StringPtr != L'&') {\r
edae8d2d 4641 *Progress = StringPtr - Length - StrLen (L"&VALUE=");\r
93e3992d 4642 Status = EFI_INVALID_PARAMETER;\r
4643 goto Exit;\r
4644 }\r
4645\r
4646 //\r
4647 // Update the Block with configuration info\r
4648 //\r
09b79417
LG
4649 if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
4650 CopyMem (Block + Offset, Value, Width);\r
4651 }\r
4652 if (Offset + Width > MaxBlockSize) {\r
4653 MaxBlockSize = Offset + Width;\r
93e3992d 4654 }\r
93e3992d 4655\r
676df92c 4656 FreePool (Value);\r
93e3992d 4657 Value = NULL;\r
4658\r
4659 //\r
edae8d2d 4660 // If '\0', parsing is finished.\r
93e3992d 4661 //\r
4662 if (*StringPtr == 0) {\r
4663 break;\r
4664 }\r
93e3992d 4665 }\r
84f9a9ec
LG
4666 \r
4667 //\r
edae8d2d 4668 // The input string is not ConfigResp format, return error.\r
84f9a9ec 4669 //\r
edae8d2d
ED
4670 if (*StringPtr != 0) {\r
4671 *Progress = StringPtr;\r
93e3992d 4672 Status = EFI_INVALID_PARAMETER;\r
4673 goto Exit;\r
4674 }\r
4675\r
6e3f5b2a 4676 *Progress = StringPtr + StrLen (StringPtr);\r
09b79417
LG
4677 *BlockSize = MaxBlockSize - 1;\r
4678\r
4679 if (MaxBlockSize > BufferSize) {\r
4680 *BlockSize = MaxBlockSize;\r
9ac0640d 4681 if (Block != NULL) {\r
09b79417
LG
4682 return EFI_DEVICE_ERROR;\r
4683 }\r
4684 }\r
4685\r
9ac0640d
LG
4686 if (Block == NULL) {\r
4687 *Progress = ConfigResp;\r
4688 return EFI_INVALID_PARAMETER;\r
4689 }\r
4690\r
93e3992d 4691 return EFI_SUCCESS;\r
4692\r
4693Exit:\r
4694\r
676df92c 4695 if (Value != NULL) {\r
4696 FreePool (Value);\r
4697 }\r
93e3992d 4698 return Status;\r
4699}\r
4700\r
4701\r
4702/**\r
4703 This helper function is to be called by drivers to extract portions of\r
4704 a larger configuration string.\r
4705\r
4706 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4707 instance.\r
4708 @param Configuration A null-terminated Unicode string in\r
771ececd 4709 <MultiConfigAltResp> format.\r
93e3992d 4710 @param Guid A pointer to the GUID value to search for in the\r
4711 routing portion of the ConfigResp string when\r
4712 retrieving the requested data. If Guid is NULL,\r
4713 then all GUID values will be searched for.\r
4714 @param Name A pointer to the NAME value to search for in the\r
4715 routing portion of the ConfigResp string when\r
4716 retrieving the requested data. If Name is NULL,\r
4717 then all Name values will be searched for.\r
4718 @param DevicePath A pointer to the PATH value to search for in the\r
4719 routing portion of the ConfigResp string when\r
4720 retrieving the requested data. If DevicePath is\r
4721 NULL, then all DevicePath values will be searched\r
4722 for.\r
4723 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
4724 routing portion of the ConfigResp string when\r
4725 retrieving the requested data. If this parameter\r
4726 is NULL, then the current setting will be\r
4727 retrieved.\r
4728 @param AltCfgResp A pointer to a buffer which will be allocated by\r
4729 the function which contains the retrieved string\r
4730 as requested. This buffer is only allocated if\r
84f9a9ec 4731 the call was successful. It is <ConfigResp> format.\r
93e3992d 4732\r
4733 @retval EFI_SUCCESS The request succeeded. The requested data was\r
4734 extracted and placed in the newly allocated\r
4735 AltCfgResp buffer.\r
4736 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
4737 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
4738 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
4739 found.\r
4740\r
4741**/\r
4742EFI_STATUS\r
4743EFIAPI\r
4744HiiGetAltCfg (\r
4745 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4746 IN CONST EFI_STRING Configuration,\r
4747 IN CONST EFI_GUID *Guid,\r
4748 IN CONST EFI_STRING Name,\r
4749 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
4750 IN CONST UINT16 *AltCfgId,\r
4751 OUT EFI_STRING *AltCfgResp\r
4752 )\r
4753{\r
93e3992d 4754 EFI_STATUS Status;\r
4755 EFI_STRING StringPtr;\r
e90b081a 4756 EFI_STRING HdrStart;\r
4757 EFI_STRING HdrEnd;\r
93e3992d 4758 EFI_STRING TmpPtr;\r
4759 UINTN Length;\r
e90b081a 4760 EFI_STRING GuidStr;\r
4761 EFI_STRING NameStr;\r
4762 EFI_STRING PathStr;\r
4763 EFI_STRING AltIdStr;\r
4764 EFI_STRING Result;\r
4765 BOOLEAN GuidFlag;\r
4766 BOOLEAN NameFlag;\r
4767 BOOLEAN PathFlag;\r
4768\r
4769 HdrStart = NULL;\r
4770 HdrEnd = NULL;\r
4771 GuidStr = NULL;\r
4772 NameStr = NULL;\r
4773 PathStr = NULL;\r
4774 AltIdStr = NULL;\r
4775 Result = NULL;\r
4776 GuidFlag = FALSE;\r
4777 NameFlag = FALSE;\r
4778 PathFlag = FALSE;\r
93e3992d 4779\r
4780 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
4781 return EFI_INVALID_PARAMETER;\r
4782 }\r
4783\r
4784 StringPtr = Configuration;\r
4785 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4786 return EFI_INVALID_PARAMETER;\r
4787 }\r
4788\r
4789 //\r
4790 // Generate the sub string for later matching.\r
4791 //\r
813acf3a 4792 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 4793 GenerateSubStr (\r
4794 L"PATH=",\r
4795 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 4796 (VOID *) DevicePath,\r
4797 1,\r
93e3992d 4798 &PathStr\r
4799 );\r
4800 if (AltCfgId != NULL) {\r
813acf3a 4801 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 4802 }\r
4803 if (Name != NULL) {\r
813acf3a 4804 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 4805 } else {\r
813acf3a 4806 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 4807 }\r
4808\r
4809 while (*StringPtr != 0) {\r
4810 //\r
4811 // Try to match the GUID\r
4812 //\r
4813 if (!GuidFlag) {\r
4814 TmpPtr = StrStr (StringPtr, GuidStr);\r
4815 if (TmpPtr == NULL) {\r
4816 Status = EFI_NOT_FOUND;\r
4817 goto Exit;\r
4818 }\r
4819 HdrStart = TmpPtr;\r
4820\r
4821 //\r
4822 // Jump to <NameHdr>\r
4823 //\r
4824 if (Guid != NULL) {\r
4825 StringPtr = TmpPtr + StrLen (GuidStr);\r
4826 } else {\r
4827 StringPtr = StrStr (TmpPtr, L"NAME=");\r
4828 if (StringPtr == NULL) {\r
4829 Status = EFI_NOT_FOUND;\r
4830 goto Exit;\r
4831 }\r
4832 }\r
4833 GuidFlag = TRUE;\r
4834 }\r
4835\r
4836 //\r
4837 // Try to match the NAME\r
4838 //\r
4839 if (GuidFlag && !NameFlag) {\r
4840 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
4841 GuidFlag = FALSE;\r
4842 } else {\r
4843 //\r
4844 // Jump to <PathHdr>\r
4845 //\r
4846 if (Name != NULL) {\r
4847 StringPtr += StrLen (NameStr);\r
4848 } else {\r
4849 StringPtr = StrStr (StringPtr, L"PATH=");\r
4850 if (StringPtr == NULL) {\r
4851 Status = EFI_NOT_FOUND;\r
4852 goto Exit;\r
4853 }\r
4854 }\r
4855 NameFlag = TRUE;\r
4856 }\r
4857 }\r
4858\r
4859 //\r
4860 // Try to match the DevicePath\r
4861 //\r
4862 if (GuidFlag && NameFlag && !PathFlag) {\r
4863 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
4864 GuidFlag = FALSE;\r
4865 NameFlag = FALSE;\r
4866 } else {\r
4867 //\r
4868 // Jump to '&' before <DescHdr> or <ConfigBody>\r
4869 //\r
4870 if (DevicePath != NULL) {\r
4871 StringPtr += StrLen (PathStr);\r
4872 } else {\r
4873 StringPtr = StrStr (StringPtr, L"&");\r
4874 if (StringPtr == NULL) {\r
4875 Status = EFI_NOT_FOUND;\r
4876 goto Exit;\r
4877 }\r
84f9a9ec 4878 StringPtr ++;\r
93e3992d 4879 }\r
4880 PathFlag = TRUE;\r
84f9a9ec 4881 HdrEnd = StringPtr;\r
93e3992d 4882 }\r
4883 }\r
4884\r
4885 //\r
4886 // Try to match the AltCfgId\r
4887 //\r
4888 if (GuidFlag && NameFlag && PathFlag) {\r
4889 if (AltCfgId == NULL) {\r
4890 //\r
4891 // Return Current Setting when AltCfgId is NULL.\r
4892 //\r
4893 Status = OutputConfigBody (StringPtr, &Result);\r
4894 goto Exit;\r
4895 }\r
4896 //\r
4897 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
4898 //\r
4899 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
4900 GuidFlag = FALSE;\r
4901 NameFlag = FALSE;\r
4902 PathFlag = FALSE;\r
4903 } else {\r
84f9a9ec
LG
4904 //\r
4905 // Skip AltIdStr and &\r
4906 //\r
4907 StringPtr = StringPtr + StrLen (AltIdStr);\r
4908 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 4909 goto Exit;\r
4910 }\r
4911 }\r
4912 }\r
4913\r
4914 Status = EFI_NOT_FOUND;\r
4915\r
4916Exit:\r
76c24251 4917 *AltCfgResp = NULL;\r
bc166db3 4918 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 4919 //\r
4920 // Copy the <ConfigHdr> and <ConfigBody>\r
4921 //\r
84f9a9ec 4922 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 4923 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
4924 if (*AltCfgResp == NULL) {\r
4925 Status = EFI_OUT_OF_RESOURCES;\r
4926 } else {\r
4927 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
4928 StrCat (*AltCfgResp, Result);\r
4929 Status = EFI_SUCCESS;\r
4930 }\r
4931 }\r
4932\r
676df92c 4933 if (GuidStr != NULL) {\r
4934 FreePool (GuidStr);\r
4935 }\r
4936 if (NameStr != NULL) {\r
4937 FreePool (NameStr);\r
4938 }\r
4939 if (PathStr != NULL) {\r
4940 FreePool (PathStr);\r
4941 }\r
4942 if (AltIdStr != NULL) {\r
4943 FreePool (AltIdStr);\r
4944 }\r
4945 if (Result != NULL) {\r
4946 FreePool (Result);\r
4947 }\r
93e3992d 4948\r
4949 return Status;\r
4950\r
93e3992d 4951}\r
4952\r
36fe40c2 4953\r