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