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