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