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