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