]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
Fix GCC build fail.
[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
LG
1432 IFR_BLOCK_DATA *BlockData;\r
1433 CHAR16 *VarStoreName;\r
84f9a9ec 1434 UINT16 VarWidth;\r
84f9a9ec
LG
1435 UINT16 VarDefaultId;\r
1436 EFI_STRING GuidStr;\r
1437 EFI_STRING NameStr;\r
1438 EFI_STRING TempStr;\r
1439 UINTN LengthString;\r
cf4c5a42 1440 BOOLEAN FirstOneOfOption;\r
ef40f0f6
ED
1441 LIST_ENTRY *LinkData;\r
1442 LIST_ENTRY *LinkDefault;\r
82e8c138 1443 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
84f9a9ec 1444\r
84f9a9ec
LG
1445 LengthString = 0;\r
1446 Status = EFI_SUCCESS;\r
1447 GuidStr = NULL;\r
1448 NameStr = NULL;\r
1449 TempStr = NULL;\r
1450 BlockData = NULL;\r
ef40f0f6 1451 DefaultDataPtr = NULL;\r
cf4c5a42 1452 FirstOneOfOption = FALSE;\r
ef40f0f6 1453 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
84f9a9ec
LG
1454\r
1455 //\r
1456 // Go through the form package to parse OpCode one by one.\r
1457 //\r
1458 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
aa75dfec 1459 while (IfrOffset < PackageLength) {\r
84f9a9ec 1460 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
84f9a9ec
LG
1461 switch (IfrOpHdr->OpCode) {\r
1462 case EFI_IFR_VARSTORE_OP:\r
1463 //\r
1464 // VarStore is found. Don't need to search any more.\r
1465 //\r
82e8c138 1466 if (VarStorageData->VarStoreId != 0) {\r
84f9a9ec
LG
1467 break;\r
1468 }\r
1469\r
84f9a9ec 1470 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
82e8c138 1471\r
f8920f0d 1472 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
84f9a9ec
LG
1473 if (VarStoreName == NULL) {\r
1474 Status = EFI_OUT_OF_RESOURCES;\r
1475 goto Done;\r
1476 }\r
f8920f0d 1477 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);\r
84f9a9ec 1478\r
82e8c138 1479 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
84f9a9ec
LG
1480 //\r
1481 // Find the matched VarStore\r
1482 //\r
1483 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
1484 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
1485 VarStorageData->Size = IfrVarStore->Size;\r
1486 VarStorageData->Name = VarStoreName;\r
82e8c138 1487 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;\r
84f9a9ec 1488 }\r
84f9a9ec
LG
1489 break;\r
1490\r
cce6230f
ED
1491 case EFI_IFR_VARSTORE_EFI_OP:\r
1492 //\r
1493 // VarStore is found. Don't need to search any more.\r
1494 //\r
82e8c138 1495 if (VarStorageData->VarStoreId != 0) {\r
cce6230f
ED
1496 break;\r
1497 }\r
1498\r
cce6230f
ED
1499 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1500\r
1501 //\r
1502 // If the length is small than the structure, this is from old efi \r
1503 // varstore definition. Old efi varstore get config directly from \r
1504 // GetVariable function.\r
1505 // \r
1506 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
1507 break;\r
1508 }\r
1509\r
f8920f0d 1510 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
cce6230f
ED
1511 if (VarStoreName == NULL) {\r
1512 Status = EFI_OUT_OF_RESOURCES;\r
1513 goto Done;\r
1514 }\r
f8920f0d 1515 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);\r
cce6230f 1516\r
82e8c138 1517 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
cce6230f
ED
1518 //\r
1519 // Find the matched VarStore\r
1520 //\r
1521 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);\r
1522 VarStorageData->VarStoreId = IfrEfiVarStore->VarStoreId;\r
1523 VarStorageData->Size = IfrEfiVarStore->Size;\r
1524 VarStorageData->Name = VarStoreName;\r
82e8c138 1525 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;\r
cce6230f 1526 }\r
cce6230f
ED
1527 break;\r
1528\r
82e8c138 1529 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
84f9a9ec 1530 //\r
82e8c138
ED
1531 // VarStore is found. Don't need to search any more.\r
1532 //\r
1533 if (VarStorageData->VarStoreId != 0) {\r
1534 break;\r
1535 }\r
1536\r
1537 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
1538\r
1539 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
1540 //\r
1541 // Find the matched VarStore\r
1542 //\r
1543 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);\r
1544 VarStorageData->VarStoreId = IfrNameValueVarStore->VarStoreId;\r
1545 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
1546 }\r
1547 break;\r
1548\r
1549 case EFI_IFR_DEFAULTSTORE_OP:\r
1550 //\r
1551 // Add new the map between default id and default name.\r
84f9a9ec 1552 //\r
ef40f0f6
ED
1553 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1554 if (DefaultDataPtr == NULL) {\r
84f9a9ec
LG
1555 Status = EFI_OUT_OF_RESOURCES;\r
1556 goto Done;\r
1557 }\r
ef40f0f6
ED
1558 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
1559 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
1560 DefaultDataPtr = NULL;\r
84f9a9ec
LG
1561 break;\r
1562\r
1563 case EFI_IFR_FORM_OP:\r
2573712e 1564 case EFI_IFR_FORM_MAP_OP:\r
84f9a9ec
LG
1565 //\r
1566 // No matched varstore is found and directly return.\r
1567 //\r
82e8c138 1568 if (VarStorageData->VarStoreId == 0) {\r
84f9a9ec
LG
1569 Status = EFI_SUCCESS;\r
1570 goto Done;\r
1571 }\r
1572 break;\r
1573\r
e7fd76d1
ED
1574 case EFI_IFR_REF_OP:\r
1575 //\r
1576 // Ref question is not in IFR Form. This IFR form is not valid. \r
1577 //\r
82e8c138 1578 if (VarStorageData->VarStoreId == 0) {\r
e7fd76d1
ED
1579 Status = EFI_INVALID_PARAMETER;\r
1580 goto Done;\r
1581 }\r
1582 //\r
1583 // Check whether this question is for the requested varstore.\r
1584 //\r
1585 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;\r
1586 if (IfrRef->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1587 break;\r
1588 }\r
e7fd76d1 1589 VarWidth = (UINT16) (sizeof (EFI_HII_REF));\r
e7fd76d1 1590\r
82e8c138
ED
1591 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1592 if (EFI_ERROR (Status)) {\r
e7fd76d1
ED
1593 goto Done;\r
1594 }\r
e7fd76d1
ED
1595 break;\r
1596\r
84f9a9ec
LG
1597 case EFI_IFR_ONE_OF_OP:\r
1598 case EFI_IFR_NUMERIC_OP:\r
1599 //\r
1600 // Numeric and OneOf has the same opcode structure.\r
1601 //\r
1602\r
8567300a
LG
1603 //\r
1604 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
1605 //\r
82e8c138 1606 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1607 Status = EFI_INVALID_PARAMETER;\r
1608 goto Done;\r
1609 }\r
84f9a9ec
LG
1610 //\r
1611 // Check whether this question is for the requested varstore.\r
1612 //\r
1613 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
1614 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1615 break;\r
1616 }\r
84f9a9ec 1617 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
84f9a9ec 1618\r
82e8c138
ED
1619 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1620 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1621 goto Done;\r
1622 }\r
82e8c138 1623\r
84f9a9ec 1624 if (BlockData == NULL) {\r
82e8c138
ED
1625 //\r
1626 // BlockData == NULL means this opcode is not in the requst array.\r
1627 //\r
1628 break;\r
84f9a9ec 1629 }\r
82e8c138 1630\r
cf4c5a42
LG
1631 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
1632 //\r
1633 // Set this flag to TRUE for the first oneof option.\r
1634 //\r
1635 FirstOneOfOption = TRUE;\r
1636 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
1637 //\r
1638 // Numeric minimum value will be used as default value when no default is specified. \r
1639 //\r
eb5e7d3e 1640 DefaultData.Type = DefaultValueFromDefault;\r
cf4c5a42
LG
1641 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1642 case EFI_IFR_NUMERIC_SIZE_1:\r
e7fd76d1 1643 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
cf4c5a42 1644 break;\r
82e8c138 1645\r
cf4c5a42 1646 case EFI_IFR_NUMERIC_SIZE_2:\r
e7fd76d1 1647 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
cf4c5a42 1648 break;\r
82e8c138 1649\r
cf4c5a42 1650 case EFI_IFR_NUMERIC_SIZE_4:\r
e7fd76d1 1651 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
cf4c5a42 1652 break;\r
82e8c138 1653\r
cf4c5a42 1654 case EFI_IFR_NUMERIC_SIZE_8:\r
e7fd76d1 1655 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
cf4c5a42 1656 break;\r
82e8c138
ED
1657\r
1658 default:\r
1659 Status = EFI_INVALID_PARAMETER;\r
1660 goto Done;\r
cf4c5a42
LG
1661 }\r
1662 //\r
ef40f0f6
ED
1663 // Set default value base on the DefaultId list get from IFR data.\r
1664 // \r
1665 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
82e8c138 1666 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
ef40f0f6
ED
1667 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
1668 InsertDefaultValue (BlockData, &DefaultData);\r
1669 }\r
cf4c5a42 1670 }\r
84f9a9ec
LG
1671 break;\r
1672\r
1673 case EFI_IFR_ORDERED_LIST_OP:\r
1674 //\r
1675 // offset by question header\r
1676 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
1677 // no default value and default id, how to define its default value?\r
1678 //\r
8567300a
LG
1679\r
1680 //\r
1681 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
1682 //\r
82e8c138 1683 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1684 Status = EFI_INVALID_PARAMETER;\r
1685 goto Done;\r
1686 }\r
84f9a9ec
LG
1687 //\r
1688 // Check whether this question is for the requested varstore.\r
1689 //\r
1690 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
1691 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
ff28420b 1692 BlockData = NULL;\r
84f9a9ec
LG
1693 break;\r
1694 }\r
84f9a9ec 1695 VarWidth = IfrOrderedList->MaxContainers;\r
82e8c138
ED
1696 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1697 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1698 goto Done;\r
1699 }\r
84f9a9ec
LG
1700 break;\r
1701\r
1702 case EFI_IFR_CHECKBOX_OP:\r
1703 //\r
1704 // EFI_IFR_DEFAULT_OP\r
1705 // offset by question header\r
1706 // width is 1 sizeof (BOOLEAN)\r
1707 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1708 // value by DefaultOption\r
1709 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1710 // \r
1711\r
8567300a
LG
1712 //\r
1713 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1714 //\r
82e8c138 1715 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1716 Status = EFI_INVALID_PARAMETER;\r
1717 goto Done;\r
1718 }\r
84f9a9ec
LG
1719 //\r
1720 // Check whether this question is for the requested varstore.\r
1721 //\r
1722 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1723 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1724 break;\r
1725 }\r
c9325700 1726 VarWidth = (UINT16) sizeof (BOOLEAN);\r
82e8c138
ED
1727 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1728 if (EFI_ERROR (Status)) {\r
1729 goto Done;\r
1730 }\r
84f9a9ec 1731\r
82e8c138 1732 if (BlockData == NULL) {\r
84f9a9ec 1733 //\r
82e8c138 1734 // BlockData == NULL means this opcode is not in the requst array.\r
84f9a9ec
LG
1735 //\r
1736 break;\r
1737 }\r
1738\r
84f9a9ec 1739 //\r
e9668a60 1740 // Add default value for standard ID by CheckBox Flag\r
84f9a9ec 1741 //\r
e9668a60
LG
1742 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1743 //\r
1744 // Prepare new DefaultValue\r
1745 //\r
ef40f0f6 1746 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1747 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1748 //\r
e9668a60 1749 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1750 //\r
e7fd76d1
ED
1751 DefaultData.Type = DefaultValueFromFlag;\r
1752 DefaultData.Value.b = TRUE;\r
e9668a60 1753 } else {\r
84f9a9ec 1754 //\r
e9668a60 1755 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1756 //\r
e7fd76d1
ED
1757 DefaultData.Type = DefaultValueFromDefault;\r
1758 DefaultData.Value.b = FALSE;\r
84f9a9ec 1759 }\r
e9668a60
LG
1760 //\r
1761 // Add DefaultValue into current BlockData\r
1762 //\r
ef40f0f6 1763 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 1764\r
e9668a60
LG
1765 //\r
1766 // Add default value for Manufacture ID by CheckBox Flag\r
1767 //\r
1768 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1769 //\r
1770 // Prepare new DefaultValue\r
1771 //\r
ef40f0f6 1772 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1773 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1774 //\r
e9668a60 1775 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1776 //\r
e7fd76d1
ED
1777 DefaultData.Type = DefaultValueFromFlag;\r
1778 DefaultData.Value.b = TRUE;\r
e9668a60 1779 } else {\r
84f9a9ec 1780 //\r
e9668a60 1781 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1782 //\r
82e8c138 1783 DefaultData.Type = DefaultValueFromDefault;\r
e7fd76d1 1784 DefaultData.Value.b = FALSE;\r
84f9a9ec 1785 }\r
e9668a60
LG
1786 //\r
1787 // Add DefaultValue into current BlockData\r
1788 //\r
ef40f0f6 1789 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec
LG
1790 break;\r
1791\r
d9bbabfd
ED
1792 case EFI_IFR_DATE_OP:\r
1793 //\r
1794 // offset by question header\r
1795 // width MaxSize * sizeof (CHAR16)\r
1796 // no default value, only block array\r
1797 //\r
1798\r
1799 //\r
1800 // Date question is not in IFR Form. This IFR form is not valid. \r
1801 //\r
82e8c138 1802 if (VarStorageData->VarStoreId == 0) {\r
d9bbabfd
ED
1803 Status = EFI_INVALID_PARAMETER;\r
1804 goto Done;\r
1805 }\r
1806 //\r
1807 // Check whether this question is for the requested varstore.\r
1808 //\r
1809 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;\r
1810 if (IfrDate->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1811 break;\r
1812 }\r
1813\r
d9bbabfd 1814 VarWidth = (UINT16) sizeof (EFI_HII_DATE);\r
82e8c138
ED
1815 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1816 if (EFI_ERROR (Status)) {\r
d9bbabfd
ED
1817 goto Done;\r
1818 }\r
d9bbabfd
ED
1819 break;\r
1820\r
1821 case EFI_IFR_TIME_OP:\r
1822 //\r
1823 // offset by question header\r
1824 // width MaxSize * sizeof (CHAR16)\r
1825 // no default value, only block array\r
1826 //\r
1827\r
1828 //\r
1829 // Time question is not in IFR Form. This IFR form is not valid. \r
1830 //\r
82e8c138 1831 if (VarStorageData->VarStoreId == 0) {\r
d9bbabfd
ED
1832 Status = EFI_INVALID_PARAMETER;\r
1833 goto Done;\r
1834 }\r
1835 //\r
1836 // Check whether this question is for the requested varstore.\r
1837 //\r
1838 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;\r
1839 if (IfrTime->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1840 break;\r
1841 }\r
1842\r
d9bbabfd 1843 VarWidth = (UINT16) sizeof (EFI_HII_TIME);\r
82e8c138
ED
1844 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1845 if (EFI_ERROR (Status)) {\r
d9bbabfd
ED
1846 goto Done;\r
1847 }\r
d9bbabfd
ED
1848 break;\r
1849\r
84f9a9ec
LG
1850 case EFI_IFR_STRING_OP:\r
1851 //\r
1852 // offset by question header\r
1853 // width MaxSize * sizeof (CHAR16)\r
1854 // no default value, only block array\r
1855 //\r
1856\r
8567300a
LG
1857 //\r
1858 // String question is not in IFR Form. This IFR form is not valid. \r
1859 //\r
82e8c138 1860 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1861 Status = EFI_INVALID_PARAMETER;\r
1862 goto Done;\r
1863 }\r
84f9a9ec
LG
1864 //\r
1865 // Check whether this question is for the requested varstore.\r
1866 //\r
1867 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1868 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1869 break;\r
1870 }\r
84f9a9ec 1871\r
82e8c138
ED
1872 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1873 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1874 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1875 goto Done;\r
1876 }\r
82e8c138 1877\r
84f9a9ec
LG
1878 //\r
1879 // No default value for string.\r
1880 //\r
1881 BlockData = NULL;\r
1882 break;\r
1883\r
1884 case EFI_IFR_PASSWORD_OP:\r
1885 //\r
1886 // offset by question header\r
1887 // width MaxSize * sizeof (CHAR16)\r
1888 // no default value, only block array\r
1889 //\r
1890\r
8567300a
LG
1891 //\r
1892 // Password question is not in IFR Form. This IFR form is not valid. \r
1893 //\r
82e8c138 1894 if (VarStorageData->VarStoreId == 0) {\r
8567300a
LG
1895 Status = EFI_INVALID_PARAMETER;\r
1896 goto Done;\r
1897 }\r
84f9a9ec
LG
1898 //\r
1899 // Check whether this question is for the requested varstore.\r
1900 //\r
1901 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
1902 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1903 break;\r
1904 }\r
84f9a9ec 1905\r
82e8c138
ED
1906 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
1907 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1908 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1909 goto Done;\r
1910 }\r
82e8c138 1911\r
84f9a9ec
LG
1912 //\r
1913 // No default value for string.\r
1914 //\r
1915 BlockData = NULL;\r
1916 break;\r
1917\r
1918 case EFI_IFR_ONE_OF_OPTION_OP:\r
1919 //\r
1920 // No matched block data is ignored.\r
1921 //\r
1922 if (BlockData == NULL || BlockData->Scope == 0) {\r
1923 break;\r
1924 }\r
82e8c138 1925\r
84f9a9ec
LG
1926 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1927 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1928 //\r
1929 // Get ordered list option data type.\r
1930 //\r
1931 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
1932 VarWidth = 1;\r
1933 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1934 VarWidth = 2;\r
1935 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1936 VarWidth = 4;\r
1937 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1938 VarWidth = 8;\r
1939 } else {\r
1940 //\r
1941 // Invalid ordered list option data type.\r
1942 //\r
1943 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
1944 if (BlockData->Name != NULL) {\r
1945 FreePool (BlockData->Name);\r
1946 }\r
ff28420b 1947 FreePool (BlockData);\r
84f9a9ec
LG
1948 goto Done;\r
1949 }\r
ff28420b 1950\r
84f9a9ec
LG
1951 //\r
1952 // Calculate Ordered list QuestionId width.\r
1953 //\r
1954 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
ff28420b
LG
1955 //\r
1956 // Check whether this question is in requested block array.\r
1957 //\r
82e8c138 1958 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, BlockData->Name != NULL, HiiHandle)) {\r
ff28420b
LG
1959 //\r
1960 // This question is not in the requested string. Skip it.\r
1961 //\r
82e8c138
ED
1962 if (BlockData->Name != NULL) {\r
1963 FreePool (BlockData->Name);\r
1964 }\r
ff28420b
LG
1965 FreePool (BlockData);\r
1966 BlockData = NULL;\r
1967 break;\r
1968 }\r
1969 //\r
1970 // Check this var question is in the var storage \r
1971 //\r
82e8c138 1972 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {\r
ff28420b 1973 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
1974 if (BlockData->Name != NULL) {\r
1975 FreePool (BlockData->Name);\r
1976 }\r
ff28420b
LG
1977 FreePool (BlockData);\r
1978 goto Done;\r
1979 }\r
1980 //\r
1981 // Add Block Data into VarStorageData BlockEntry\r
1982 //\r
1983 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1984 //\r
1985 // No default data for OrderedList.\r
1986 //\r
84f9a9ec
LG
1987 BlockData = NULL;\r
1988 break;\r
1989 }\r
1990\r
ef40f0f6
ED
1991 //\r
1992 // 1. Set default value for OneOf option when flag field has default attribute.\r
1993 //\r
cf4c5a42 1994 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
ef40f0f6 1995 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {\r
cf4c5a42
LG
1996 //\r
1997 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
1998 // The first oneof option value will be used as default value when no default value is specified. \r
1999 //\r
2000 FirstOneOfOption = FALSE;\r
ef40f0f6 2001 \r
84f9a9ec
LG
2002 // Prepare new DefaultValue\r
2003 //\r
82e8c138 2004 DefaultData.Type = DefaultValueFromFlag;\r
a7f87053 2005 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
2006 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
2007 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2008 InsertDefaultValue (BlockData, &DefaultData);\r
2009 } \r
2010 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
2011 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2012 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 2013 }\r
ef40f0f6 2014 }\r
82e8c138 2015\r
ef40f0f6
ED
2016 //\r
2017 // 2. Set as the default value when this is the first option.\r
2018 // The first oneof option value will be used as default value when no default value is specified. \r
2019 //\r
2020 if (FirstOneOfOption) {\r
2021 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2022 FirstOneOfOption = FALSE;\r
2023 \r
84f9a9ec
LG
2024 //\r
2025 // Prepare new DefaultValue\r
ef40f0f6 2026 // \r
82e8c138 2027 DefaultData.Type = DefaultValueFromDefault;\r
a7f87053 2028 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
2029 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2030 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry); \r
2031 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2032 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 2033 }\r
84f9a9ec
LG
2034 }\r
2035 break;\r
2036\r
2037 case EFI_IFR_DEFAULT_OP:\r
2038 //\r
2039 // Update Current BlockData to the default value.\r
2040 //\r
2041 if (BlockData == NULL || BlockData->Scope == 0) {\r
2042 //\r
82e8c138 2043 // No matched block data is ignored.\r
84f9a9ec
LG
2044 //\r
2045 break;\r
2046 }\r
2047\r
2048 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
2049 //\r
2050 // OrderedList Opcode is no default value.\r
2051 //\r
2052 break;\r
2053 }\r
2054 //\r
81b618fe 2055 // Get the DefaultId\r
84f9a9ec
LG
2056 //\r
2057 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
2058 VarDefaultId = IfrDefault->DefaultId;\r
84f9a9ec
LG
2059 //\r
2060 // Prepare new DefaultValue\r
2061 //\r
eb5e7d3e 2062 DefaultData.Type = DefaultValueFromOpcode;\r
ef40f0f6 2063 DefaultData.DefaultId = VarDefaultId;\r
23fe74dc 2064 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
82e8c138 2065\r
ef40f0f6
ED
2066 // If the value field is expression, set the cleaned flag.\r
2067 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
2068 DefaultData.Cleaned = TRUE;\r
84f9a9ec 2069 }\r
84f9a9ec
LG
2070 //\r
2071 // Add DefaultValue into current BlockData\r
2072 //\r
ef40f0f6 2073 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 2074\r
ef40f0f6
ED
2075 //\r
2076 // After insert the default value, reset the cleaned value for next \r
2077 // time used. If not set here, need to set the value before everytime \r
2078 // use it.\r
2079 //\r
2080 DefaultData.Cleaned = FALSE;\r
84f9a9ec 2081 break;\r
82e8c138 2082\r
84f9a9ec
LG
2083 case EFI_IFR_END_OP:\r
2084 //\r
8567300a 2085 // End Opcode is for Var question.\r
84f9a9ec
LG
2086 //\r
2087 if (BlockData != NULL && BlockData->Scope > 0) {\r
2088 BlockData->Scope--;\r
2089 }\r
2090 break;\r
82e8c138 2091\r
84f9a9ec
LG
2092 default:\r
2093 if (BlockData != NULL && BlockData->Scope > 0) {\r
2094 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
2095 }\r
2096 break;\r
2097 }\r
2098\r
2099 IfrOffset += IfrOpHdr->Length;\r
2100 }\r
2101\r
2102Done:\r
ef40f0f6
ED
2103 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2104 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2105 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
2106 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2107 LinkDefault = LinkDefault->ForwardLink;\r
2108 if (DefaultDataPtr->Cleaned == TRUE) {\r
2109 RemoveEntryList (&DefaultDataPtr->Entry);\r
2110 FreePool (DefaultDataPtr);\r
2111 }\r
2112 }\r
2113 }\r
2114\r
82e8c138 2115 return Status;\r
84f9a9ec
LG
2116}\r
2117\r
2118/**\r
82e8c138 2119 parse the configrequest string, get the elements.\r
84f9a9ec 2120\r
82e8c138
ED
2121 @param ConfigRequest The input configrequest string.\r
2122 @param Progress Return the progress data.\r
2123\r
2124 @retval Block data pointer.\r
2125**/\r
2126IFR_BLOCK_DATA *\r
2127GetBlockElement (\r
2128 IN EFI_STRING ConfigRequest,\r
2129 OUT EFI_STRING *Progress\r
2130 )\r
2131{\r
2132 EFI_STRING StringPtr;\r
2133 IFR_BLOCK_DATA *BlockData;\r
2134 IFR_BLOCK_DATA *RequestBlockArray;\r
2135 EFI_STATUS Status;\r
2136 UINT8 *TmpBuffer;\r
2137 UINT16 Offset;\r
2138 UINT16 Width;\r
2139 LIST_ENTRY *Link;\r
2140 IFR_BLOCK_DATA *NextBlockData;\r
2141 UINTN Length;\r
2142\r
2143 //\r
2144 // Init RequestBlockArray\r
2145 //\r
2146 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2147 if (RequestBlockArray == NULL) {\r
2148 goto Done;\r
2149 }\r
2150 InitializeListHead (&RequestBlockArray->Entry);\r
2151\r
2152 //\r
2153 // Get the request Block array from the request string\r
2154 // Offset and Width\r
2155 //\r
2156\r
2157 //\r
2158 // Parse each <RequestElement> if exists\r
2159 // Only <BlockName> format is supported by this help function.\r
2160 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
2161 //\r
2162 StringPtr = ConfigRequest;\r
2163 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
2164 //\r
2165 // Skip the OFFSET string\r
2166 //\r
2167 *Progress = StringPtr;\r
2168 StringPtr += StrLen (L"&OFFSET=");\r
2169 //\r
2170 // Get Offset\r
2171 //\r
2172 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2173 if (EFI_ERROR (Status)) {\r
2174 goto Done;\r
2175 }\r
2176 Offset = 0;\r
2177 CopyMem (\r
2178 &Offset,\r
2179 TmpBuffer,\r
2180 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2181 );\r
2182 FreePool (TmpBuffer);\r
2183\r
2184 StringPtr += Length;\r
2185 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
2186 goto Done;\r
2187 }\r
2188 StringPtr += StrLen (L"&WIDTH=");\r
2189\r
2190 //\r
2191 // Get Width\r
2192 //\r
2193 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2194 if (EFI_ERROR (Status)) {\r
2195 goto Done;\r
2196 }\r
2197 Width = 0;\r
2198 CopyMem (\r
2199 &Width,\r
2200 TmpBuffer,\r
2201 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2202 );\r
2203 FreePool (TmpBuffer);\r
2204\r
2205 StringPtr += Length;\r
2206 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2207 goto Done;\r
2208 }\r
2209 \r
2210 //\r
2211 // Set Block Data\r
2212 //\r
2213 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2214 if (BlockData == NULL) {\r
2215 goto Done;\r
2216 }\r
2217 BlockData->Offset = Offset;\r
2218 BlockData->Width = Width;\r
2219 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2220\r
2221 //\r
2222 // Skip &VALUE string if &VALUE does exists.\r
2223 //\r
2224 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
2225 StringPtr += StrLen (L"&VALUE=");\r
2226\r
2227 //\r
2228 // Get Value\r
2229 //\r
2230 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2231 if (EFI_ERROR (Status)) {\r
2232 goto Done;\r
2233 }\r
2234\r
2235 StringPtr += Length;\r
2236 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2237 goto Done;\r
2238 }\r
2239 }\r
2240 //\r
2241 // If '\0', parsing is finished. \r
2242 //\r
2243 if (*StringPtr == 0) {\r
2244 break;\r
2245 }\r
2246 }\r
2247\r
2248 //\r
2249 // Merge the requested block data.\r
2250 //\r
2251 Link = RequestBlockArray->Entry.ForwardLink;\r
2252 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
2253 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2254 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
2255 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
2256 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
2257 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
2258 }\r
2259 RemoveEntryList (Link->ForwardLink);\r
2260 FreePool (NextBlockData);\r
2261 continue;\r
2262 }\r
2263 Link = Link->ForwardLink;\r
2264 }\r
2265\r
2266 return RequestBlockArray;\r
2267\r
2268Done:\r
2269 if (RequestBlockArray != NULL) {\r
2270 //\r
2271 // Free Link Array RequestBlockArray\r
2272 //\r
2273 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2274 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2275 RemoveEntryList (&BlockData->Entry);\r
2276 FreePool (BlockData);\r
2277 }\r
2278\r
2279 FreePool (RequestBlockArray);\r
2280 }\r
2281\r
2282 return NULL;\r
2283}\r
2284\r
2285/**\r
2286 parse the configrequest string, get the elements.\r
2287\r
2288 @param ConfigRequest The input config request string.\r
2289 @param Progress Return the progress data.\r
2290\r
2291 @retval return data block array.\r
2292**/\r
2293IFR_BLOCK_DATA *\r
2294GetNameElement (\r
2295 IN EFI_STRING ConfigRequest,\r
2296 OUT EFI_STRING *Progress\r
2297 )\r
2298{\r
2299 EFI_STRING StringPtr;\r
2300 EFI_STRING NextTag;\r
2301 IFR_BLOCK_DATA *BlockData;\r
2302 IFR_BLOCK_DATA *RequestBlockArray;\r
2303 BOOLEAN HasValue;\r
2304\r
2305 StringPtr = ConfigRequest;\r
2306\r
2307 //\r
2308 // Init RequestBlockArray\r
2309 //\r
2310 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2311 if (RequestBlockArray == NULL) {\r
2312 goto Done;\r
2313 }\r
2314 InitializeListHead (&RequestBlockArray->Entry);\r
2315\r
2316 //\r
2317 // Get the request Block array from the request string\r
2318 //\r
2319\r
2320 //\r
2321 // Parse each <RequestElement> if exists\r
2322 // Only <BlockName> format is supported by this help function.\r
2323 // <BlockName> ::= &'Name***=***\r
2324 //\r
2325 while (StringPtr != NULL && *StringPtr == L'&') {\r
2326\r
2327 *Progress = StringPtr;\r
2328 //\r
2329 // Skip the L"&" string\r
2330 //\r
2331 StringPtr += 1;\r
2332\r
2333 HasValue = FALSE;\r
2334 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
2335 *NextTag = L'\0';\r
2336 HasValue = TRUE;\r
2337 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
2338 *NextTag = L'\0';\r
2339 }\r
2340\r
2341 //\r
2342 // Set Block Data\r
2343 //\r
2344 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2345 if (BlockData == NULL) {\r
2346 goto Done;\r
2347 }\r
2348\r
2349 //\r
2350 // Get Name\r
2351 //\r
2352 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);\r
2353 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2354\r
2355 if (HasValue) {\r
2356 //\r
2357 // If has value, skip the value.\r
2358 // \r
2359 StringPtr = NextTag + 1;\r
2360 *NextTag = L'=';\r
2361 StringPtr = StrStr (StringPtr, L"&");\r
2362 } else if (NextTag != NULL) {\r
2363 //\r
2364 // restore the '&' text.\r
2365 //\r
2366 StringPtr = NextTag;\r
2367 *NextTag = L'&';\r
2368 }\r
2369 }\r
2370\r
2371 return RequestBlockArray;\r
2372\r
2373Done:\r
2374 if (RequestBlockArray != NULL) {\r
2375 //\r
2376 // Free Link Array RequestBlockArray\r
2377 //\r
2378 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2379 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2380 RemoveEntryList (&BlockData->Entry);\r
2381 if (BlockData->Name != NULL) {\r
2382 FreePool (BlockData->Name);\r
2383 }\r
2384 FreePool (BlockData);\r
2385 }\r
2386\r
2387 FreePool (RequestBlockArray);\r
2388 }\r
2389\r
2390 return NULL;\r
2391}\r
2392\r
2393/**\r
2394 Generate ConfigRequest string base on the varstore info.\r
2395\r
2396 @param ConfigHdr The config header for this varstore.\r
2397 @param VarStorageData The varstore info.\r
2398 @param Status Return Status.\r
2399 @param ConfigRequest The ConfigRequest info may be return.\r
2400\r
2401 @retval TRUE Need to continue\r
2402 @retval Others NO need to continue or error occur.\r
2403**/\r
2404BOOLEAN\r
2405GenerateConfigRequest (\r
2406 IN CHAR16 *ConfigHdr,\r
2407 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2408 OUT EFI_STATUS *Status,\r
2409 IN OUT EFI_STRING *ConfigRequest\r
2410 )\r
2411{\r
2412 BOOLEAN DataExist;\r
2413 UINTN Length;\r
2414 LIST_ENTRY *Link;\r
2415 CHAR16 *FullConfigRequest;\r
2416 CHAR16 *StringPtr;\r
2417 IFR_BLOCK_DATA *BlockData;\r
2418\r
2419 //\r
2420 // Append VarStorageData BlockEntry into *Request string\r
2421 // Now support only one varstore in a form package.\r
2422 //\r
2423 \r
2424 //\r
2425 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
2426 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
2427 //\r
2428 \r
2429 //\r
2430 // Compute the length of the entire request starting with <ConfigHdr> and a \r
2431 // Null-terminator\r
2432 //\r
2433 DataExist = FALSE;\r
2434 Length = StrLen (ConfigHdr) + 1;\r
2435\r
2436 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2437 DataExist = TRUE;\r
2438 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2439 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2440 //\r
2441 // Add <BlockName> length for each Name\r
2442 //\r
2443 // <BlockName> ::= &Name1&Name2&... \r
2444 // |1| StrLen(Name1)\r
2445 //\r
2446 Length = Length + (1 + StrLen (BlockData->Name));\r
2447 } else {\r
2448 //\r
2449 // Add <BlockName> length for each Offset/Width pair\r
2450 //\r
2451 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
2452 // | 8 | 4 | 7 | 4 |\r
2453 //\r
2454 Length = Length + (8 + 4 + 7 + 4);\r
2455 }\r
2456 }\r
2457 //\r
2458 // No any request block data is found. The request string can't be constructed.\r
2459 //\r
2460 if (!DataExist) {\r
2461 *Status = EFI_SUCCESS;\r
2462 return FALSE;\r
2463 }\r
2464\r
2465 //\r
2466 // Allocate buffer for the entire <ConfigRequest>\r
2467 //\r
2468 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
2469 if (FullConfigRequest == NULL) {\r
2470 *Status = EFI_OUT_OF_RESOURCES;\r
2471 return FALSE;\r
2472 }\r
2473 StringPtr = FullConfigRequest;\r
2474\r
2475 //\r
2476 // Start with <ConfigHdr>\r
2477 //\r
2478 StrCpy (StringPtr, ConfigHdr);\r
2479 StringPtr += StrLen (StringPtr);\r
2480\r
2481 //\r
2482 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
2483 //\r
2484 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2485 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2486 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2487 //\r
2488 // Append &Name1\0\r
2489 //\r
2490 UnicodeSPrint (\r
2491 StringPtr,\r
2492 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
2493 L"&%s",\r
2494 BlockData->Name\r
2495 );\r
2496 } else {\r
2497 //\r
2498 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
2499 //\r
2500 UnicodeSPrint (\r
2501 StringPtr, \r
2502 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
2503 L"&OFFSET=%04X&WIDTH=%04X", \r
2504 BlockData->Offset, \r
2505 BlockData->Width\r
2506 );\r
2507 }\r
2508 StringPtr += StrLen (StringPtr);\r
2509 }\r
2510 //\r
2511 // Set to the got full request string.\r
2512 //\r
2513 HiiToLower (FullConfigRequest);\r
2514\r
2515 if (*ConfigRequest != NULL) {\r
2516 FreePool (*ConfigRequest);\r
2517 }\r
2518 *ConfigRequest = FullConfigRequest;\r
2519\r
2520 return TRUE;\r
2521}\r
2522\r
2523/**\r
2524 Generate ConfigRequest Header base on the varstore info.\r
2525\r
2526 @param VarStorageData The varstore info.\r
2527 @param DevicePath Device path for this varstore.\r
2528 @param ConfigHdr The config header for this varstore.\r
2529\r
2530 @retval EFI_SUCCESS Generate the header success.\r
2531 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
2532**/\r
2533EFI_STATUS\r
2534GenerateHdr (\r
2535 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2536 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2537 OUT EFI_STRING *ConfigHdr\r
2538 )\r
2539{\r
2540 EFI_STRING GuidStr;\r
2541 EFI_STRING NameStr;\r
2542 EFI_STRING PathStr;\r
2543 UINTN Length;\r
2544 EFI_STATUS Status;\r
2545\r
2546 Status = EFI_SUCCESS;\r
2547 NameStr = NULL;\r
2548 GuidStr = NULL;\r
2549 PathStr = NULL;\r
2550\r
2551 //\r
2552 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
2553 //\r
2554 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
2555 if (VarStorageData->Name != NULL) {\r
2556 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
2557 } else {\r
2558 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
2559 }\r
2560 GenerateSubStr (\r
2561 L"PATH=",\r
2562 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
2563 (VOID *) DevicePath,\r
2564 1,\r
2565 &PathStr\r
2566 );\r
2567 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
2568 if (VarStorageData->Name == NULL) {\r
2569 Length += 1;\r
2570 }\r
2571\r
2572 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
2573 if (*ConfigHdr == NULL) {\r
2574 Status = EFI_OUT_OF_RESOURCES;\r
2575 goto Done;\r
2576 }\r
2577 StrCpy (*ConfigHdr, GuidStr);\r
2578 StrCat (*ConfigHdr, NameStr);\r
2579 if (VarStorageData->Name == NULL) {\r
2580 StrCat (*ConfigHdr, L"&");\r
2581 }\r
2582 StrCat (*ConfigHdr, PathStr);\r
2583\r
2584 //\r
2585 // Remove the last character L'&'\r
2586 //\r
2587 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
2588\r
2589Done:\r
2590 if (GuidStr != NULL) {\r
2591 FreePool (GuidStr);\r
2592 }\r
2593\r
2594 if (NameStr != NULL) {\r
2595 FreePool (NameStr);\r
2596 }\r
2597\r
2598 if (PathStr != NULL) {\r
2599 FreePool (PathStr);\r
2600 }\r
2601\r
2602 return Status;\r
2603}\r
2604\r
2605/**\r
2606 Get Data buffer size based on data type.\r
2607\r
2608 @param ValueType The input data type.\r
2609\r
2610 @retval The data buffer size for the input type.\r
2611**/\r
2612UINT16\r
2613GetStorageWidth (\r
2614 IN UINT8 ValueType\r
2615 )\r
2616{\r
2617 UINT16 StorageWidth;\r
2618\r
2619 switch (ValueType) {\r
2620 case EFI_IFR_NUMERIC_SIZE_1:\r
2621 case EFI_IFR_TYPE_BOOLEAN:\r
2622 StorageWidth = (UINT16) sizeof (UINT8);\r
2623 break;\r
2624\r
2625 case EFI_IFR_NUMERIC_SIZE_2:\r
2626 StorageWidth = (UINT16) sizeof (UINT16);\r
2627 break;\r
2628\r
2629 case EFI_IFR_NUMERIC_SIZE_4:\r
2630 StorageWidth = (UINT16) sizeof (UINT32);\r
2631 break;\r
2632\r
2633 case EFI_IFR_NUMERIC_SIZE_8:\r
2634 StorageWidth = (UINT16) sizeof (UINT64);\r
2635 break;\r
2636\r
2637 case EFI_IFR_TYPE_TIME:\r
2638 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);\r
2639 break;\r
2640\r
2641 case EFI_IFR_TYPE_DATE:\r
2642 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);\r
2643 break;\r
2644\r
2645 default:\r
2646 StorageWidth = 0;\r
2647 break;\r
2648 }\r
2649\r
2650 return StorageWidth;\r
2651}\r
2652\r
2653/**\r
2654 Generate ConfigAltResp string base on the varstore info.\r
2655\r
2656 @param ConfigHdr The config header for this varstore.\r
2657 @param VarStorageData The varstore info.\r
2658 @param DefaultIdArray The Default id array.\r
2659 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
2660\r
2661 @retval TRUE Need to continue\r
2662 @retval Others NO need to continue or error occur.\r
2663**/\r
2664EFI_STATUS\r
2665GenerateAltConfigResp (\r
2666 IN CHAR16 *ConfigHdr,\r
2667 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2668 IN IFR_DEFAULT_DATA *DefaultIdArray,\r
2669 IN OUT EFI_STRING *DefaultAltCfgResp\r
2670 )\r
2671{\r
2672 BOOLEAN DataExist;\r
2673 UINTN Length;\r
2674 LIST_ENTRY *Link;\r
2675 LIST_ENTRY *LinkData;\r
2676 LIST_ENTRY *LinkDefault;\r
2677 LIST_ENTRY *ListEntry;\r
2678 CHAR16 *StringPtr;\r
2679 IFR_BLOCK_DATA *BlockData;\r
2680 IFR_DEFAULT_DATA *DefaultId;\r
2681 IFR_DEFAULT_DATA *DefaultValueData;\r
2682 UINTN Width;\r
2683 UINT8 *TmpBuffer;\r
2684\r
2685 BlockData = NULL;\r
2686 DataExist = FALSE;\r
2687\r
2688 //\r
2689 // Add length for <ConfigHdr> + '\0'\r
2690 //\r
2691 Length = StrLen (ConfigHdr) + 1;\r
2692\r
2693 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2694 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2695 //\r
2696 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
2697 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2698 //\r
2699 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
2700 \r
2701 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2702 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2703 ListEntry = &BlockData->DefaultValueEntry;\r
2704 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2705 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2706 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2707 continue;\r
2708 }\r
2709 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2710 //\r
2711 // Add length for "&Name1=zzzzzzzzzzzz"\r
2712 // |1|Name|1|Value|\r
2713 //\r
2714 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
2715 } else {\r
2716 //\r
2717 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
2718 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
2719 //\r
2720 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
2721 }\r
2722 DataExist = TRUE;\r
2723 }\r
2724 }\r
2725 }\r
2726 \r
2727 //\r
2728 // No default value is found. The default string doesn't exist.\r
2729 //\r
2730 if (!DataExist) {\r
2731 return EFI_SUCCESS;\r
2732 }\r
2733\r
2734 //\r
2735 // Allocate buffer for the entire <DefaultAltCfgResp>\r
2736 //\r
2737 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
2738 if (*DefaultAltCfgResp == NULL) {\r
2739 return EFI_OUT_OF_RESOURCES;\r
2740 }\r
2741 StringPtr = *DefaultAltCfgResp;\r
2742\r
2743 //\r
2744 // Start with <ConfigHdr>\r
2745 //\r
2746 StrCpy (StringPtr, ConfigHdr);\r
2747 StringPtr += StrLen (StringPtr);\r
2748\r
2749 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2750 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2751 //\r
2752 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
2753 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2754 //\r
2755 UnicodeSPrint (\r
2756 StringPtr, \r
2757 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
2758 L"&%s&ALTCFG=%04X", \r
2759 ConfigHdr, \r
2760 DefaultId->DefaultId\r
2761 );\r
2762 StringPtr += StrLen (StringPtr);\r
2763\r
2764 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2765 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2766 ListEntry = &BlockData->DefaultValueEntry;\r
2767 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2768 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2769 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2770 continue;\r
2771 }\r
2772 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2773 UnicodeSPrint (\r
2774 StringPtr, \r
2775 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16), \r
2776 L"&%s=", \r
2777 BlockData->Name\r
2778 );\r
2779 StringPtr += StrLen (StringPtr);\r
2780 } else {\r
2781 //\r
2782 // Add <BlockConfig>\r
2783 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
2784 //\r
2785 UnicodeSPrint (\r
2786 StringPtr, \r
2787 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
2788 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
2789 BlockData->Offset, \r
2790 BlockData->Width\r
2791 );\r
2792 StringPtr += StrLen (StringPtr);\r
2793 }\r
2794 Width = BlockData->Width;\r
2795 //\r
2796 // Convert Value to a hex string in "%x" format\r
2797 // NOTE: This is in the opposite byte that GUID and PATH use\r
2798 //\r
2799 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
2800 for (; Width > 0; Width--) {\r
2801 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
2802 }\r
2803 }\r
2804 }\r
2805 }\r
2806\r
2807 HiiToLower (*DefaultAltCfgResp);\r
2808\r
2809 return EFI_SUCCESS;\r
2810}\r
2811\r
2812/**\r
2813 This function gets the full request string and full default value string by \r
2814 parsing IFR data in HII form packages. \r
2815 \r
2816 When Request points to NULL string, the request string and default value string \r
2817 for each varstore in form package will return. \r
2818\r
2819 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
2820 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
2821 @param Request Pointer to a null-terminated Unicode string in\r
2822 <ConfigRequest> format. When it doesn't contain\r
2823 any RequestElement, it will be updated to return \r
2824 the full RequestElement retrieved from IFR data.\r
2825 If it points to NULL, the request string for the first\r
2826 varstore in form package will be merged into a\r
2827 <MultiConfigRequest> format string and return. \r
2828 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
2829 <ConfigAltResp> format. When the pointer is to NULL,\r
2830 the full default value string retrieved from IFR data\r
2831 will return. When the pinter is to a string, the\r
2832 full default value string retrieved from IFR data\r
2833 will be merged into the input string and return.\r
2834 When Request points to NULL, the default value string \r
2835 for each varstore in form package will be merged into \r
2836 a <MultiConfigAltResp> format string and return.\r
2837 @param PointerProgress Optional parameter, it can be be NULL. \r
2838 When it is not NULL, if Request is NULL, it returns NULL. \r
2839 On return, points to a character in the Request\r
2840 string. Points to the string's null terminator if\r
2841 request was successful. Points to the most recent\r
2842 & before the first failing name / value pair (or\r
ae79d2f9
LG
2843 the beginning of the string if the failure is in\r
2844 the first name / value pair) if the request was\r
2845 not successful.\r
84f9a9ec
LG
2846 @retval EFI_SUCCESS The Results string is set to the full request string.\r
2847 And AltCfgResp contains all default value string.\r
2848 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
2849 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
2850 can't be found in Form package.\r
2851 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 2852 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
2853\r
2854**/\r
2855EFI_STATUS\r
2856EFIAPI\r
2857GetFullStringFromHiiFormPackages (\r
8567300a 2858 IN HII_DATABASE_RECORD *DataBaseRecord,\r
84f9a9ec
LG
2859 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2860 IN OUT EFI_STRING *Request,\r
ae79d2f9
LG
2861 IN OUT EFI_STRING *AltCfgResp,\r
2862 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
2863 )\r
2864{\r
2865 EFI_STATUS Status;\r
8567300a
LG
2866 UINT8 *HiiFormPackage;\r
2867 UINTN PackageSize;\r
84f9a9ec
LG
2868 IFR_BLOCK_DATA *RequestBlockArray;\r
2869 IFR_BLOCK_DATA *BlockData;\r
84f9a9ec
LG
2870 IFR_DEFAULT_DATA *DefaultValueData;\r
2871 IFR_DEFAULT_DATA *DefaultId;\r
2872 IFR_DEFAULT_DATA *DefaultIdArray;\r
84f9a9ec
LG
2873 IFR_VARSTORAGE_DATA *VarStorageData;\r
2874 EFI_STRING DefaultAltCfgResp;\r
84f9a9ec 2875 EFI_STRING ConfigHdr;\r
84f9a9ec 2876 EFI_STRING StringPtr;\r
ae79d2f9 2877 EFI_STRING Progress;\r
6e3f5b2a 2878 BOOLEAN DataExist;\r
84f9a9ec 2879\r
ae79d2f9
LG
2880 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
2881 return EFI_INVALID_PARAMETER;\r
2882 }\r
2883\r
84f9a9ec
LG
2884 //\r
2885 // Initialize the local variables.\r
2886 //\r
2887 RequestBlockArray = NULL;\r
8567300a 2888 DefaultIdArray = NULL;\r
84f9a9ec
LG
2889 VarStorageData = NULL;\r
2890 DefaultAltCfgResp = NULL;\r
84f9a9ec 2891 ConfigHdr = NULL;\r
8567300a 2892 HiiFormPackage = NULL;\r
8567300a 2893 PackageSize = 0;\r
6e3f5b2a 2894 DataExist = FALSE;\r
ae79d2f9 2895 Progress = *Request;\r
84f9a9ec 2896\r
cce6230f 2897 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
84f9a9ec 2898 if (EFI_ERROR (Status)) {\r
cce6230f 2899 return Status;\r
84f9a9ec
LG
2900 }\r
2901\r
2902 //\r
8567300a 2903 // 1. Get the request block array by Request String when Request string containts the block array.\r
84f9a9ec
LG
2904 //\r
2905 StringPtr = NULL;\r
2906 if (*Request != NULL) {\r
ae79d2f9
LG
2907 StringPtr = *Request;\r
2908 //\r
2909 // Jump <ConfigHdr>\r
2910 //\r
2911 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2912 Status = EFI_INVALID_PARAMETER;\r
2913 goto Done;\r
2914 }\r
2915 StringPtr += StrLen (L"GUID=");\r
2916 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
2917 StringPtr++;\r
2918 }\r
2919 if (*StringPtr == L'\0') {\r
2920 Status = EFI_INVALID_PARAMETER;\r
2921 goto Done;\r
2922 }\r
2923 StringPtr += StrLen (L"&NAME=");\r
82e8c138
ED
2924 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
2925 StringPtr++;\r
6e3f5b2a 2926 }\r
82e8c138
ED
2927 if (*StringPtr == L'\0') {\r
2928 Status = EFI_INVALID_PARAMETER;\r
84f9a9ec
LG
2929 goto Done;\r
2930 }\r
82e8c138
ED
2931 StringPtr += StrLen (L"&PATH=");\r
2932 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2933 StringPtr ++;\r
2934 }\r
84f9a9ec 2935\r
82e8c138 2936 if (*StringPtr == L'\0') {\r
84f9a9ec 2937 //\r
82e8c138 2938 // No request block is found.\r
84f9a9ec 2939 //\r
82e8c138 2940 StringPtr = NULL;\r
84f9a9ec 2941 }\r
84f9a9ec 2942 }\r
82e8c138 2943\r
93e3992d 2944 //\r
82e8c138 2945 // If StringPtr != NULL, get the request elements.\r
93e3992d 2946 //\r
82e8c138
ED
2947 if (StringPtr != NULL) {\r
2948 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {\r
2949 RequestBlockArray = GetBlockElement(StringPtr, &Progress);\r
2950 } else {\r
2951 RequestBlockArray = GetNameElement(StringPtr, &Progress);\r
2952 }\r
2953\r
2954 if (RequestBlockArray == NULL) {\r
2955 Status = EFI_INVALID_PARAMETER;\r
2956 goto Done;\r
84f9a9ec 2957 }\r
93e3992d 2958 }\r
82e8c138 2959\r
6e3f5b2a 2960 //\r
82e8c138 2961 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
6e3f5b2a 2962 //\r
82e8c138
ED
2963 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
2964 if (DefaultIdArray == NULL) {\r
2965 Status = EFI_OUT_OF_RESOURCES;\r
6e3f5b2a
LG
2966 goto Done;\r
2967 }\r
82e8c138 2968 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 2969\r
93e3992d 2970 //\r
82e8c138 2971 // Initialize VarStorageData to store the var store Block and Default value information.\r
93e3992d 2972 //\r
82e8c138
ED
2973 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
2974 if (VarStorageData == NULL) {\r
6e3f5b2a 2975 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
2976 goto Done;\r
2977 }\r
82e8c138
ED
2978 InitializeListHead (&VarStorageData->Entry);\r
2979 InitializeListHead (&VarStorageData->BlockEntry);\r
93e3992d 2980\r
84f9a9ec 2981 //\r
82e8c138 2982 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 2983 //\r
93e3992d 2984\r
82e8c138
ED
2985 //\r
2986 // Parse the opcode in form pacakge to get the default setting.\r
2987 //\r
2988 Status = ParseIfrData (DataBaseRecord->Handle,\r
2989 HiiFormPackage,\r
2990 (UINT32) PackageSize,\r
2991 *Request,\r
2992 RequestBlockArray,\r
2993 VarStorageData,\r
2994 DefaultIdArray);\r
2995 if (EFI_ERROR (Status)) {\r
2996 goto Done;\r
2997 }\r
84f9a9ec 2998\r
82e8c138
ED
2999 //\r
3000 // No requested varstore in IFR data and directly return\r
3001 //\r
3002 if (VarStorageData->VarStoreId == 0) {\r
3003 Status = EFI_SUCCESS;\r
3004 goto Done;\r
3005 }\r
3006\r
3007 //\r
3008 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
3009 //\r
3010 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);\r
3011 if (EFI_ERROR (Status)) {\r
3012 goto Done;\r
3013 }\r
3014\r
3015 if (RequestBlockArray == NULL) {\r
3016 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {\r
3017 goto Done;\r
84f9a9ec 3018 }\r
93e3992d 3019 }\r
82e8c138
ED
3020\r
3021 //\r
3022 // 4. Construct Default Value string in AltResp according to request element.\r
3023 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
3024 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
3025 //\r
3026 Status = GenerateAltConfigResp (ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);\r
3027 if (EFI_ERROR (Status)) {\r
3028 goto Done;\r
3029 }\r
93e3992d 3030\r
84f9a9ec
LG
3031 //\r
3032 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
3033 //\r
6e3f5b2a 3034 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
84f9a9ec
LG
3035 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
3036 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
3037 } else if (*AltCfgResp == NULL) {\r
3038 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 3039 }\r
93e3992d 3040\r
84f9a9ec
LG
3041Done:\r
3042 if (RequestBlockArray != NULL) {\r
3043 //\r
3044 // Free Link Array RequestBlockArray\r
3045 //\r
3046 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3047 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3048 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
3049 if (BlockData->Name != NULL) {\r
3050 FreePool (BlockData->Name);\r
3051 }\r
84f9a9ec
LG
3052 FreePool (BlockData);\r
3053 }\r
3054\r
3055 FreePool (RequestBlockArray);\r
93e3992d 3056 }\r
82e8c138 3057\r
84f9a9ec
LG
3058 if (VarStorageData != NULL) {\r
3059 //\r
3060 // Free link array VarStorageData\r
3061 //\r
3062 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
3063 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3064 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
3065 if (BlockData->Name != NULL) {\r
3066 FreePool (BlockData->Name);\r
3067 }\r
84f9a9ec
LG
3068 //\r
3069 // Free default value link array\r
3070 //\r
3071 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
3072 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3073 RemoveEntryList (&DefaultValueData->Entry);\r
3074 FreePool (DefaultValueData);\r
3075 }\r
3076 FreePool (BlockData);\r
63d55bb9 3077 }\r
84f9a9ec 3078 FreePool (VarStorageData);\r
93e3992d 3079 }\r
3080\r
84f9a9ec
LG
3081 if (DefaultIdArray != NULL) {\r
3082 //\r
3083 // Free DefaultId Array\r
3084 //\r
3085 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
3086 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3087 RemoveEntryList (&DefaultId->Entry);\r
3088 FreePool (DefaultId);\r
3089 }\r
3090 FreePool (DefaultIdArray);\r
3091 }\r
82e8c138 3092\r
84f9a9ec
LG
3093 //\r
3094 // Free the allocated string \r
3095 //\r
84f9a9ec
LG
3096 if (ConfigHdr != NULL) {\r
3097 FreePool (ConfigHdr);\r
3098 }\r
93e3992d 3099\r
84f9a9ec
LG
3100 //\r
3101 // Free Pacakge data\r
3102 //\r
8567300a
LG
3103 if (HiiFormPackage != NULL) {\r
3104 FreePool (HiiFormPackage);\r
676df92c 3105 }\r
63d55bb9 3106\r
ae79d2f9
LG
3107 if (PointerProgress != NULL) {\r
3108 if (*Request == NULL) {\r
3109 *PointerProgress = NULL;\r
3110 } else if (EFI_ERROR (Status)) {\r
82e8c138 3111 *PointerProgress = *Request;\r
ae79d2f9
LG
3112 } else {\r
3113 *PointerProgress = *Request + StrLen (*Request);\r
3114 }\r
3115 }\r
3116\r
93e3992d 3117 return Status;\r
3118}\r
3119\r
cce6230f
ED
3120/**\r
3121 This function gets the full request resp string by \r
3122 parsing IFR data in HII form packages.\r
3123\r
3124 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3125 instance.\r
3126 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3127 varstore data structure. \r
3128 @param Request Pointer to a null-terminated Unicode string in\r
3129 <ConfigRequest> format.\r
3130 @param RequestResp Pointer to a null-terminated Unicode string in\r
3131 <ConfigResp> format.\r
3132 @param AccessProgress On return, points to a character in the Request\r
3133 string. Points to the string's null terminator if\r
3134 request was successful. Points to the most recent\r
3135 & before the first failing name / value pair (or\r
3136 the beginning of the string if the failure is in\r
3137 the first name / value pair) if the request was\r
3138 not successful.\r
3139\r
3140 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3141 And AltCfgResp contains all default value string.\r
3142 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3143 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3144\r
3145**/\r
3146EFI_STATUS\r
3147GetConfigRespFromEfiVarStore (\r
3148 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3149 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3150 IN EFI_STRING Request,\r
3151 OUT EFI_STRING *RequestResp,\r
3152 OUT EFI_STRING *AccessProgress\r
3153 )\r
3154{\r
3155 EFI_STATUS Status;\r
3156 EFI_STRING VarStoreName;\r
3157 UINT8 *VarStore;\r
3158 UINTN BufferSize;\r
3159\r
3160 Status = EFI_SUCCESS;\r
3161 BufferSize = 0;\r
3162 VarStore = NULL;\r
3163 VarStoreName = NULL;\r
3164 \r
3165 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3166 if (VarStoreName == NULL) {\r
3167 Status = EFI_OUT_OF_RESOURCES;\r
3168 goto Done;\r
3169 }\r
3170 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3171 \r
3172 \r
3173 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3174 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3175 goto Done;\r
3176 }\r
3177\r
3178 VarStore = AllocateZeroPool (BufferSize);\r
3179 ASSERT (VarStore != NULL);\r
3180 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3181 if (EFI_ERROR (Status)) {\r
3182 goto Done;\r
3183 }\r
3184\r
3185 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
3186 if (EFI_ERROR (Status)) {\r
3187 goto Done;\r
3188 }\r
3189\r
3190Done:\r
3191 if (VarStoreName != NULL) {\r
3192 FreePool (VarStoreName);\r
3193 }\r
3194\r
3195 if (VarStore != NULL) {\r
3196 FreePool (VarStore);\r
3197 }\r
3198\r
3199 return Status;\r
3200}\r
3201\r
3202\r
3203/**\r
3204 This function route the full request resp string for efi varstore. \r
3205\r
3206 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3207 instance.\r
3208 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3209 varstore data structure. \r
3210 @param RequestResp Pointer to a null-terminated Unicode string in\r
3211 <ConfigResp> format.\r
3212 @param Result Pointer to a null-terminated Unicode string in\r
3213 <ConfigResp> format.\r
3214 \r
3215 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3216 And AltCfgResp contains all default value string.\r
3217 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3218 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3219\r
3220**/\r
3221EFI_STATUS\r
3222RouteConfigRespForEfiVarStore (\r
3223 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3224 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3225 IN EFI_STRING RequestResp,\r
3226 OUT EFI_STRING *Result\r
3227 )\r
3228{\r
3229 EFI_STATUS Status;\r
3230 EFI_STRING VarStoreName;\r
f26b6a9c 3231 UINT8 *VarStore;\r
cce6230f
ED
3232 UINTN BufferSize;\r
3233 UINTN BlockSize;\r
3234\r
3235 Status = EFI_SUCCESS;\r
3236 BufferSize = 0;\r
3237 VarStore = NULL;\r
3238 VarStoreName = NULL;\r
3239\r
3240 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3241 if (VarStoreName == NULL) {\r
3242 Status = EFI_OUT_OF_RESOURCES;\r
3243 goto Done;\r
3244 }\r
3245 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3246 \r
3247 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3248 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3249 goto Done;\r
3250 }\r
3251\r
3252 BlockSize = BufferSize;\r
3253 VarStore = AllocateZeroPool (BufferSize);\r
3254 ASSERT (VarStore != NULL);\r
3255 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3256 if (EFI_ERROR (Status)) {\r
3257 goto Done;\r
3258 }\r
3259\r
3260 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);\r
3261 if (EFI_ERROR (Status)) {\r
3262 goto Done;\r
3263 }\r
3264\r
3265 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
3266 if (EFI_ERROR (Status)) {\r
3267 goto Done;\r
3268 }\r
3269\r
3270Done:\r
3271 if (VarStoreName != NULL) {\r
3272 FreePool (VarStoreName);\r
3273 }\r
3274\r
3275 if (VarStore != NULL) {\r
3276 FreePool (VarStore);\r
3277 }\r
3278\r
3279 return Status;\r
3280}\r
3281\r
82e8c138
ED
3282/**\r
3283 Validate the config request elements.\r
3284\r
3285 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3286 without configHdr field.\r
3287\r
3288 @retval CHAR16 * THE first Name/value pair not correct.\r
3289 @retval NULL Success parse the name/value pair\r
3290**/\r
3291CHAR16 *\r
3292OffsetWidthValidate (\r
3293 CHAR16 *ConfigElements\r
3294 )\r
3295{\r
3296 CHAR16 *StringPtr;\r
3297 CHAR16 *RetVal;\r
3298\r
3299 StringPtr = ConfigElements;\r
3300\r
3301 while (1) {\r
3302 RetVal = StringPtr;\r
3303 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3304 return RetVal;\r
3305 }\r
3306\r
3307 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3308 StringPtr++;\r
3309 }\r
3310 if (*StringPtr == L'\0') {\r
3311 return RetVal;\r
3312 }\r
3313\r
3314 StringPtr += StrLen (L"&WIDTH=");\r
3315 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3316 StringPtr ++;\r
3317 }\r
3318\r
3319 if (*StringPtr == L'\0') {\r
3320 return NULL;\r
3321 }\r
3322 }\r
3323}\r
3324\r
3325/**\r
3326 Validate the config request elements.\r
3327\r
3328 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3329 without configHdr field.\r
3330\r
3331 @retval CHAR16 * THE first Name/value pair not correct.\r
3332 @retval NULL Success parse the name/value pair\r
3333\r
3334**/\r
3335CHAR16 *\r
3336NameValueValidate (\r
3337 CHAR16 *ConfigElements\r
3338 )\r
3339{\r
3340 CHAR16 *StringPtr;\r
3341 CHAR16 *RetVal;\r
3342\r
3343 StringPtr = ConfigElements;\r
3344\r
3345 while (1) {\r
3346 RetVal = StringPtr;\r
3347 if (*StringPtr != L'&') {\r
3348 return RetVal;\r
3349 }\r
3350 StringPtr += 1;\r
3351\r
3352 StringPtr = StrStr (StringPtr, L"&");\r
3353 \r
3354 if (StringPtr == NULL) {\r
3355 return NULL;\r
3356 }\r
3357 }\r
3358}\r
3359\r
3360/**\r
3361 Validate the config request string.\r
3362\r
3363 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.\r
3364\r
3365 @retval CHAR16 * THE first element not correct.\r
3366 @retval NULL Success parse the name/value pair\r
3367\r
3368**/\r
3369CHAR16 *\r
3370ConfigRequestValidate (\r
3371 CHAR16 *ConfigRequest\r
3372 )\r
3373{\r
3374 BOOLEAN HasNameField;\r
3375 CHAR16 *StringPtr;\r
3376\r
3377 HasNameField = TRUE;\r
3378 StringPtr = ConfigRequest;\r
3379\r
3380 //\r
3381 // Check <ConfigHdr>\r
3382 //\r
3383 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3384 return ConfigRequest;\r
3385 }\r
3386 StringPtr += StrLen (L"GUID=");\r
3387 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
3388 StringPtr++;\r
3389 }\r
3390 if (*StringPtr == L'\0') {\r
3391 return ConfigRequest;\r
3392 }\r
3393 StringPtr += StrLen (L"&NAME=");\r
3394 if (*StringPtr == L'&') {\r
3395 HasNameField = FALSE;\r
3396 }\r
3397 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
3398 StringPtr++;\r
3399 }\r
3400 if (*StringPtr == L'\0') {\r
3401 return ConfigRequest;\r
3402 }\r
3403 StringPtr += StrLen (L"&PATH=");\r
3404 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
3405 StringPtr ++;\r
3406 }\r
3407\r
3408 if (*StringPtr == L'\0') {\r
3409 return NULL;\r
3410 }\r
3411\r
3412 if (HasNameField) {\r
3413 //\r
3414 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.\r
3415 //\r
3416 return OffsetWidthValidate(StringPtr);\r
3417 } else {\r
3418 //\r
3419 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.\r
3420 //\r
3421 return NameValueValidate(StringPtr);\r
3422 }\r
3423}\r
3424\r
93e3992d 3425/**\r
3426 This function allows a caller to extract the current configuration\r
3427 for one or more named elements from one or more drivers.\r
3428\r
3429 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3430 instance.\r
3431 @param Request A null-terminated Unicode string in\r
3432 <MultiConfigRequest> format.\r
3433 @param Progress On return, points to a character in the Request\r
3434 string. Points to the string's null terminator if\r
3435 request was successful. Points to the most recent\r
3436 & before the first failing name / value pair (or\r
3437 the beginning of the string if the failure is in\r
3438 the first name / value pair) if the request was\r
3439 not successful.\r
3440 @param Results Null-terminated Unicode string in\r
3441 <MultiConfigAltResp> format which has all values\r
3442 filled in for the names in the Request string.\r
3443 String to be allocated by the called function.\r
3444\r
3445 @retval EFI_SUCCESS The Results string is filled with the values\r
3446 corresponding to all requested names.\r
3447 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3448 results that must be stored awaiting possible\r
3449 future protocols.\r
3450 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
3451 Progress set to the "G" in "GUID" of the routing\r
3452 header that doesn't match. Note: There is no\r
3453 requirement that all routing data be validated\r
3454 before any configuration extraction.\r
3455 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
3456 parameter would result in this type of error. The\r
3457 Progress parameter is set to NULL.\r
3458 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
3459 before the error or the beginning of the string.\r
3460 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
3461 name in question.\r
3462\r
3463**/\r
3464EFI_STATUS\r
3465EFIAPI\r
3466HiiConfigRoutingExtractConfig (\r
3467 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3468 IN CONST EFI_STRING Request,\r
3469 OUT EFI_STRING *Progress,\r
3470 OUT EFI_STRING *Results\r
3471 )\r
3472{\r
84f9a9ec 3473 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 3474 EFI_STRING StringPtr;\r
3475 EFI_STRING ConfigRequest;\r
3476 UINTN Length;\r
3477 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 3478 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 3479 EFI_STATUS Status;\r
84f9a9ec
LG
3480 LIST_ENTRY *Link;\r
3481 HII_DATABASE_RECORD *Database;\r
3482 UINT8 *DevicePathPkg;\r
3483 UINT8 *CurrentDevicePath;\r
93e3992d 3484 EFI_HANDLE DriverHandle;\r
84f9a9ec 3485 EFI_HII_HANDLE HiiHandle;\r
93e3992d 3486 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3487 EFI_STRING AccessProgress;\r
3488 EFI_STRING AccessResults;\r
84f9a9ec 3489 EFI_STRING DefaultResults;\r
8d00a0f1 3490 BOOLEAN FirstElement;\r
6e3f5b2a 3491 BOOLEAN IfrDataParsedFlag;\r
cce6230f 3492 BOOLEAN IsEfiVarStore;\r
82e8c138
ED
3493 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
3494 EFI_STRING ErrorPtr;\r
93e3992d 3495\r
3496 if (This == NULL || Progress == NULL || Results == NULL) {\r
3497 return EFI_INVALID_PARAMETER;\r
3498 }\r
3499\r
3500 if (Request == NULL) {\r
3501 *Progress = NULL;\r
3502 return EFI_INVALID_PARAMETER;\r
3503 }\r
3504\r
84f9a9ec 3505 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 3506 StringPtr = Request;\r
3507 *Progress = StringPtr;\r
84f9a9ec
LG
3508 DefaultResults = NULL;\r
3509 ConfigRequest = NULL;\r
3510 Status = EFI_SUCCESS;\r
3511 AccessResults = NULL;\r
cce6230f 3512 AccessProgress = NULL;\r
84f9a9ec 3513 DevicePath = NULL;\r
6e3f5b2a 3514 IfrDataParsedFlag = FALSE;\r
cce6230f
ED
3515 IsEfiVarStore = FALSE;\r
3516 EfiVarStoreInfo = NULL;\r
93e3992d 3517\r
3518 //\r
3519 // The first element of <MultiConfigRequest> should be\r
3520 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
3521 //\r
3522 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3523 return EFI_INVALID_PARAMETER;\r
3524 }\r
3525\r
8d00a0f1 3526 FirstElement = TRUE;\r
3527\r
93e3992d 3528 //\r
3529 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3530 // Results if this fix length is insufficient.\r
3531 //\r
3532 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3533 if (*Results == NULL) {\r
3534 return EFI_OUT_OF_RESOURCES;\r
3535 }\r
3536\r
3537 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
3538 //\r
3539 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
3540 // or most recent & before the error.\r
3541 //\r
3542 if (StringPtr == Request) {\r
3543 *Progress = StringPtr;\r
3544 } else {\r
3545 *Progress = StringPtr - 1;\r
3546 }\r
3547\r
3548 //\r
3549 // Process each <ConfigRequest> of <MultiConfigRequest>\r
3550 //\r
3551 Length = CalculateConfigStringLen (StringPtr);\r
3552 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
3553 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
3554 Status = EFI_OUT_OF_RESOURCES;\r
3555 goto Done;\r
93e3992d 3556 }\r
3557 *(ConfigRequest + Length) = 0;\r
3558\r
3559 //\r
3560 // Get the UEFI device path\r
3561 //\r
3562 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
3563 if (EFI_ERROR (Status)) {\r
84f9a9ec 3564 goto Done;\r
93e3992d 3565 }\r
3566\r
3567 //\r
84f9a9ec
LG
3568 // Find driver which matches the routing data.\r
3569 //\r
3570 DriverHandle = NULL;\r
3571 HiiHandle = NULL;\r
8567300a 3572 Database = NULL;\r
84f9a9ec
LG
3573 for (Link = Private->DatabaseList.ForwardLink;\r
3574 Link != &Private->DatabaseList;\r
3575 Link = Link->ForwardLink\r
3576 ) {\r
3577 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
3578 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3579 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 3580 if (CompareMem (\r
84f9a9ec
LG
3581 DevicePath,\r
3582 CurrentDevicePath,\r
6e3f5b2a
LG
3583 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
3584 ) == 0) {\r
84f9a9ec
LG
3585 DriverHandle = Database->DriverHandle;\r
3586 HiiHandle = Database->Handle;\r
3587 break;\r
3588 }\r
3589 }\r
3590 }\r
3591 \r
3592 //\r
3593 // Try to find driver handle by device path.\r
93e3992d 3594 //\r
84f9a9ec
LG
3595 if (DriverHandle == NULL) {\r
3596 TempDevicePath = DevicePath;\r
3597 Status = gBS->LocateDevicePath (\r
3598 &gEfiDevicePathProtocolGuid,\r
3599 &TempDevicePath,\r
3600 &DriverHandle\r
3601 );\r
3602 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
3603 //\r
3604 // Routing data does not match any known driver.\r
3605 // Set Progress to the 'G' in "GUID" of the routing header.\r
3606 //\r
3607 *Progress = StringPtr;\r
3608 Status = EFI_NOT_FOUND;\r
3609 goto Done;\r
3610 }\r
3611 }\r
82e8c138
ED
3612\r
3613 //\r
3614 // Validate ConfigRequest String.\r
3615 //\r
3616 ErrorPtr = ConfigRequestValidate(ConfigRequest);\r
3617 if (ErrorPtr != NULL) {\r
3618 *Progress = StrStr (StringPtr, ErrorPtr);\r
3619 Status = EFI_INVALID_PARAMETER;\r
3620 goto Done;\r
3621 }\r
3622\r
84f9a9ec 3623 //\r
82e8c138 3624 // Check whether ConfigRequest contains request string.\r
84f9a9ec 3625 //\r
6e3f5b2a 3626 IfrDataParsedFlag = FALSE;\r
82e8c138 3627 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {\r
93e3992d 3628 //\r
84f9a9ec 3629 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 3630 //\r
6e3f5b2a 3631 IfrDataParsedFlag = TRUE;\r
ae79d2f9 3632 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 3633 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
3634 //\r
3635 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3636 // Map it to the progress on <MultiConfigRequest> then return it.\r
3637 //\r
82e8c138 3638 ASSERT (AccessProgress != NULL);\r
ae79d2f9 3639 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
3640 goto Done;\r
3641 }\r
1f1cb2f2
LG
3642 //\r
3643 // Not any request block is found.\r
3644 //\r
82e8c138 3645 if (!GetElementsFromRequest(ConfigRequest)) {\r
76c24251 3646 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
3647 goto NextConfigString;\r
3648 }\r
93e3992d 3649 }\r
3650\r
3651 //\r
cce6230f 3652 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 3653 //\r
cce6230f
ED
3654 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
3655 if (EFI_ERROR (Status)) {\r
3656 goto Done;\r
3657 }\r
3658 \r
3659 if (IsEfiVarStore) {\r
3660 //\r
3661 // Call the GetVariable function to extract settings.\r
3662 //\r
3663 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
82e8c138 3664 FreePool (EfiVarStoreInfo);\r
cce6230f
ED
3665 } else {\r
3666 //\r
3667 // Call corresponding ConfigAccess protocol to extract settings\r
3668 //\r
3669 Status = gBS->HandleProtocol (\r
3670 DriverHandle,\r
3671 &gEfiHiiConfigAccessProtocolGuid,\r
3672 (VOID **) &ConfigAccess\r
3673 );\r
3674 ASSERT_EFI_ERROR (Status);\r
93e3992d 3675\r
cce6230f
ED
3676 Status = ConfigAccess->ExtractConfig (\r
3677 ConfigAccess,\r
3678 ConfigRequest,\r
3679 &AccessProgress,\r
3680 &AccessResults\r
3681 );\r
3682 }\r
93e3992d 3683 if (EFI_ERROR (Status)) {\r
3684 //\r
3685 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3686 // Map it to the progress on <MultiConfigRequest> then return it.\r
3687 //\r
8d00a0f1 3688 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 3689 goto Done;\r
93e3992d 3690 }\r
3691\r
3692 //\r
8d00a0f1 3693 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3694 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 3695 //\r
3696 ASSERT (*AccessProgress == 0);\r
8d00a0f1 3697\r
84f9a9ec
LG
3698 //\r
3699 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3700 //\r
ae79d2f9
LG
3701 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
3702 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3703 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 3704 }\r
ae79d2f9 3705\r
84f9a9ec
LG
3706 FreePool (DevicePath);\r
3707 DevicePath = NULL;\r
84f9a9ec 3708\r
ae79d2f9
LG
3709 if (DefaultResults != NULL) {\r
3710 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3711 ASSERT_EFI_ERROR (Status);\r
3712 FreePool (DefaultResults);\r
3713 DefaultResults = NULL;\r
3714 }\r
3715 \r
82e8c138 3716NextConfigString:\r
8d00a0f1 3717 if (!FirstElement) {\r
3718 Status = AppendToMultiString (Results, L"&");\r
3719 ASSERT_EFI_ERROR (Status);\r
3720 }\r
3721 \r
93e3992d 3722 Status = AppendToMultiString (Results, AccessResults);\r
3723 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 3724\r
3725 FirstElement = FALSE;\r
84f9a9ec 3726\r
676df92c 3727 FreePool (AccessResults);\r
93e3992d 3728 AccessResults = NULL;\r
676df92c 3729 FreePool (ConfigRequest);\r
93e3992d 3730 ConfigRequest = NULL;\r
3731\r
3732 //\r
3733 // Go to next <ConfigRequest> (skip '&').\r
3734 //\r
3735 StringPtr += Length;\r
3736 if (*StringPtr == 0) {\r
3737 *Progress = StringPtr;\r
3738 break;\r
3739 }\r
3740\r
3741 StringPtr++;\r
93e3992d 3742 }\r
3743\r
84f9a9ec
LG
3744Done:\r
3745 if (EFI_ERROR (Status)) {\r
3746 FreePool (*Results);\r
6e3f5b2a 3747 *Results = NULL;\r
84f9a9ec
LG
3748 }\r
3749 \r
3750 if (ConfigRequest != NULL) {\r
3751 FreePool (ConfigRequest);\r
3752 }\r
3753 \r
3754 if (AccessResults != NULL) {\r
3755 FreePool (AccessResults);\r
3756 }\r
3757 \r
3758 if (DefaultResults != NULL) {\r
3759 FreePool (DefaultResults);\r
3760 }\r
3761 \r
3762 if (DevicePath != NULL) {\r
3763 FreePool (DevicePath);\r
3764 } \r
93e3992d 3765\r
84f9a9ec 3766 return Status;\r
93e3992d 3767}\r
3768\r
3769\r
3770/**\r
3771 This function allows the caller to request the current configuration for the\r
3772 entirety of the current HII database and returns the data in a\r
3773 null-terminated Unicode string.\r
3774\r
3775 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3776 instance.\r
3777 @param Results Null-terminated Unicode string in\r
3778 <MultiConfigAltResp> format which has all values\r
3779 filled in for the names in the Request string.\r
3780 String to be allocated by the called function.\r
3781 De-allocation is up to the caller.\r
3782\r
3783 @retval EFI_SUCCESS The Results string is filled with the values\r
3784 corresponding to all requested names.\r
3785 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3786 results that must be stored awaiting possible\r
3787 future protocols.\r
3788 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
3789 parameter would result in this type of error.\r
3790\r
3791**/\r
3792EFI_STATUS\r
3793EFIAPI\r
3794HiiConfigRoutingExportConfig (\r
3795 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3796 OUT EFI_STRING *Results\r
3797 )\r
3798{\r
93e3992d 3799 EFI_STATUS Status;\r
93e3992d 3800 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
3801 EFI_STRING AccessResults;\r
3802 EFI_STRING Progress;\r
6e3f5b2a 3803 EFI_STRING StringPtr;\r
ae79d2f9 3804 EFI_STRING ConfigRequest;\r
8d00a0f1 3805 UINTN Index;\r
3806 EFI_HANDLE *ConfigAccessHandles;\r
3807 UINTN NumberConfigAccessHandles;\r
3808 BOOLEAN FirstElement;\r
84f9a9ec
LG
3809 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3810 EFI_HII_HANDLE HiiHandle;\r
3811 EFI_STRING DefaultResults;\r
3812 HII_DATABASE_PRIVATE_DATA *Private;\r
3813 LIST_ENTRY *Link;\r
3814 HII_DATABASE_RECORD *Database;\r
3815 UINT8 *DevicePathPkg;\r
3816 UINT8 *CurrentDevicePath;\r
ae79d2f9 3817 BOOLEAN IfrDataParsedFlag;\r
93e3992d 3818\r
3819 if (This == NULL || Results == NULL) {\r
3820 return EFI_INVALID_PARAMETER;\r
3821 }\r
3822\r
84f9a9ec
LG
3823 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3824\r
93e3992d 3825 //\r
3826 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3827 // Results if this fix length is insufficient.\r
3828 //\r
3829 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3830 if (*Results == NULL) {\r
3831 return EFI_OUT_OF_RESOURCES;\r
3832 }\r
3833\r
8d00a0f1 3834 NumberConfigAccessHandles = 0;\r
3835 Status = gBS->LocateHandleBuffer (\r
3836 ByProtocol,\r
3837 &gEfiHiiConfigAccessProtocolGuid,\r
3838 NULL,\r
3839 &NumberConfigAccessHandles,\r
3840 &ConfigAccessHandles\r
3841 );\r
3842 if (EFI_ERROR (Status)) {\r
3843 return Status;\r
3844 }\r
93e3992d 3845\r
8d00a0f1 3846 FirstElement = TRUE;\r
93e3992d 3847\r
8d00a0f1 3848 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 3849 Status = gBS->HandleProtocol (\r
8d00a0f1 3850 ConfigAccessHandles[Index],\r
93e3992d 3851 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 3852 (VOID **) &ConfigAccess\r
93e3992d 3853 );\r
8d00a0f1 3854 if (EFI_ERROR (Status)) {\r
3855 continue;\r
3856 }\r
93e3992d 3857\r
84f9a9ec
LG
3858 //\r
3859 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
3860 //\r
ae79d2f9 3861 IfrDataParsedFlag = FALSE;\r
84f9a9ec
LG
3862 Progress = NULL;\r
3863 HiiHandle = NULL;\r
84f9a9ec 3864 DefaultResults = NULL;\r
8567300a 3865 Database = NULL;\r
ae79d2f9 3866 ConfigRequest = NULL;\r
84f9a9ec 3867 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
3868 if (DevicePath != NULL) {\r
3869 for (Link = Private->DatabaseList.ForwardLink;\r
3870 Link != &Private->DatabaseList;\r
3871 Link = Link->ForwardLink\r
3872 ) {\r
3873 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3874 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3875 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 3876 if (CompareMem (\r
84f9a9ec
LG
3877 DevicePath,\r
3878 CurrentDevicePath,\r
6e3f5b2a
LG
3879 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
3880 ) == 0) {\r
84f9a9ec
LG
3881 HiiHandle = Database->Handle;\r
3882 break;\r
3883 }\r
3884 }\r
3885 }\r
3886 }\r
3887\r
93e3992d 3888 Status = ConfigAccess->ExtractConfig (\r
3889 ConfigAccess,\r
6e3f5b2a 3890 NULL,\r
84f9a9ec 3891 &Progress,\r
93e3992d 3892 &AccessResults\r
3893 );\r
ae79d2f9 3894 if (EFI_ERROR (Status)) {\r
6e3f5b2a
LG
3895 //\r
3896 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3897 //\r
3898 if (HiiHandle != NULL && DevicePath != NULL) {\r
ae79d2f9
LG
3899 IfrDataParsedFlag = TRUE;\r
3900 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3901 //\r
3902 // Get the full request string to get the Current setting again.\r
3903 //\r
3904 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
3905 Status = ConfigAccess->ExtractConfig (\r
3906 ConfigAccess,\r
3907 ConfigRequest,\r
3908 &Progress,\r
3909 &AccessResults\r
3910 );\r
3911 FreePool (ConfigRequest);\r
3912 } else {\r
3913 Status = EFI_NOT_FOUND;\r
3914 }\r
3915 }\r
3916 }\r
3917\r
3918 if (!EFI_ERROR (Status)) {\r
3919 //\r
3920 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3921 //\r
3922 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
6e3f5b2a
LG
3923 StringPtr = StrStr (AccessResults, L"&GUID=");\r
3924 if (StringPtr != NULL) {\r
3925 *StringPtr = 0;\r
3926 }\r
82e8c138 3927 if (GetElementsFromRequest (AccessResults)) {\r
ae79d2f9
LG
3928 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
3929 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a
LG
3930 }\r
3931 if (StringPtr != NULL) {\r
3932 *StringPtr = L'&';\r
3933 }\r
3934 }\r
84f9a9ec
LG
3935 //\r
3936 // Merge the default sting from IFR code into the got setting from driver.\r
3937 //\r
3938 if (DefaultResults != NULL) {\r
8567300a
LG
3939 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3940 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 3941 FreePool (DefaultResults);\r
8567300a 3942 DefaultResults = NULL;\r
84f9a9ec
LG
3943 }\r
3944 \r
8d00a0f1 3945 //\r
3946 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3947 // which seperates the first <ConfigAltResp> and the following ones. \r
3948 //\r
3949 if (!FirstElement) {\r
3950 Status = AppendToMultiString (Results, L"&");\r
3951 ASSERT_EFI_ERROR (Status);\r
676df92c 3952 }\r
8d00a0f1 3953 \r
3954 Status = AppendToMultiString (Results, AccessResults);\r
3955 ASSERT_EFI_ERROR (Status);\r
93e3992d 3956\r
8d00a0f1 3957 FirstElement = FALSE;\r
3958 \r
3959 FreePool (AccessResults);\r
3960 AccessResults = NULL;\r
3961 }\r
93e3992d 3962 }\r
f4113e1f 3963 FreePool (ConfigAccessHandles);\r
93e3992d 3964\r
8d00a0f1 3965 return EFI_SUCCESS; \r
93e3992d 3966}\r
3967\r
3968\r
3969/**\r
3970 This function processes the results of processing forms and routes it to the\r
3971 appropriate handlers or storage.\r
3972\r
3973 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3974 instance.\r
3975 @param Configuration A null-terminated Unicode string in\r
3976 <MulltiConfigResp> format.\r
3977 @param Progress A pointer to a string filled in with the offset of\r
3978 the most recent & before the first failing name /\r
3979 value pair (or the beginning of the string if the\r
3980 failure is in the first name / value pair) or the\r
3981 terminating NULL if all was successful.\r
3982\r
3983 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
3984 distribution.\r
3985 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3986 results that must be stored awaiting possible\r
3987 future protocols.\r
3988 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
3989 would result in this type of error.\r
3990 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
3991 found.\r
3992\r
3993**/\r
3994EFI_STATUS\r
3995EFIAPI\r
813acf3a 3996HiiConfigRoutingRouteConfig (\r
93e3992d 3997 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3998 IN CONST EFI_STRING Configuration,\r
3999 OUT EFI_STRING *Progress\r
4000 )\r
4001{\r
84f9a9ec 4002 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 4003 EFI_STRING StringPtr;\r
4004 EFI_STRING ConfigResp;\r
4005 UINTN Length;\r
4006 EFI_STATUS Status;\r
4007 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 4008 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
4009 LIST_ENTRY *Link;\r
4010 HII_DATABASE_RECORD *Database;\r
4011 UINT8 *DevicePathPkg;\r
4012 UINT8 *CurrentDevicePath;\r
93e3992d 4013 EFI_HANDLE DriverHandle;\r
4014 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4015 EFI_STRING AccessProgress;\r
cce6230f
ED
4016 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
4017 BOOLEAN IsEfiVarstore;\r
93e3992d 4018\r
4019 if (This == NULL || Progress == NULL) {\r
4020 return EFI_INVALID_PARAMETER;\r
4021 }\r
4022\r
4023 if (Configuration == NULL) {\r
4024 *Progress = NULL;\r
4025 return EFI_INVALID_PARAMETER;\r
4026 }\r
4027\r
84f9a9ec 4028 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 4029 StringPtr = Configuration;\r
4030 *Progress = StringPtr;\r
cce6230f
ED
4031 Database = NULL;\r
4032 AccessProgress = NULL;\r
4033 EfiVarStoreInfo= NULL;\r
4034 IsEfiVarstore = FALSE;\r
93e3992d 4035\r
4036 //\r
4037 // The first element of <MultiConfigResp> should be\r
4038 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
4039 //\r
4040 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4041 return EFI_INVALID_PARAMETER;\r
4042 }\r
4043\r
4044 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
4045 //\r
4046 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
4047 // or most recent & before the error.\r
4048 //\r
4049 if (StringPtr == Configuration) {\r
4050 *Progress = StringPtr;\r
4051 } else {\r
4052 *Progress = StringPtr - 1;\r
4053 }\r
4054\r
4055 //\r
4056 // Process each <ConfigResp> of <MultiConfigResp>\r
4057 //\r
4058 Length = CalculateConfigStringLen (StringPtr);\r
4059 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
4060 if (ConfigResp == NULL) {\r
4061 return EFI_OUT_OF_RESOURCES;\r
4062 }\r
4063 //\r
4064 // Append '\0' to the end of ConfigRequest\r
4065 //\r
4066 *(ConfigResp + Length) = 0;\r
4067\r
4068 //\r
4069 // Get the UEFI device path\r
4070 //\r
4071 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
4072 if (EFI_ERROR (Status)) {\r
676df92c 4073 FreePool (ConfigResp);\r
93e3992d 4074 return Status;\r
4075 }\r
4076\r
4077 //\r
84f9a9ec
LG
4078 // Find driver which matches the routing data.\r
4079 //\r
4080 DriverHandle = NULL;\r
84f9a9ec
LG
4081 for (Link = Private->DatabaseList.ForwardLink;\r
4082 Link != &Private->DatabaseList;\r
4083 Link = Link->ForwardLink\r
4084 ) {\r
4085 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4086\r
4087 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4088 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 4089 if (CompareMem (\r
84f9a9ec
LG
4090 DevicePath,\r
4091 CurrentDevicePath,\r
6e3f5b2a
LG
4092 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
4093 ) == 0) {\r
84f9a9ec
LG
4094 DriverHandle = Database->DriverHandle;\r
4095 break;\r
4096 }\r
4097 }\r
4098 }\r
93e3992d 4099\r
84f9a9ec
LG
4100 //\r
4101 // Try to find driver handle by device path.\r
4102 //\r
4103 if (DriverHandle == NULL) {\r
4104 TempDevicePath = DevicePath;\r
4105 Status = gBS->LocateDevicePath (\r
4106 &gEfiDevicePathProtocolGuid,\r
4107 &TempDevicePath,\r
4108 &DriverHandle\r
4109 );\r
4110 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
4111 //\r
4112 // Routing data does not match any known driver.\r
4113 // Set Progress to the 'G' in "GUID" of the routing header.\r
4114 //\r
4115 FreePool (DevicePath);\r
4116 *Progress = StringPtr;\r
4117 FreePool (ConfigResp);\r
4118 return EFI_NOT_FOUND;\r
4119 }\r
93e3992d 4120 }\r
4121\r
84f9a9ec
LG
4122 FreePool (DevicePath);\r
4123\r
93e3992d 4124 //\r
cce6230f 4125 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 4126 //\r
cce6230f
ED
4127 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
4128 if (EFI_ERROR (Status)) {\r
4129 return Status;\r
4130 }\r
93e3992d 4131\r
cce6230f
ED
4132 if (IsEfiVarstore) {\r
4133 //\r
4134 // Call the SetVariable function to route settings.\r
4135 // \r
4136 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
4137 FreePool (EfiVarStoreInfo);\r
4138 } else {\r
4139 //\r
4140 // Call corresponding ConfigAccess protocol to route settings\r
4141 //\r
4142 Status = gBS->HandleProtocol (\r
4143 DriverHandle,\r
4144 &gEfiHiiConfigAccessProtocolGuid,\r
4145 (VOID **) &ConfigAccess\r
4146 );\r
4147 ASSERT_EFI_ERROR (Status);\r
93e3992d 4148\r
cce6230f
ED
4149 Status = ConfigAccess->RouteConfig (\r
4150 ConfigAccess,\r
4151 ConfigResp,\r
4152 &AccessProgress\r
4153 );\r
4154 }\r
93e3992d 4155 if (EFI_ERROR (Status)) {\r
4156 //\r
4157 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
4158 // Map it to the progress on <MultiConfigResp> then return it.\r
4159 //\r
8d00a0f1 4160 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 4161\r
676df92c 4162 FreePool (ConfigResp);\r
93e3992d 4163 return Status;\r
4164 }\r
4165\r
676df92c 4166 FreePool (ConfigResp);\r
93e3992d 4167 ConfigResp = NULL;\r
4168\r
4169 //\r
4170 // Go to next <ConfigResp> (skip '&').\r
4171 //\r
4172 StringPtr += Length;\r
4173 if (*StringPtr == 0) {\r
4174 *Progress = StringPtr;\r
4175 break;\r
4176 }\r
4177\r
4178 StringPtr++;\r
4179\r
4180 }\r
4181\r
4182 return EFI_SUCCESS;\r
93e3992d 4183}\r
4184\r
4185\r
4186/**\r
4187 This helper function is to be called by drivers to map configuration data\r
4188 stored in byte array ("block") formats such as UEFI Variables into current\r
4189 configuration strings.\r
4190\r
4191 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4192 instance.\r
4193 @param ConfigRequest A null-terminated Unicode string in\r
4194 <ConfigRequest> format.\r
4195 @param Block Array of bytes defining the block's configuration.\r
4196 @param BlockSize Length in bytes of Block.\r
4197 @param Config Filled-in configuration string. String allocated\r
4198 by the function. Returned only if call is\r
84f9a9ec 4199 successful. It is <ConfigResp> string format.\r
93e3992d 4200 @param Progress A pointer to a string filled in with the offset of\r
4201 the most recent & before the first failing\r
4202 name/value pair (or the beginning of the string if\r
4203 the failure is in the first name / value pair) or\r
4204 the terminating NULL if all was successful.\r
4205\r
4206 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4207 terminator at the end of the ConfigRequest\r
4208 string.\r
4209 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4210 points to the first character of ConfigRequest.\r
4211 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
4212 Block parameter would result in this type of\r
4213 error. Progress points to the first character of\r
4214 ConfigRequest.\r
4215 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
4216 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
4217 Block is left updated and Progress points at\r
4218 the "&" preceding the first non-<BlockName>.\r
4219\r
4220**/\r
4221EFI_STATUS\r
4222EFIAPI\r
4223HiiBlockToConfig (\r
4224 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4225 IN CONST EFI_STRING ConfigRequest,\r
4226 IN CONST UINT8 *Block,\r
4227 IN CONST UINTN BlockSize,\r
4228 OUT EFI_STRING *Config,\r
4229 OUT EFI_STRING *Progress\r
4230 )\r
4231{\r
84f9a9ec 4232 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 4233 EFI_STRING StringPtr;\r
4234 UINTN Length;\r
4235 EFI_STATUS Status;\r
4236 EFI_STRING TmpPtr;\r
4237 UINT8 *TmpBuffer;\r
4238 UINTN Offset;\r
4239 UINTN Width;\r
4240 UINT8 *Value;\r
4241 EFI_STRING ValueStr;\r
4242 EFI_STRING ConfigElement;\r
63d55bb9
LG
4243 UINTN Index;\r
4244 UINT8 *TemBuffer;\r
4245 CHAR16 *TemString;\r
41ff10dc 4246 CHAR16 TemChar;\r
93e3992d 4247\r
4248 if (This == NULL || Progress == NULL || Config == NULL) {\r
4249 return EFI_INVALID_PARAMETER;\r
4250 }\r
4251\r
4252 if (Block == NULL || ConfigRequest == NULL) {\r
4253 *Progress = ConfigRequest;\r
4254 return EFI_INVALID_PARAMETER;\r
4255 }\r
4256\r
84f9a9ec
LG
4257\r
4258 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4259 ASSERT (Private != NULL);\r
4260\r
93e3992d 4261 StringPtr = ConfigRequest;\r
4262 ValueStr = NULL;\r
4263 Value = NULL;\r
4264 ConfigElement = NULL;\r
4265\r
4266 //\r
4267 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4268 // Results if this fix length is insufficient.\r
4269 //\r
4270 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
4271 if (*Config == NULL) {\r
4272 return EFI_OUT_OF_RESOURCES;\r
4273 }\r
4274\r
4275 //\r
4276 // Jump <ConfigHdr>\r
4277 //\r
4278 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4279 *Progress = StringPtr;\r
4280 Status = EFI_INVALID_PARAMETER;\r
4281 goto Exit;\r
4282 }\r
4283 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4284 StringPtr++;\r
4285 }\r
4286 if (*StringPtr == 0) {\r
76c24251 4287 *Progress = StringPtr - 1;\r
93e3992d 4288 Status = EFI_INVALID_PARAMETER;\r
4289 goto Exit;\r
4290 }\r
08e6463a 4291\r
4292 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4293 StringPtr++;\r
4294 }\r
4295 if (*StringPtr == 0) {\r
41ff10dc
ED
4296 *Progress = StringPtr;\r
4297 Status = EFI_SUCCESS;\r
4298\r
4299 AppendToMultiString(Config, ConfigRequest);\r
4300 HiiToLower (*Config);\r
4301\r
08e6463a 4302 goto Exit;\r
4303 }\r
4304 //\r
4305 // Skip '&'\r
4306 //\r
4307 StringPtr++;\r
93e3992d 4308\r
4309 //\r
4310 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
4311 //\r
41ff10dc
ED
4312 TemChar = *StringPtr;\r
4313 *StringPtr = '\0';\r
4314 AppendToMultiString(Config, ConfigRequest);\r
4315 *StringPtr = TemChar;\r
93e3992d 4316\r
4317 //\r
4318 // Parse each <RequestElement> if exists\r
4319 // Only <BlockName> format is supported by this help function.\r
4320 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
4321 //\r
4322 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
4323 //\r
4324 // Back up the header of one <BlockName>\r
4325 //\r
4326 TmpPtr = StringPtr;\r
4327\r
4328 StringPtr += StrLen (L"OFFSET=");\r
4329 //\r
4330 // Get Offset\r
4331 //\r
4332 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4333 if (EFI_ERROR (Status)) {\r
93e3992d 4334 *Progress = ConfigRequest;\r
4335 goto Exit;\r
4336 }\r
4337 Offset = 0;\r
4338 CopyMem (\r
4339 &Offset,\r
4340 TmpBuffer,\r
4341 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4342 );\r
676df92c 4343 FreePool (TmpBuffer);\r
93e3992d 4344\r
4345 StringPtr += Length;\r
4346 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
4347 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
4348 Status = EFI_INVALID_PARAMETER;\r
4349 goto Exit;\r
4350 }\r
4351 StringPtr += StrLen (L"&WIDTH=");\r
4352\r
4353 //\r
4354 // Get Width\r
4355 //\r
4356 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4357 if (EFI_ERROR (Status)) {\r
93e3992d 4358 *Progress = ConfigRequest;\r
4359 goto Exit;\r
4360 }\r
4361 Width = 0;\r
4362 CopyMem (\r
4363 &Width,\r
4364 TmpBuffer,\r
4365 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4366 );\r
676df92c 4367 FreePool (TmpBuffer);\r
93e3992d 4368\r
4369 StringPtr += Length;\r
4370 if (*StringPtr != 0 && *StringPtr != L'&') {\r
4371 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
4372 Status = EFI_INVALID_PARAMETER;\r
4373 goto Exit;\r
4374 }\r
4375\r
4376 //\r
4377 // Calculate Value and convert it to hex string.\r
4378 //\r
4379 if (Offset + Width > BlockSize) {\r
4380 *Progress = StringPtr;\r
4381 Status = EFI_DEVICE_ERROR;\r
4382 goto Exit;\r
4383 }\r
4384\r
4385 Value = (UINT8 *) AllocateZeroPool (Width);\r
4386 if (Value == NULL) {\r
4387 *Progress = ConfigRequest;\r
4388 Status = EFI_OUT_OF_RESOURCES;\r
4389 goto Exit;\r
4390 }\r
4391\r
4392 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
4393\r
4394 Length = Width * 2 + 1;\r
4395 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4396 if (ValueStr == NULL) {\r
4397 *Progress = ConfigRequest;\r
4398 Status = EFI_OUT_OF_RESOURCES;\r
4399 goto Exit;\r
4400 }\r
63d55bb9
LG
4401 \r
4402 TemString = ValueStr;\r
4403 TemBuffer = Value + Width - 1;\r
4404 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
4405 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
4406 }\r
813acf3a 4407\r
676df92c 4408 FreePool (Value);\r
93e3992d 4409 Value = NULL;\r
4410\r
4411 //\r
4412 // Build a ConfigElement\r
4413 //\r
4414 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
4415 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4416 if (ConfigElement == NULL) {\r
4417 Status = EFI_OUT_OF_RESOURCES;\r
4418 goto Exit;\r
4419 }\r
4420 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
4421 if (*StringPtr == 0) {\r
4422 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
4423 }\r
4424 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
4425 StrCat (ConfigElement, L"VALUE=");\r
4426 StrCat (ConfigElement, ValueStr);\r
4427\r
4428 AppendToMultiString (Config, ConfigElement);\r
4429\r
676df92c 4430 FreePool (ConfigElement);\r
4431 FreePool (ValueStr);\r
93e3992d 4432 ConfigElement = NULL;\r
4433 ValueStr = NULL;\r
4434\r
4435 //\r
4436 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
4437 //\r
4438 if (*StringPtr == 0) {\r
4439 break;\r
4440 }\r
4441 AppendToMultiString (Config, L"&");\r
4442 StringPtr++;\r
4443\r
4444 }\r
4445\r
4446 if (*StringPtr != 0) {\r
4447 *Progress = StringPtr - 1;\r
4448 Status = EFI_INVALID_PARAMETER;\r
4449 goto Exit;\r
4450 }\r
84f9a9ec
LG
4451 \r
4452 HiiToLower (*Config);\r
93e3992d 4453 *Progress = StringPtr;\r
4454 return EFI_SUCCESS;\r
4455\r
4456Exit:\r
76c24251 4457 if (*Config != NULL) {\r
1f1cb2f2
LG
4458 FreePool (*Config);\r
4459 *Config = NULL;\r
76c24251 4460 }\r
676df92c 4461 if (ValueStr != NULL) {\r
4462 FreePool (ValueStr);\r
4463 }\r
4464 if (Value != NULL) {\r
4465 FreePool (Value);\r
4466 }\r
69367b5b 4467 if (ConfigElement != NULL) {\r
676df92c 4468 FreePool (ConfigElement);\r
4469 }\r
93e3992d 4470\r
4471 return Status;\r
4472\r
4473}\r
4474\r
4475\r
4476/**\r
4477 This helper function is to be called by drivers to map configuration strings\r
4478 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
4479\r
4480 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4481 instance.\r
4482 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
771ececd 4483 format.\r
93e3992d 4484 @param Block A possibly null array of bytes representing the\r
4485 current block. Only bytes referenced in the\r
4486 ConfigResp string in the block are modified. If\r
4487 this parameter is null or if the *BlockSize\r
4488 parameter is (on input) shorter than required by\r
4489 the Configuration string, only the BlockSize\r
4490 parameter is updated and an appropriate status\r
4491 (see below) is returned.\r
4492 @param BlockSize The length of the Block in units of UINT8. On\r
4493 input, this is the size of the Block. On output,\r
4494 if successful, contains the index of the last\r
4495 modified byte in the Block.\r
4496 @param Progress On return, points to an element of the ConfigResp\r
4497 string filled in with the offset of the most\r
4498 recent '&' before the first failing name / value\r
4499 pair (or the beginning of the string if the\r
4500 failure is in the first name / value pair) or the\r
4501 terminating NULL if all was successful.\r
4502\r
4503 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4504 terminator at the end of the ConfigResp string.\r
4505 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4506 points to the first character of ConfigResp.\r
4507 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
4508 Block parameter would result in this type of\r
4509 error. Progress points to the first character of\r
4510 ConfigResp.\r
4511 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
4512 value pair. Block is left updated and\r
4513 Progress points at the '&' preceding the first\r
4514 non-<BlockName>.\r
09b79417
LG
4515 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
4516 @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
4517 Progress points to the "G" in "GUID" of the errant\r
4518 routing data.\r
93e3992d 4519\r
4520**/\r
4521EFI_STATUS\r
4522EFIAPI\r
4523HiiConfigToBlock (\r
4524 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4525 IN CONST EFI_STRING ConfigResp,\r
4526 IN OUT UINT8 *Block,\r
4527 IN OUT UINTN *BlockSize,\r
4528 OUT EFI_STRING *Progress\r
4529 )\r
4530{\r
4531 HII_DATABASE_PRIVATE_DATA *Private;\r
4532 EFI_STRING StringPtr;\r
4533 UINTN Length;\r
4534 EFI_STATUS Status;\r
4535 UINT8 *TmpBuffer;\r
4536 UINTN Offset;\r
4537 UINTN Width;\r
4538 UINT8 *Value;\r
4539 UINTN BufferSize;\r
09b79417 4540 UINTN MaxBlockSize;\r
93e3992d 4541\r
4542 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
4543 return EFI_INVALID_PARAMETER;\r
4544 }\r
4545\r
09b79417
LG
4546 *Progress = ConfigResp;\r
4547 if (ConfigResp == NULL) {\r
93e3992d 4548 return EFI_INVALID_PARAMETER;\r
4549 }\r
4550\r
4551 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4552 ASSERT (Private != NULL);\r
4553\r
4554 StringPtr = ConfigResp;\r
4555 BufferSize = *BlockSize;\r
4556 Value = NULL;\r
09b79417 4557 MaxBlockSize = 0;\r
93e3992d 4558\r
4559 //\r
4560 // Jump <ConfigHdr>\r
4561 //\r
4562 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4563 *Progress = StringPtr;\r
4564 Status = EFI_INVALID_PARAMETER;\r
4565 goto Exit;\r
4566 }\r
4567 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4568 StringPtr++;\r
4569 }\r
4570 if (*StringPtr == 0) {\r
4571 *Progress = StringPtr;\r
4572 Status = EFI_INVALID_PARAMETER;\r
4573 goto Exit;\r
4574 }\r
08e6463a 4575\r
4576 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4577 StringPtr++;\r
4578 }\r
4579 if (*StringPtr == 0) {\r
4580 *Progress = StringPtr;\r
4581 Status = EFI_INVALID_PARAMETER;\r
4582 goto Exit;\r
4583 }\r
93e3992d 4584\r
4585 //\r
4586 // Parse each <ConfigElement> if exists\r
edae8d2d 4587 // Only '&'<BlockConfig> format is supported by this help function.\r
93e3992d 4588 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
4589 //\r
edae8d2d
ED
4590 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
4591 StringPtr += StrLen (L"&OFFSET=");\r
93e3992d 4592 //\r
4593 // Get Offset\r
4594 //\r
4595 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 4596 if (EFI_ERROR (Status)) {\r
93e3992d 4597 *Progress = ConfigResp;\r
4598 goto Exit;\r
4599 }\r
4600 Offset = 0;\r
4601 CopyMem (\r
4602 &Offset,\r
4603 TmpBuffer,\r
4604 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4605 );\r
676df92c 4606 FreePool (TmpBuffer);\r
93e3992d 4607\r
4608 StringPtr += Length;\r
4609 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
edae8d2d 4610 *Progress = StringPtr - Length - StrLen (L"&OFFSET=");\r
93e3992d 4611 Status = EFI_INVALID_PARAMETER;\r
4612 goto Exit;\r
4613 }\r
4614 StringPtr += StrLen (L"&WIDTH=");\r
4615\r
4616 //\r
4617 // Get Width\r
4618 //\r
4619 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4620 if (EFI_ERROR (Status)) {\r
93e3992d 4621 *Progress = ConfigResp;\r
4622 goto Exit;\r
4623 }\r
4624 Width = 0;\r
4625 CopyMem (\r
4626 &Width,\r
4627 TmpBuffer,\r
4628 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4629 );\r
676df92c 4630 FreePool (TmpBuffer);\r
93e3992d 4631\r
4632 StringPtr += Length;\r
4633 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
4634 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
4635 Status = EFI_INVALID_PARAMETER;\r
4636 goto Exit;\r
4637 }\r
4638 StringPtr += StrLen (L"&VALUE=");\r
4639\r
4640 //\r
4641 // Get Value\r
4642 //\r
4643 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 4644 if (EFI_ERROR (Status)) {\r
93e3992d 4645 *Progress = ConfigResp;\r
4646 goto Exit;\r
4647 }\r
4648\r
4649 StringPtr += Length;\r
4650 if (*StringPtr != 0 && *StringPtr != L'&') {\r
edae8d2d 4651 *Progress = StringPtr - Length - StrLen (L"&VALUE=");\r
93e3992d 4652 Status = EFI_INVALID_PARAMETER;\r
4653 goto Exit;\r
4654 }\r
4655\r
4656 //\r
4657 // Update the Block with configuration info\r
4658 //\r
09b79417
LG
4659 if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
4660 CopyMem (Block + Offset, Value, Width);\r
4661 }\r
4662 if (Offset + Width > MaxBlockSize) {\r
4663 MaxBlockSize = Offset + Width;\r
93e3992d 4664 }\r
93e3992d 4665\r
676df92c 4666 FreePool (Value);\r
93e3992d 4667 Value = NULL;\r
4668\r
4669 //\r
edae8d2d 4670 // If '\0', parsing is finished.\r
93e3992d 4671 //\r
4672 if (*StringPtr == 0) {\r
4673 break;\r
4674 }\r
93e3992d 4675 }\r
84f9a9ec
LG
4676 \r
4677 //\r
edae8d2d 4678 // The input string is not ConfigResp format, return error.\r
84f9a9ec 4679 //\r
edae8d2d
ED
4680 if (*StringPtr != 0) {\r
4681 *Progress = StringPtr;\r
93e3992d 4682 Status = EFI_INVALID_PARAMETER;\r
4683 goto Exit;\r
4684 }\r
4685\r
6e3f5b2a 4686 *Progress = StringPtr + StrLen (StringPtr);\r
09b79417
LG
4687 *BlockSize = MaxBlockSize - 1;\r
4688\r
4689 if (MaxBlockSize > BufferSize) {\r
4690 *BlockSize = MaxBlockSize;\r
9ac0640d 4691 if (Block != NULL) {\r
09b79417
LG
4692 return EFI_DEVICE_ERROR;\r
4693 }\r
4694 }\r
4695\r
9ac0640d
LG
4696 if (Block == NULL) {\r
4697 *Progress = ConfigResp;\r
4698 return EFI_INVALID_PARAMETER;\r
4699 }\r
4700\r
93e3992d 4701 return EFI_SUCCESS;\r
4702\r
4703Exit:\r
4704\r
676df92c 4705 if (Value != NULL) {\r
4706 FreePool (Value);\r
4707 }\r
93e3992d 4708 return Status;\r
4709}\r
4710\r
4711\r
4712/**\r
4713 This helper function is to be called by drivers to extract portions of\r
4714 a larger configuration string.\r
4715\r
4716 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4717 instance.\r
4718 @param Configuration A null-terminated Unicode string in\r
771ececd 4719 <MultiConfigAltResp> format.\r
93e3992d 4720 @param Guid A pointer to the GUID value to search for in the\r
4721 routing portion of the ConfigResp string when\r
4722 retrieving the requested data. If Guid is NULL,\r
4723 then all GUID values will be searched for.\r
4724 @param Name A pointer to the NAME value to search for in the\r
4725 routing portion of the ConfigResp string when\r
4726 retrieving the requested data. If Name is NULL,\r
4727 then all Name values will be searched for.\r
4728 @param DevicePath A pointer to the PATH value to search for in the\r
4729 routing portion of the ConfigResp string when\r
4730 retrieving the requested data. If DevicePath is\r
4731 NULL, then all DevicePath values will be searched\r
4732 for.\r
4733 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
4734 routing portion of the ConfigResp string when\r
4735 retrieving the requested data. If this parameter\r
4736 is NULL, then the current setting will be\r
4737 retrieved.\r
4738 @param AltCfgResp A pointer to a buffer which will be allocated by\r
4739 the function which contains the retrieved string\r
4740 as requested. This buffer is only allocated if\r
84f9a9ec 4741 the call was successful. It is <ConfigResp> format.\r
93e3992d 4742\r
4743 @retval EFI_SUCCESS The request succeeded. The requested data was\r
4744 extracted and placed in the newly allocated\r
4745 AltCfgResp buffer.\r
4746 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
4747 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
4748 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
4749 found.\r
4750\r
4751**/\r
4752EFI_STATUS\r
4753EFIAPI\r
4754HiiGetAltCfg (\r
4755 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4756 IN CONST EFI_STRING Configuration,\r
4757 IN CONST EFI_GUID *Guid,\r
4758 IN CONST EFI_STRING Name,\r
4759 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
4760 IN CONST UINT16 *AltCfgId,\r
4761 OUT EFI_STRING *AltCfgResp\r
4762 )\r
4763{\r
93e3992d 4764 EFI_STATUS Status;\r
4765 EFI_STRING StringPtr;\r
e90b081a 4766 EFI_STRING HdrStart;\r
4767 EFI_STRING HdrEnd;\r
93e3992d 4768 EFI_STRING TmpPtr;\r
4769 UINTN Length;\r
e90b081a 4770 EFI_STRING GuidStr;\r
4771 EFI_STRING NameStr;\r
4772 EFI_STRING PathStr;\r
4773 EFI_STRING AltIdStr;\r
4774 EFI_STRING Result;\r
4775 BOOLEAN GuidFlag;\r
4776 BOOLEAN NameFlag;\r
4777 BOOLEAN PathFlag;\r
4778\r
4779 HdrStart = NULL;\r
4780 HdrEnd = NULL;\r
4781 GuidStr = NULL;\r
4782 NameStr = NULL;\r
4783 PathStr = NULL;\r
4784 AltIdStr = NULL;\r
4785 Result = NULL;\r
4786 GuidFlag = FALSE;\r
4787 NameFlag = FALSE;\r
4788 PathFlag = FALSE;\r
93e3992d 4789\r
4790 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
4791 return EFI_INVALID_PARAMETER;\r
4792 }\r
4793\r
4794 StringPtr = Configuration;\r
4795 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4796 return EFI_INVALID_PARAMETER;\r
4797 }\r
4798\r
4799 //\r
4800 // Generate the sub string for later matching.\r
4801 //\r
813acf3a 4802 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 4803 GenerateSubStr (\r
4804 L"PATH=",\r
4805 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 4806 (VOID *) DevicePath,\r
4807 1,\r
93e3992d 4808 &PathStr\r
4809 );\r
4810 if (AltCfgId != NULL) {\r
813acf3a 4811 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 4812 }\r
4813 if (Name != NULL) {\r
813acf3a 4814 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 4815 } else {\r
813acf3a 4816 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 4817 }\r
4818\r
4819 while (*StringPtr != 0) {\r
4820 //\r
4821 // Try to match the GUID\r
4822 //\r
4823 if (!GuidFlag) {\r
4824 TmpPtr = StrStr (StringPtr, GuidStr);\r
4825 if (TmpPtr == NULL) {\r
4826 Status = EFI_NOT_FOUND;\r
4827 goto Exit;\r
4828 }\r
4829 HdrStart = TmpPtr;\r
4830\r
4831 //\r
4832 // Jump to <NameHdr>\r
4833 //\r
4834 if (Guid != NULL) {\r
4835 StringPtr = TmpPtr + StrLen (GuidStr);\r
4836 } else {\r
4837 StringPtr = StrStr (TmpPtr, L"NAME=");\r
4838 if (StringPtr == NULL) {\r
4839 Status = EFI_NOT_FOUND;\r
4840 goto Exit;\r
4841 }\r
4842 }\r
4843 GuidFlag = TRUE;\r
4844 }\r
4845\r
4846 //\r
4847 // Try to match the NAME\r
4848 //\r
4849 if (GuidFlag && !NameFlag) {\r
4850 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
4851 GuidFlag = FALSE;\r
4852 } else {\r
4853 //\r
4854 // Jump to <PathHdr>\r
4855 //\r
4856 if (Name != NULL) {\r
4857 StringPtr += StrLen (NameStr);\r
4858 } else {\r
4859 StringPtr = StrStr (StringPtr, L"PATH=");\r
4860 if (StringPtr == NULL) {\r
4861 Status = EFI_NOT_FOUND;\r
4862 goto Exit;\r
4863 }\r
4864 }\r
4865 NameFlag = TRUE;\r
4866 }\r
4867 }\r
4868\r
4869 //\r
4870 // Try to match the DevicePath\r
4871 //\r
4872 if (GuidFlag && NameFlag && !PathFlag) {\r
4873 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
4874 GuidFlag = FALSE;\r
4875 NameFlag = FALSE;\r
4876 } else {\r
4877 //\r
4878 // Jump to '&' before <DescHdr> or <ConfigBody>\r
4879 //\r
4880 if (DevicePath != NULL) {\r
4881 StringPtr += StrLen (PathStr);\r
4882 } else {\r
4883 StringPtr = StrStr (StringPtr, L"&");\r
4884 if (StringPtr == NULL) {\r
4885 Status = EFI_NOT_FOUND;\r
4886 goto Exit;\r
4887 }\r
84f9a9ec 4888 StringPtr ++;\r
93e3992d 4889 }\r
4890 PathFlag = TRUE;\r
84f9a9ec 4891 HdrEnd = StringPtr;\r
93e3992d 4892 }\r
4893 }\r
4894\r
4895 //\r
4896 // Try to match the AltCfgId\r
4897 //\r
4898 if (GuidFlag && NameFlag && PathFlag) {\r
4899 if (AltCfgId == NULL) {\r
4900 //\r
4901 // Return Current Setting when AltCfgId is NULL.\r
4902 //\r
4903 Status = OutputConfigBody (StringPtr, &Result);\r
4904 goto Exit;\r
4905 }\r
4906 //\r
4907 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
4908 //\r
4909 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
4910 GuidFlag = FALSE;\r
4911 NameFlag = FALSE;\r
4912 PathFlag = FALSE;\r
4913 } else {\r
84f9a9ec
LG
4914 //\r
4915 // Skip AltIdStr and &\r
4916 //\r
4917 StringPtr = StringPtr + StrLen (AltIdStr);\r
4918 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 4919 goto Exit;\r
4920 }\r
4921 }\r
4922 }\r
4923\r
4924 Status = EFI_NOT_FOUND;\r
4925\r
4926Exit:\r
76c24251 4927 *AltCfgResp = NULL;\r
bc166db3 4928 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 4929 //\r
4930 // Copy the <ConfigHdr> and <ConfigBody>\r
4931 //\r
84f9a9ec 4932 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 4933 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
4934 if (*AltCfgResp == NULL) {\r
4935 Status = EFI_OUT_OF_RESOURCES;\r
4936 } else {\r
4937 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
4938 StrCat (*AltCfgResp, Result);\r
4939 Status = EFI_SUCCESS;\r
4940 }\r
4941 }\r
4942\r
676df92c 4943 if (GuidStr != NULL) {\r
4944 FreePool (GuidStr);\r
4945 }\r
4946 if (NameStr != NULL) {\r
4947 FreePool (NameStr);\r
4948 }\r
4949 if (PathStr != NULL) {\r
4950 FreePool (PathStr);\r
4951 }\r
4952 if (AltIdStr != NULL) {\r
4953 FreePool (AltIdStr);\r
4954 }\r
4955 if (Result != NULL) {\r
4956 FreePool (Result);\r
4957 }\r
93e3992d 4958\r
4959 return Status;\r
4960\r
93e3992d 4961}\r
4962\r
36fe40c2 4963\r