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