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